Skip to content

Commit

Permalink
Added the ability to generate community snippets
Browse files Browse the repository at this point in the history
  • Loading branch information
AndreasArvidsson committed Jan 21, 2025
1 parent 3d1447c commit 3754e88
Show file tree
Hide file tree
Showing 16 changed files with 778 additions and 263 deletions.
3 changes: 2 additions & 1 deletion cursorless-talon/src/actions/actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@

# Don't wait for these actions to finish, usually because they hang on some kind of user interaction
no_wait_actions = [
"generateSnippet",
"rename",
]

Expand Down Expand Up @@ -99,6 +98,8 @@ def cursorless_command(action_name: str, target: CursorlessExplicitTarget): # p
)
elif action_name == "callAsFunction":
actions.user.private_cursorless_call(target)
elif action_name == "generateSnippet":
actions.user.private_cursorless_generate_snippet_action(target)
elif action_name in no_wait_actions:
action = {"name": action_name, "target": target}
actions.user.private_cursorless_command_no_wait(action)
Expand Down
71 changes: 71 additions & 0 deletions cursorless-talon/src/actions/generate_snippet.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import glob
from pathlib import Path

from talon import Context, Module, actions, settings

from ..targets.target_types import CursorlessExplicitTarget

mod = Module()

ctx = Context()
ctx.matches = r"""
tag: user.cursorless_use_community_snippets
"""


@mod.action_class
class Actions:
def private_cursorless_generate_snippet_action(target: CursorlessExplicitTarget): # pyright: ignore [reportGeneralTypeIssues]
"""Generate a snippet from the given target"""
actions.user.private_cursorless_command_no_wait(
{
"name": "generateSnippet",
"target": target,
}
)


@ctx.action_class("user")
class UserActions:
def private_cursorless_generate_snippet_action(target: CursorlessExplicitTarget): # pyright: ignore [reportGeneralTypeIssues]
actions.user.private_cursorless_command_no_wait(
{
"name": "generateSnippet",
"target": target,
"dirPath": get_dir_path(),
}
)


def get_dir_path() -> str:
settings_dir = get_setting_dir()
if settings_dir is not None:
return settings_dir
return get_community_snippets_dir()


def get_setting_dir() -> str | None:
try:
setting_dir = settings.get("user.snippets_dir")
if not setting_dir:
return None

dir = Path(str(setting_dir))

if not dir.is_absolute():
user_dir = Path(actions.path.talon_user())
dir = user_dir / dir

return str(dir.resolve())
except Exception:
return None


def get_community_snippets_dir() -> str:
files = glob.iglob(
f"{actions.path.talon_user()}/**/snippets/snippets/*.snippet",
recursive=True,
)
for file in files:
return str(Path(file).parent)
raise ValueError("Could not find community snippets directory")
55 changes: 55 additions & 0 deletions data/fixtures/recorded/actions/snippets/snipMakeFunk2.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
languageId: typescript
command:
version: 7
spokenForm: snippet make funk
action:
name: generateSnippet
dirPath: ""
snippetName: snippetTest1
target:
type: primitive
modifiers:
- type: containingScope
scopeType: {type: namedFunction}
usePrePhraseSnapshot: true
spokenFormError: generateSnippet.snippetName
initialState:
documentContents: |2-
function helloWorld() {
const whatever = "hello";
if (whatever == null) {
console.log("hello")
}
}
selections:
- anchor: {line: 0, character: 13}
active: {line: 0, character: 23}
- anchor: {line: 3, character: 8}
active: {line: 5, character: 9}
marks: {}
finalState:
documentContents: |
name: snippetTest1
language: typescript
phrase:
$1.wrapperPhrase:
$0.wrapperPhrase:
-
function $1() {
const whatever = "hello";
$0
}
---
selections:
- anchor: {line: 2, character: 8}
active: {line: 2, character: 8}
thatMark:
- type: UntypedTarget
contentRange:
start: {line: 0, character: 4}
end: {line: 6, character: 5}
isReversed: false
hasExplicitRange: true
46 changes: 46 additions & 0 deletions data/fixtures/recorded/actions/snippets/snipMakeState2.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
languageId: typescript
command:
version: 7
spokenForm: snippet make state
action:
name: generateSnippet
dirPath: ""
snippetName: snippetTest1
target:
type: primitive
modifiers:
- type: containingScope
scopeType: {type: statement}
usePrePhraseSnapshot: true
spokenFormError: generateSnippet.snippetName
initialState:
documentContents: |-
if () {
console.log("hello")
}
selections:
- anchor: {line: 0, character: 4}
active: {line: 0, character: 4}
marks: {}
finalState:
documentContents: |
name: snippetTest1
language: typescript
phrase:
$0.wrapperPhrase:
-
if ($0) {
console.log("hello")
}
---
selections:
- anchor: {line: 2, character: 8}
active: {line: 2, character: 8}
thatMark:
- type: UntypedTarget
contentRange:
start: {line: 0, character: 0}
end: {line: 2, character: 1}
isReversed: false
hasExplicitRange: true
41 changes: 41 additions & 0 deletions data/fixtures/recorded/actions/snippets/testSnippetMakeLine2.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
languageId: plaintext
command:
version: 7
spokenForm: test snippet make line
action:
name: generateSnippet
dirPath: ""
snippetName: testSnippet
target:
type: primitive
modifiers:
- type: containingScope
scopeType: {type: line}
usePrePhraseSnapshot: true
spokenFormError: generateSnippet.snippetName
initialState:
documentContents: \textbf{$foo}
selections:
- anchor: {line: 0, character: 9}
active: {line: 0, character: 12}
marks: {}
finalState:
documentContents: |
name: testSnippet
language: plaintext
phrase:
$0.wrapperPhrase:
-
\textbf{\$$0}
---
selections:
- anchor: {line: 2, character: 8}
active: {line: 2, character: 8}
thatMark:
- type: UntypedTarget
contentRange:
start: {line: 0, character: 0}
end: {line: 0, character: 13}
isReversed: false
hasExplicitRange: true
1 change: 1 addition & 0 deletions packages/common/src/types/command/ActionDescriptor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ export interface PasteActionDescriptor {

export interface GenerateSnippetActionDescriptor {
name: "generateSnippet";
dirPath?: string;
snippetName?: string;
target: PartialTargetDescriptor;
}
Expand Down
1 change: 1 addition & 0 deletions packages/cursorless-engine/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
"lodash-es": "^4.17.21",
"moo": "0.5.2",
"nearley": "2.20.1",
"talon-snippets": "1.1.0",
"uuid": "^10.0.0",
"zod": "3.23.8"
},
Expand Down
Loading

0 comments on commit 3754e88

Please sign in to comment.