Skip to content

Commit

Permalink
Cursorless tutorial
Browse files Browse the repository at this point in the history
  • Loading branch information
pokey committed Jul 13, 2024
1 parent b9590b4 commit afee306
Show file tree
Hide file tree
Showing 76 changed files with 3,190 additions and 12 deletions.
22 changes: 22 additions & 0 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,16 @@
},
"group": "build"
},
{
"label": "Build tutorial webview",
"type": "npm",
"script": "build:dev",
"path": "packages/cursorless-vscode-tutorial-webview",
"presentation": {
"reveal": "silent"
},
"group": "build"
},
{
"label": "Build test harness",
"type": "npm",
Expand All @@ -57,6 +67,7 @@
"type": "npm",
"script": "populate-dist",
"path": "packages/cursorless-vscode",
"dependsOn": ["Build tutorial webview"],
"presentation": {
"reveal": "silent"
},
Expand Down Expand Up @@ -103,6 +114,17 @@
"dependsOn": ["Watch esbuild", "Watch typescript"],
"group": "build"
},
{
"label": "watch tutorial",
"type": "npm",
"script": "watch:tailwind",
"isBackground": true,
"presentation": {
"reveal": "never"
},
"path": "packages/cursorless-vscode-tutorial-webview",
"group": "build"
},
{
"type": "npm",
"script": "watch:esbuild",
Expand Down
7 changes: 7 additions & 0 deletions cursorless-talon/src/cheatsheet/cheat_sheet.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from .sections.modifiers import get_modifiers
from .sections.scopes import get_scopes
from .sections.special_marks import get_special_marks
from .sections.tutorial import get_tutorial_entries

mod = Module()
ctx = Context()
Expand All @@ -37,6 +38,7 @@ def private_cursorless_cheat_sheet_update_json():

def private_cursorless_open_instructions():
"""Open web page with cursorless instructions"""
actions.user.private_cursorless_notify_docs_opened()
webbrowser.open(instructions_url)


Expand Down Expand Up @@ -150,5 +152,10 @@ def cursorless_cheat_sheet_get_json():
"id": "shapes",
"items": get_list("hat_shape", "hatShape"),
},
{
"name": "Tutorial",
"id": "tutorial",
"items": get_tutorial_entries(),
},
]
}
83 changes: 83 additions & 0 deletions cursorless-talon/src/cheatsheet/sections/tutorial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
def get_tutorial_entries():
return [
{
"id": "start_tutorial",
"type": "command",
"variations": [
{
"spokenForm": "cursorless tutorial",
"description": "Start the introductory Cursorless tutorial",
},
],
},
{
"id": "tutorial_next",
"type": "command",
"variations": [
{
"spokenForm": "tutorial next",
"description": "Advance to next step in tutorial",
},
],
},
{
"id": "tutorial_previous",
"type": "command",
"variations": [
{
"spokenForm": "tutorial previous",
"description": "Go back to previous step in tutorial",
},
],
},
{
"id": "tutorial_restart",
"type": "command",
"variations": [
{
"spokenForm": "tutorial restart",
"description": "Restart the tutorial",
},
],
},
{
"id": "tutorial_resume",
"type": "command",
"variations": [
{
"spokenForm": "tutorial resume",
"description": "Resume the tutorial",
},
],
},
{
"id": "tutorial_list",
"type": "command",
"variations": [
{
"spokenForm": "tutorial list",
"description": "List all available tutorials",
},
],
},
{
"id": "tutorial_close",
"type": "command",
"variations": [
{
"spokenForm": "tutorial close",
"description": "Close the tutorial",
},
],
},
{
"id": "tutorial_start_by_number",
"type": "command",
"variations": [
{
"spokenForm": "tutorial <number>",
"description": "Start a specific tutorial by number",
},
],
},
]
68 changes: 67 additions & 1 deletion cursorless-talon/src/cursorless.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from talon import Module, actions
from talon import Context, Module, actions

mod = Module()

Expand All @@ -7,6 +7,13 @@
"Application supporting cursorless commands",
)

global_ctx = Context()

cursorless_ctx = Context()
cursorless_ctx.matches = r"""
tag: user.cursorless
"""


@mod.action_class
class Actions:
Expand All @@ -16,8 +23,67 @@ def private_cursorless_show_settings_in_ide():
def private_cursorless_show_sidebar():
"""Show Cursorless-specific settings in ide"""

def private_cursorless_notify_docs_opened():
"""Notify the ide that the docs were opened in case the tutorial is waiting for that event"""
...

def private_cursorless_show_command_statistics():
"""Show Cursorless command statistics"""
actions.user.private_cursorless_run_rpc_command_no_wait(
"cursorless.analyzeCommandHistory"
)

def private_cursorless_start_tutorial():
"""Start the introductory Cursorless tutorial"""
actions.user.private_cursorless_run_rpc_command_no_wait(
"cursorless.tutorial.start", "unit-1-basics"
)

def private_cursorless_tutorial_next():
"""Cursorless tutorial: next"""
actions.user.private_cursorless_run_rpc_command_no_wait(
"cursorless.tutorial.next"
)

def private_cursorless_tutorial_previous():
"""Cursorless tutorial: previous"""
actions.user.private_cursorless_run_rpc_command_no_wait(
"cursorless.tutorial.previous"
)

def private_cursorless_tutorial_restart():
"""Cursorless tutorial: restart"""
actions.user.private_cursorless_run_rpc_command_no_wait(
"cursorless.tutorial.restart"
)

def private_cursorless_tutorial_resume():
"""Cursorless tutorial: resume"""
actions.user.private_cursorless_run_rpc_command_no_wait(
"cursorless.tutorial.resume"
)

def private_cursorless_tutorial_list():
"""Cursorless tutorial: list all available tutorials"""
actions.user.private_cursorless_run_rpc_command_no_wait(
"cursorless.tutorial.list"
)

def private_cursorless_tutorial_start_by_number(number: int): # pyright: ignore [reportGeneralTypeIssues]
"""Start Cursorless tutorial by number"""
actions.user.private_cursorless_run_rpc_command_no_wait(
"cursorless.tutorial.start", number - 1
)


@global_ctx.action_class("user")
class GlobalActions:
def private_cursorless_notify_docs_opened():
# Do nothing if we're not in a Cursorless context
pass


@cursorless_ctx.action_class("user")
class CursorlessActions:
def private_cursorless_notify_docs_opened():
actions.user.private_cursorless_run_rpc_command_no_wait("cursorless.docsOpened")
10 changes: 10 additions & 0 deletions cursorless-talon/src/cursorless.talon
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,13 @@ bar {user.cursorless_homophone}:

{user.cursorless_homophone} stats:
user.private_cursorless_show_command_statistics()

{user.cursorless_homophone} tutorial:
user.private_cursorless_start_tutorial()
tutorial next: user.private_cursorless_tutorial_next()
tutorial (previous | last): user.private_cursorless_tutorial_previous()
tutorial restart: user.private_cursorless_tutorial_restart()
tutorial resume: user.private_cursorless_tutorial_resume()
tutorial (list | close): user.private_cursorless_tutorial_list()
tutorial <user.private_cursorless_number_small>:
user.private_cursorless_tutorial_start_by_number(private_cursorless_number_small)
30 changes: 30 additions & 0 deletions data/fixtures/recorded/tutorial/unit-1-basics/changeSit.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
languageId: plaintext
command:
version: 7
spokenForm: change sit
action:
name: clearAndSetSelection
target:
type: primitive
mark: {type: decoratedSymbol, symbolColor: default, character: i}
usePrePhraseSnapshot: true
initialState:
documentContents: |
Welcome Cursorless!
Notice the hats above each word in this sentence.
selections:
- anchor: {line: 2, character: 15}
active: {line: 2, character: 15}
marks:
default.i:
start: {line: 2, character: 32}
end: {line: 2, character: 34}
finalState:
documentContents: |
Welcome Cursorless!
Notice the hats above each word this sentence.
selections:
- anchor: {line: 2, character: 32}
active: {line: 2, character: 32}
39 changes: 39 additions & 0 deletions data/fixtures/recorded/tutorial/unit-1-basics/chuckLineOdd.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
languageId: plaintext
command:
version: 7
spokenForm: chuck line odd
action:
name: remove
target:
type: primitive
mark: {type: decoratedSymbol, symbolColor: default, character: o}
modifiers:
- type: containingScope
scopeType: {type: line}
usePrePhraseSnapshot: true
initialState:
documentContents: |-
Welcome Cursorless!
Notice the hats above each word in this sentence.
Now, see the sidebar.
selections:
- anchor: {line: 2, character: 0}
active: {line: 2, character: 6}
- anchor: {line: 2, character: 35}
active: {line: 2, character: 39}
marks:
default.o:
start: {line: 4, character: 0}
end: {line: 4, character: 3}
finalState:
documentContents: |
Welcome Cursorless!
Notice the hats above each word in this sentence.
selections:
- anchor: {line: 2, character: 0}
active: {line: 2, character: 6}
- anchor: {line: 2, character: 35}
active: {line: 2, character: 39}
38 changes: 38 additions & 0 deletions data/fixtures/recorded/tutorial/unit-1-basics/chuckTrap.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
languageId: plaintext
command:
version: 7
spokenForm: chuck trap
action:
name: remove
target:
type: primitive
mark: {type: decoratedSymbol, symbolColor: default, character: t}
usePrePhraseSnapshot: true
initialState:
documentContents: |-
Welcome to Cursorless!
Notice the hats above each word in this sentence.
Now, see the sidebar.
selections:
- anchor: {line: 2, character: 0}
active: {line: 2, character: 6}
- anchor: {line: 2, character: 35}
active: {line: 2, character: 39}
marks:
default.t:
start: {line: 0, character: 8}
end: {line: 0, character: 10}
finalState:
documentContents: |-
Welcome Cursorless!
Notice the hats above each word in this sentence.
Now, see the sidebar.
selections:
- anchor: {line: 2, character: 0}
active: {line: 2, character: 6}
- anchor: {line: 2, character: 35}
active: {line: 2, character: 39}
30 changes: 30 additions & 0 deletions data/fixtures/recorded/tutorial/unit-1-basics/postAir.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
languageId: plaintext
command:
version: 7
spokenForm: post air
action:
name: setSelectionAfter
target:
type: primitive
mark: {type: decoratedSymbol, symbolColor: default, character: a}
usePrePhraseSnapshot: true
initialState:
documentContents: |
Welcome Cursorless!
Notice the hats above each word in this sentence.
selections:
- anchor: {line: 0, character: 8}
active: {line: 0, character: 8}
marks:
default.a:
start: {line: 2, character: 11}
end: {line: 2, character: 15}
finalState:
documentContents: |
Welcome Cursorless!
Notice the hats above each word in this sentence.
selections:
- anchor: {line: 2, character: 15}
active: {line: 2, character: 15}
Loading

0 comments on commit afee306

Please sign in to comment.