Skip to content

Commit

Permalink
First pass at adding a language mode for elixir
Browse files Browse the repository at this point in the history
  • Loading branch information
jaresty committed Oct 11, 2024
1 parent 02db7ce commit b844e8c
Show file tree
Hide file tree
Showing 3 changed files with 208 additions and 0 deletions.
1 change: 1 addition & 0 deletions core/modes/language_modes.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"javascript": "js",
"javascriptreact": "jsx",
# "json": "json",
"elixir": "ex",
"kotlin": "kt",
"lua": "lua",
"markdown": "md",
Expand Down
161 changes: 161 additions & 0 deletions lang/elixir/elixir.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
from talon import Context, Module, actions, settings

ctx = Context()
mod = Module()
ctx.matches = r"""
code.language: elixir
"""

# Elixir keywords and constructs
ctx.lists["user.code_keyword"] = {
"def": "def ",
"def p": "defp ",
"do": "do ",
"end": "end",
"if": "if ",
"else": "else ",
"cond": "cond ",
"case": "case ",
"when": "when ",
"f n": "fn ",
"receive": "receive ",
"after": "after ",
"try": "try ",
"catch": "catch ",
"rescue": "rescue ",
"raise": "raise ",
"with": "with ",
"unless": "unless ",
"import": "import ",
"alias": "alias ",
"require": "require ",
"use": "use ",
}


@ctx.action_class("user")
class UserActions:
def code_comment_line_prefix():
actions.insert("# ")

def code_operator_lambda():
actions.auto_insert("->")

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

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

def code_operator_subtraction():
actions.auto_insert(" - ")

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

def code_operator_division():
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_greater_than_or_equal_to():
actions.auto_insert(" >= ")

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

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

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

def code_operator_or():
actions.auto_insert(" or ")

def code_self():
actions.auto_insert("self")

def code_insert_null():
actions.insert("nil")

def code_insert_is_null():
actions.insert(" == nil")

def code_insert_is_not_null():
actions.insert(" != nil")

def code_state_if():
actions.user.insert_between("if ", " do\nend")

def code_state_else_if():
actions.user.insert_between("else if ", " do\nend")

def code_state_else():
actions.insert("else\nend")
actions.key("enter")

def code_state_case():
actions.user.insert_between("case ", " do\nend")

def code_state_for():
actions.user.insert_between("for ", " do\nend")

def code_state_while():
actions.user.insert_between("while ", " do\nend")

def code_define_class():
# Elixir doesn't have classes, so this is not applicable
pass

def code_state_return():
# Elixir functions automatically return the last evaluated expression
pass

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

def code_default_function(text: str):
result = "def {}".format(
actions.user.formatted_text(
text, settings.get("user.code_protected_function_formatter")
)
)
actions.user.code_insert_function(result, None)

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

def code_private_function(text: str):
"""Inserts private function declaration"""
result = "defp {}".format(
actions.user.formatted_text(
text, settings.get("user.code_private_function_formatter")
)
)
actions.user.code_insert_function(result, None)

def code_import_module(text: str):
actions.auto_insert("import ")
actions.insert(text)

def code_alias_module(text: str):
actions.auto_insert("alias ")
actions.insert(text)

def code_require_module(text: str):
actions.auto_insert("require ")
actions.insert(text)

def code_use_module(text: str):
actions.auto_insert("use ")
actions.insert(text)
46 changes: 46 additions & 0 deletions lang/elixir/elixir.talon
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
code.language: elixir
-
tag(): user.code_functional
tag(): user.code_concurrent

tag(): user.code_comment_line
tag(): user.code_data_bool
tag(): user.code_data_null
tag(): user.code_functions
tag(): user.code_keywords
tag(): user.code_libraries
tag(): user.code_operators_array
tag(): user.code_operators_assignment
tag(): user.code_operators_math
tag(): user.code_operators_lambda

settings():
user.code_private_function_formatter = "snake_case"
user.code_public_function_formatter = "snake_case"
user.code_private_variable_formatter = "snake_case"
user.code_public_variable_formatter = "snake_case"

# Elixir-specific grammars
state def: "def "
state defp: "defp "
state if: "if "
state else: "else"
state case: "case "
state cond: "cond do"
state try: "try do"
state rescue: "rescue"
state after: "after"
state end: "end"

# Elixir-specific keywords and symbols
true: "true"
false: "false"
nil: "nil"

[state] raise {user.elixir_exception}:
user.insert_between("raise ", "")

[state] rescue {user.elixir_exception}: "rescue {elixir_exception}"

comment line: user.code_comment_line_prefix()
comment block: user.code_comment_block_prefix()

0 comments on commit b844e8c

Please sign in to comment.