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

Migrate language modes to CSV #1528

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
04cf66f
Start on three column CSV handling code
FireChickenProductivity Jul 30, 2024
7bad13a
Draft parsing the file
FireChickenProductivity Jul 30, 2024
2817402
Add parsing intermediate value parsing
FireChickenProductivity Jul 30, 2024
ea9e81f
Draft unification function
FireChickenProductivity Jul 31, 2024
be4aa56
Improve naming
FireChickenProductivity Jul 31, 2024
7fa6e0b
Finish drafting file handling
FireChickenProductivity Jul 31, 2024
d005db0
Fix syntax
FireChickenProductivity Jul 31, 2024
e4fd3f0
Make some minor fixes
FireChickenProductivity Jul 31, 2024
f430655
Stop using deprecated function
FireChickenProductivity Jul 31, 2024
70c2eab
Handle different tuple sizes
FireChickenProductivity Jul 31, 2024
3f1fd5e
Remove accidental character
FireChickenProductivity Jul 31, 2024
b7e8b9e
Make name less confusing
FireChickenProductivity Jul 31, 2024
9ebff4c
Watch file
FireChickenProductivity Jul 31, 2024
f37298d
Draft refactoring of language modes
FireChickenProductivity Aug 1, 2024
76a9df6
Correctly use name, fix single item tuples
FireChickenProductivity Aug 2, 2024
a8d0a96
Make sure file exists before loading as a resource
FireChickenProductivity Aug 2, 2024
e2d4c91
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 3, 2024
c98009a
Add missing defaults
FireChickenProductivity Aug 5, 2024
88f816c
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 5, 2024
d81ebd5
Properly handle new lines
FireChickenProductivity Aug 5, 2024
79a9cac
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 5, 2024
10bd11b
Strip text for values
FireChickenProductivity Aug 5, 2024
000fb40
Theoretically address issues brought up in community meeting
FireChickenProductivity Aug 10, 2024
e46d3eb
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 10, 2024
fc201b8
Document more of the change
FireChickenProductivity Aug 10, 2024
4275392
Declare globals first
FireChickenProductivity Aug 10, 2024
94c16a7
Update edit_text_file.py
nriley Aug 10, 2024
91d9a3e
Merge branch 'main' into migrate-language-modes
nriley Aug 10, 2024
cb26c99
Add callback
FireChickenProductivity Aug 11, 2024
3d55c2c
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 11, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
August 10 2024: The language modes (that keep track of programming language names, corresponding extensions, and spoken forms) have been migrated to a CSV file. If you have made changes directly to the language_modes.py file to customize that information, you can migrate your changes by letting the new community code run to generate the CSV file and then editing it. Items within the same column can be separated by semicolons if you want to have multiple spoken forms or file extensions associated with the same language.
1 change: 1 addition & 0 deletions core/edit_text_file.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"alphabet": "alphabet.csv",
"directories": "directories.csv",
"file extensions": "file_extensions.csv",
"language modes": "language_modes.csv",
"search engines": "search_engines.csv",
"system paths": "system_paths.csv",
"unix utilities": "unix_utilities.csv",
Expand Down
249 changes: 174 additions & 75 deletions core/modes/language_modes.py
Original file line number Diff line number Diff line change
@@ -1,65 +1,13 @@
from talon import Context, Module, actions

# Maps language mode names to the extensions that activate them. Only put things
# here which have a supported language mode; that's why there are so many
# commented out entries. TODO: make this a csv file?
language_extensions = {
# 'assembly': 'asm s',
# 'bash': 'bashbook sh',
"batch": "bat",
"c": "c h",
# 'cmake': 'cmake',
# "cplusplus": "cpp hpp",
"csharp": "cs",
"css": "css",
# 'elisp': 'el',
# 'elm': 'elm',
"gdb": "gdb",
"go": "go",
"java": "java",
"javascript": "js",
"javascriptreact": "jsx",
# "json": "json",
"kotlin": "kt",
"lua": "lua",
"markdown": "md",
# 'perl': 'pl',
"php": "php",
# 'powershell': 'ps1',
"python": "py",
"protobuf": "proto",
"r": "r",
# 'racket': 'rkt',
"ruby": "rb",
"rust": "rs",
"scala": "scala",
"scss": "scss",
# 'snippets': 'snippets',
"sql": "sql",
"stata": "do ado",
"talon": "talon",
"talonlist": "talon-list",
"terraform": "tf",
"tex": "tex",
"typescript": "ts",
"typescriptreact": "tsx",
# 'vba': 'vba',
"vimscript": "vim vimrc",
# html doesn't actually have a language mode, but we do have snippets.
"html": "html",
}

# Override speakable forms for language modes. If not present, a language mode's
# name is used directly.
language_name_overrides = {
"cplusplus": ["see plus plus"],
"csharp": ["see sharp"],
"css": ["c s s"],
"gdb": ["g d b"],
"go": ["go", "go lang", "go language"],
"r": ["are language"],
"tex": ["tech", "lay tech", "latex"],
}
from typing import Callable

from talon import Context, Module, actions, resource

from ..user_settings import (
compute_csv_path,
compute_spoken_form_to_key_dictionary,
create_three_columns_csv_from_default_if_nonexistent,
get_key_value_pairs_and_spoken_forms_from_three_column_csv,
)
nriley marked this conversation as resolved.
Show resolved Hide resolved

mod = Module()

Expand All @@ -74,20 +22,165 @@
mod.tag("code_language_forced", "This tag is active when a language mode is forced")
mod.list("language_mode", desc="Name of a programming language mode.")

ctx.lists["self.language_mode"] = {
name: language
for language in language_extensions
for name in language_name_overrides.get(language, [language])
}

# Maps extension to languages.
extension_lang_map = {
"." + ext: language
for language, extensions in language_extensions.items()
for ext in extensions.split()
}

language_ids = set(language_extensions.keys())
extension_lang_map = None

language_ids = None
language_extensions = None

SETTINGS_FILENAME = "language_modes.csv"
settings_filepath = compute_csv_path(SETTINGS_FILENAME)

LANGUAGE_HEADERS = ["language", "extensions", "spoken_forms"]

language_mode_update_callbacks = {}


def make_sure_settings_file_exists():
# Maps language mode names to the extensions that activate them and language spoken forms. Only put things
# here which have a supported language mode or snippets; that's why there are so many
# commented out entries.
default_csv_contents = [
# ['assembly', ('asm', 's'),],
# ['bash', ('bashbook', 'sh'),],
[
"batch",
("bat",),
],
[
"c",
("c", "h"),
],
# ['cmake', ('cmake',),],
# ["cplusplus", ("cpp hpp",), ("see plus plus",)],
["csharp", ("cs",), ("see sharp",)],
["css", ("css",), ("c s s",)],
# ['elisp', ('el'),],
# ['elm', ('elm'),],
["gdb", ("gdb",), ("g d b",)],
["go", ("go",), ("go", "go lang", "go language")],
["java", ("java",)],
["javascript", ("js",)],
["javascriptreact", ("jsx",)],
# ["json", ("json",),],
[
"kotlin",
("kt",),
],
[
"lua",
("lua",),
],
[
"markdown",
("md",),
],
# ['perl', ('pl',),],
[
"php",
("php",),
],
# ['powershell', ('ps1',),],
[
"python",
("py",),
],
[
"protobuf",
("proto",),
],
["r", ("r"), ("are language",)],
# ['racket', ('rkt,'),],
[
"ruby",
("rb",),
],
[
"rust",
("rs",),
],
[
"scala",
("scala",),
],
[
"scss",
("scss",),
],
# ['snippets', ('snippets',),],
[
"sql",
("sql",),
],
[
"stata",
("do", "ado"),
],
[
"talon",
("talon",),
],
[
"talonlist",
("talon-list",),
],
[
"terraform",
("tf",),
],
["tex", ("tex",), ("tech", "lay tech", "latex")],
[
"typescript",
("ts",),
],
[
"typescriptreact",
("tsx",),
],
# ['vba', ('vba',),],
[
"vimscript",
("vim", "vimrc"),
],
# html doesn't actually have a language mode, but we do have snippets.
[
"html",
("html",),
],
]
create_three_columns_csv_from_default_if_nonexistent(
SETTINGS_FILENAME, LANGUAGE_HEADERS, default_csv_contents
)


make_sure_settings_file_exists()


@resource.watch(settings_filepath)
Copy link
Collaborator

Choose a reason for hiding this comment

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

How does this handle if the file doesn't exist?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Last time I tested the code, it created the file if it did not exist.

def load_language_modes(path: str):
global language_extensions, extension_lang_map, language_ids
make_sure_settings_file_exists()
language_extensions, language_spoken_forms = (
get_key_value_pairs_and_spoken_forms_from_three_column_csv(
SETTINGS_FILENAME,
LANGUAGE_HEADERS,
)
)
ctx.lists["self.language_mode"] = compute_spoken_form_to_key_dictionary(
language_extensions, language_spoken_forms
)
extension_lang_map = {
"." + ext: language
for language, extensions in language_extensions.items()
for ext in extensions
}
language_ids = set(language_extensions.keys())

for callback in language_mode_update_callbacks.values():
callback()


load_language_modes(settings_filepath)

forced_language = ""

Expand Down Expand Up @@ -122,3 +215,9 @@ def code_clear_language_mode():
global forced_language
forced_language = ""
ctx.tags = []

def register_language_mode_on_update_callback(
name: str, callback: Callable[[], None]
):
"""Registers a callback to be called when the language mode csv is updated"""
language_mode_update_callbacks[name] = callback
37 changes: 27 additions & 10 deletions core/snippets/snippets.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,26 @@
desc="Directory (relative to Talon user) containing additional snippets",
)

context_map = {
# `_` represents the global context, ie snippets available regardless of language
"_": Context(),
}
snippets_map = {}
context_map = None


def create_context_map():
global context_map
context_map = {
# `_` represents the global context, ie snippets available regardless of language
"_": Context(),
}

# Create a context for each defined language
for lang in language_ids:
ctx = Context()
Copy link
Collaborator

Choose a reason for hiding this comment

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

If we decide to keep this implementation we definitely should check if the context already exists before creating a new one

ctx.matches = f"code.language: {lang}"
context_map[lang] = ctx


# Create a context for each defined language
for lang in language_ids:
ctx = Context()
ctx.matches = f"code.language: {lang}"
context_map[lang] = ctx
create_context_map()

snippets_map = {}


def get_setting_dir():
Expand Down Expand Up @@ -199,13 +208,21 @@ def create_lists(
return snippets_map, insertions, insertions_phrase, wrappers


def on_language_modes_update():
create_context_map()
update_snippets()


def on_ready():
fs.watch(str(SNIPPETS_DIR), lambda _1, _2: update_snippets())

if get_setting_dir():
fs.watch(str(get_setting_dir()), lambda _1, _2: update_snippets())

update_snippets()
actions.user.register_language_mode_on_update_callback(
"snippets", on_language_modes_update
)


app.register("ready", on_ready)
Loading