Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

stata support #1401

Merged
merged 14 commits into from
Jun 6, 2024
Merged
12 changes: 12 additions & 0 deletions apps/stata/stata.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
from talon import Context

ctx = Context()
ctx.matches = r"""
app: stata
"""


@ctx.action_class("code")
class CodeActions:
def language():
return "stata"
7 changes: 7 additions & 0 deletions apps/stata/stata.talon
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Commands for the Stata Do-File Editor
os: windows
app: stata
fidgetingbits marked this conversation as resolved.
Show resolved Hide resolved
-
settings():
key_wait = 4
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what's the deal with these delays out of curiosity? is the Stata editor particularly slow on windows? I think it's ok unless someone complains eventually, but since there is another issue in this file I figured I'd ask.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right, these do not seem to be strictly necessary for the pull request. I believe I added them because I have some extra commands for stata that may run into trouble otherwise. Since these are not part of the pull request, there is no need for the file at all.

I would suggest to keep calling the other file "stata_do_file_editor" because those commands target the "Do-File Editor" of Stata's IDE, not the command window/terminal. The Stata IDE is similar to R Studio or Spyder for python.

insert_wait = 7
25 changes: 25 additions & 0 deletions apps/stata/stata_do_file_editor.talon
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Commands for the Stata Do-File Editor
os: windows
app: stata
fidgetingbits marked this conversation as resolved.
Show resolved Hide resolved
win.title: Do-file Editor
-
do this: key(ctrl-d)

do line:
edit.select_line()
key(ctrl-d)

do (all | file):
edit.select_all()
edit.copy()
key(ctrl-d)

do way up:
edit.extend_file_start()
edit.copy()
key(ctrl-d)

do way down:
edit.extend_file_end()
edit.copy()
key(ctrl-d)
1 change: 1 addition & 0 deletions core/modes/language_modes.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
"scss": "scss",
# 'snippets': 'snippets',
"sql": "sql",
"stata": "do ado",
"talon": "talon",
"talonlist": "talon-list",
"terraform": "tf",
Expand Down
157 changes: 157 additions & 0 deletions lang/stata/stata.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
from talon import Context, actions, settings

ctx = Context()

ctx.matches = r"""
code.language: stata
"""

# functions.py
ctx.lists["user.code_parameter_name"] = {
# regressions
"V C E cluster": "vce(cluster)",
"V C E robust": "vce(robust)",
}

# functions_common.py
ctx.lists["user.code_common_function"] = {
# base stata
"global": "global",
"local": "local",
"reg": "reg",
"regress": "reg",
# packages
"estadd": "estadd",
maxbruening marked this conversation as resolved.
Show resolved Hide resolved
"estout": "estout",
"estpost": "estpost",
"eststo": "eststo",
"esttab": "esttab",
}

# libraries_gui.py
ctx.lists["user.code_libraries"] = {
"estout": "estout",
}


@ctx.action_class("user")
class UserActions:
# comment_line.py
def code_comment_line_prefix():
actions.auto_insert("* ")

# functions.py
def code_private_function(text: str):
result = "program {} \n\nend".format(
actions.user.formatted_text(
text, settings.get("user.code_private_function_formatter")
)
)
actions.user.paste(result)
actions.edit.up()
actions.key("tab")

def code_default_function(text: str):
actions.user.code_private_function(text)

def code_insert_named_argument(parameter_name: str):
actions.insert(f"{parameter_name} ")

# functions_common.py
def code_insert_function(text: str, selection: str):
text += f" {selection or ''}"
actions.user.paste(text)

# imperative.py
def code_block():
actions.auto_insert("\n")

def code_state_if():
actions.insert("if {\n\n}\n")
actions.key("up:2 tab up left")

def code_state_else_if():
actions.insert("else if {\n\n}\n")
actions.key("up:2 tab up right:4")

def code_state_else():
actions.insert("else {\n\n}\n")
actions.key("up:2 tab")

def code_state_for():
actions.insert("forval {\n\n}\n")
actions.key("up:2 tab up right:3")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is it possible people would/could configure the stada app to not use 4 space tabs? if so I guess this would break. same goes for the other spots you added tab

Copy link
Contributor Author

@maxbruening maxbruening Jun 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Per default stata inserts 4 spaces per tab. However, this can be configured in the editor. But I guess if someone configured this, talon actually does press tab and this would insert the modified number of spaces, correct?

I would say that most people use the stata IDE to code in stata. if they used another editor, they could modify the editor behavior?

What would be the alternative? Not adding the tab? \t?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ya, that's my worry if someone configures it differently than the default then it will be wrong. I think the only option is to just manually press the keys unfortunately, which will be a bit slower for the user, but at least correct. I believe \t will be the same as pressing tab.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, Now I understand. Will make these changes either tonight or tomorrow.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have made the according changes. The code should now be robust to how many spaces are defined as a tab.

However, if one works in an editor with auto closing brackets on, one would still run into problems. But I guess this affects all languages in talon. one could create something like context sensitive dictation I guess. But this goes beyond the scope of this pull request.


def code_state_for_each():
actions.insert("foreach in {\n\n}\n")
actions.key("up:2 tab up right:4")

def code_state_while():
actions.insert("while {\n\n}\n")
actions.key("up:2 tab up right:2")

def code_break():
actions.insert("break")

def code_next():
actions.insert("continue")

# libraries.py
def code_import():
actions.auto_insert("ssc install ")

# libraries_gui.py
def code_insert_library(text: str, selection: str):
actions.auto_insert("ssc install ")
actions.user.paste(text + selection)

# operators_array.py
def code_operator_subscript():
actions.user.insert_between("[", "]")

# operators_assignment.py
def code_operator_assignment():
actions.auto_insert(" = ")

# operators_math.py
def code_operator_subtraction():
actions.auto_insert(" - ")

def code_operator_addition():
actions.auto_insert(" + ")

def code_operator_multiplication():
actions.auto_insert(" * ")

def code_operator_division():
actions.auto_insert(" / ")

def code_operator_modulo():
actions.user.insert_between("mod(", ")")

def code_operator_exponent():
actions.auto_insert(" ^ ")

def code_operator_equal():
actions.auto_insert(" == ")

def code_operator_not_equal():
actions.auto_insert(" != ")

def code_operator_greater_than():
actions.auto_insert(" > ")

def code_operator_less_than():
actions.auto_insert(" < ")

def code_operator_greater_than_or_equal_to():
actions.auto_insert(" >= ")

def code_operator_less_than_or_equal_to():
actions.auto_insert(" <= ")

def code_operator_and():
actions.auto_insert(" & ")

def code_operator_or():
actions.auto_insert(" | ")
28 changes: 28 additions & 0 deletions lang/stata/stata.talon
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
code.language: stata
-
tag(): user.code_imperative

tag(): user.code_comment_block_c_like
tag(): user.code_comment_block
tag(): user.code_comment_line
tag(): user.code_functions
tag(): user.code_functions_common
tag(): user.code_libraries
tag(): user.code_libraries_gui
tag(): user.code_operators_array
tag(): user.code_operators_assignment

settings():
user.code_private_function_formatter = "SNAKE_CASE"

arg {user.code_parameter_name}: user.code_insert_named_argument(code_parameter_name)

state for val: user.code_state_for()

# alternative to saying ""state import""
s s c install: user.code_import()

s s c install <user.code_libraries>: user.code_insert_library(code_libraries, "")

toggle imports: user.code_toggle_libraries()
toggle packages: user.code_toggle_libraries()