Skip to content

Commit

Permalink
Merge pull request #54 from michaelblyons/completions/python-import
Browse files Browse the repository at this point in the history
Python improvements
Remove the external script spawning Python processes
Make a class for the data object we keep passing around
Make the runnable Python files 755.
  • Loading branch information
axemonk authored Feb 10, 2025
2 parents 14d5721 + 5911207 commit 1f0642e
Show file tree
Hide file tree
Showing 14 changed files with 8,511 additions and 6,243 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
__pycache__/
*.pyc
4,608 changes: 4,096 additions & 512 deletions resources/completion_builder/.sublime-completions

Large diffs are not rendered by default.

54 changes: 54 additions & 0 deletions resources/completion_builder/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# Function completion builder

## Scripts

General operations performed by the scripts found in this directory:

### *main.py* Main
Runner script

### *js.py* JSON
Convert the function data found in `func_data_list.txt` to JSON, where each has:
- `func_name` (String)
- `req_param` (Array)
- `opt_param` (Array)
- `ellipsis` (Boolean)

### *cb.py* Completion Builder
Build out completion strings for param-having functions

### *ld.py* Load
Convert the function metadata found in *\*\_funcs\_ref.xlsx* to JSON

### *mg.py* Merge

1. Match completion strings to descriptions, categories, and function names.

2. Build out completion strings for nullary functions.
(Nullary functions are not included during the OCR which creates the
*\*\_data\_list\_raw.txt* file. Nullary functions are however included in
the *\*\_funcs\_ref.xlsx* file, so this is where they are managed.)

3. Remove `TRUE()` and `FALSE()` from consideration if present in
*\*\_funcs\_ref.xlsx*

4. Run all subscripts (if `toggle_rerun` is enabled) and build out entire
*.sublime-completions* file.


## Comments

- NOTE: Not all `ellipsis == True` functions follow the same format.

```
COUNTA~value1,[value2],...
COUNTIFS~criteria_range1,criteria1,...
```
Before running this script, clean formulas in *\*\_funcs\_data\_list.txt*
that look like the second line to look like the first, using your best
judgement. Find them using: `[^\]],\.{3}`
- TODO: Allow this entire directory to switch between application specific
information like the `scope` found in this file and the file names used by
all scripts instead of having to refactor a bunch of stuff every time.
111 changes: 111 additions & 0 deletions resources/completion_builder/SpreadsheetFunction.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
APP_SUFFIXES = [
'excel',
'google',
'libre',
]

class SpreadsheetFunction(object):
"""Metadata about a function for a spreadsheet application"""

def __init__(self, name: str, description: str = None, family: str = None,
required_args: list[str] = None,
optional_args: list[str] = None,
has_ellipsis: bool = False):
super(SpreadsheetFunction, self).__init__()
self.name = name
self.description = description
self.family = family
self.required_args = required_args
self.optional_args = optional_args
self.has_ellipsis = has_ellipsis

@staticmethod
def from_json(json_obj):
"""This is the temporary transfer format"""
return SpreadsheetFunction(
json_obj.get('func_name'),
description = json_obj.get('func_desc', None),
family = json_obj.get('func_cat', None),
required_args = json_obj.get('req_param', None),
optional_args = json_obj.get('opt_param', None),
has_ellipsis = json_obj.get('ellipsis', False),
)

def to_json(self) -> str:
"""This is the temporary transfer format"""
output = dict(
func_name = self.name,
func_cat = self.family,
func_desc = self.description,
is_nullary = not (self.required_args or self.optional_args),
comp_str = self.to_completion_arg_string(),
req_param = self.required_args,
opt_param = self.optional_args,
ellipsis = self.has_ellipsis,
)
return {k:output[k] for k in output if output[k] is not None}

def to_arg_list(self) -> list[str]:
args = []
if self.required_args:
args += self.required_args
if self.optional_args:
args += [f'[{a}]' for a in self.optional_args]
if self.has_ellipsis:
args += ['...']
return args

def to_arg_string(self) -> str:
return ', '.join(self.to_arg_list())

def to_completion_arg_string(self) -> str:
completions = []
param_id = 0

if self.required_args:
for req in self.required_args:
param_id += 1

if param_id > 1:
completions.append(',')
completions.append(f'${{{param_id}: {req}}}')
else:
completions.append(f'${{{param_id}:{req}}}')

if self.optional_args:
num_opt_param = len(self.optional_args)
num_param = num_opt_param + len(self.required_args or [])

# Wrap optional arguments in an extra tabstop
param_id += 1
completions.append(f'${{{param_id}:')

for opt in self.optional_args:
param_id += 1

if param_id == num_param + 1 and self.has_ellipsis:
completions.append(f',${{{param_id}: [{opt}], ...}}')
else:
completions.append(f',${{{param_id}: [{opt}]}}')

completions.append('}')

return f'{self.name}({"".join(completions)})'

def to_sublime_word_completion(self) -> dict[str,str]:
return {
"trigger": self.name,
"contents": self.name,
"annotation": self.family,
"details": self.description,
"kind": "function",
}

def to_sublime_snippet_completion(self) -> dict[str,str]:
return {
"trigger": self.name.lower(),
"contents": self.to_completion_arg_string(),
"annotation": self.family,
"details": self.description,
"kind": "snippet",
}
Empty file modified resources/completion_builder/cb.py
100644 → 100755
Empty file.
Empty file modified resources/completion_builder/cb_2.py
100644 → 100755
Empty file.
Loading

0 comments on commit 1f0642e

Please sign in to comment.