diff --git a/CHANGELOG.md b/CHANGELOG.md
index ac7392ffa7..2149468127 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,7 @@
## 2026
+- 2026-09-09: Added support for Shell script language. ([#2058](https://github.com/cursorless-dev/cursorless/pull/2058))
- 2026-09-02: Added documentation for learning resources. ([#3334](https://github.com/cursorless-dev/cursorless/pull/3334))
- 2026-09-02: Added reference documentation for community draft editor. ([#3333](https://github.com/cursorless-dev/cursorless/pull/3333))
- 2026-09-02: Added reference documentation for community alphabet and symbols. ([#3332](https://github.com/cursorless-dev/cursorless/pull/3332))
diff --git a/packages/app-web-docs/src/docs/contributing/private-scopes/fixtures/interior.json b/packages/app-web-docs/src/docs/contributing/private-scopes/fixtures/interior.json
index 4576a7ae0c..094669a52e 100644
--- a/packages/app-web-docs/src/docs/contributing/private-scopes/fixtures/interior.json
+++ b/packages/app-web-docs/src/docs/contributing/private-scopes/fixtures/interior.json
@@ -4868,6 +4868,186 @@
}
]
},
+ {
+ "name": "scopes/shellscript/interior/interior.for",
+ "languageId": "shellscript",
+ "facet": "interior.for",
+ "code": "for ((foo = 0; foo < 2; foo++)); do :; done",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:36-0:38",
+ "removal": "0:35-0:39"
+ }
+ ],
+ "domain": "0:35-0:39"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/interior/interior.foreach",
+ "languageId": "shellscript",
+ "facet": "interior.foreach",
+ "code": "for v in values; do :; done",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:20-0:22",
+ "removal": "0:19-0:23"
+ }
+ ],
+ "domain": "0:19-0:23"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/interior/interior.function",
+ "languageId": "shellscript",
+ "facet": "interior.function",
+ "code": "foo() { }",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:7-0:8",
+ "removal": "0:7-0:8"
+ }
+ ],
+ "domain": "0:7-0:8"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/interior/interior.function2",
+ "languageId": "shellscript",
+ "facet": "interior.function",
+ "code": "function foo { }",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:14-0:15",
+ "removal": "0:14-0:15"
+ }
+ ],
+ "domain": "0:14-0:15"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/interior/interior.if",
+ "languageId": "shellscript",
+ "facet": "interior.if",
+ "code": "if true; then\n :\nelif false; then\n :\nelse\n :\nfi",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "1:2-1:3",
+ "removal": "0:13-2:0"
+ }
+ ],
+ "domain": "0:13-2:0"
+ },
+ {
+ "targets": [
+ {
+ "content": "3:2-3:3",
+ "removal": "2:16-4:0"
+ }
+ ],
+ "domain": "2:16-4:0"
+ },
+ {
+ "targets": [
+ {
+ "content": "5:2-5:3",
+ "removal": "4:4-6:0"
+ }
+ ],
+ "domain": "4:4-6:0"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/interior/interior.switch",
+ "languageId": "shellscript",
+ "facet": "interior.switch",
+ "code": "case $foo in esac",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:12-0:13",
+ "removal": "0:12-0:13"
+ }
+ ],
+ "domain": "0:12-0:13"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/interior/interior.switchCase",
+ "languageId": "shellscript",
+ "facet": "interior.switchCase",
+ "code": "case $foo in\n 0) : ;;\nesac",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "1:2-1:9",
+ "removal": "0:12-2:0"
+ }
+ ],
+ "domain": "0:12-2:0"
+ },
+ {
+ "targets": [
+ {
+ "content": "1:5-1:6",
+ "removal": "1:4-1:7"
+ }
+ ],
+ "domain": "1:4-1:7"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/interior/interior.while",
+ "languageId": "shellscript",
+ "facet": "interior.while",
+ "code": "while foo; do :; done",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:14-0:16",
+ "removal": "0:13-0:17"
+ }
+ ],
+ "domain": "0:13-0:17"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/interior/interior.while2",
+ "languageId": "shellscript",
+ "facet": "interior.while",
+ "code": "until foo; do :; done",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:14-0:16",
+ "removal": "0:13-0:17"
+ }
+ ],
+ "domain": "0:13-0:17"
+ }
+ ]
+ },
{
"name": "scopes/talon/interior.command",
"languageId": "talon",
diff --git a/packages/app-web-docs/src/docs/contributing/private-scopes/fixtures/string.json b/packages/app-web-docs/src/docs/contributing/private-scopes/fixtures/string.json
index 69c092e30d..a075ba5b65 100644
--- a/packages/app-web-docs/src/docs/contributing/private-scopes/fixtures/string.json
+++ b/packages/app-web-docs/src/docs/contributing/private-scopes/fixtures/string.json
@@ -594,6 +594,40 @@
}
]
},
+ {
+ "name": "scopes/shellscript/string.multiLine",
+ "languageId": "shellscript",
+ "facet": "string.multiLine",
+ "code": "\"Hello\nworld\"",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-1:6",
+ "removal": "0:0-1:6"
+ }
+ ],
+ "domain": "0:0-1:6"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/string.singleLine",
+ "languageId": "shellscript",
+ "facet": "string.singleLine",
+ "code": "\"Hello world\"",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-0:13",
+ "removal": "0:0-0:13"
+ }
+ ],
+ "domain": "0:0-0:13"
+ }
+ ]
+ },
{
"name": "scopes/talon/string.singleLine",
"languageId": "talon",
diff --git a/packages/app-web-docs/src/docs/contributing/private-scopes/fixtures/textFragment.json b/packages/app-web-docs/src/docs/contributing/private-scopes/fixtures/textFragment.json
index e6d513f217..03938caf4f 100644
--- a/packages/app-web-docs/src/docs/contributing/private-scopes/fixtures/textFragment.json
+++ b/packages/app-web-docs/src/docs/contributing/private-scopes/fixtures/textFragment.json
@@ -1360,6 +1360,57 @@
}
]
},
+ {
+ "name": "scopes/shellscript/textFragment.comment.line",
+ "languageId": "shellscript",
+ "facet": "textFragment.comment.line",
+ "code": "# Hello world",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-0:13",
+ "removal": "0:0-0:13"
+ }
+ ],
+ "domain": "0:0-0:13"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/textFragment.string.multiLine",
+ "languageId": "shellscript",
+ "facet": "textFragment.string.multiLine",
+ "code": "\"Hello\nworld\"",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:1-1:5",
+ "removal": "0:1-1:5"
+ }
+ ],
+ "domain": "0:1-1:5"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/textFragment.string.singleLine",
+ "languageId": "shellscript",
+ "facet": "textFragment.string.singleLine",
+ "code": "\"Hello world\"",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:1-0:12",
+ "removal": "0:1-0:12"
+ }
+ ],
+ "domain": "0:1-0:12"
+ }
+ ]
+ },
{
"name": "scopes/talon/textFragment.comment.line",
"languageId": "talon",
diff --git a/packages/app-web-docs/src/docs/contributing/private-scopes/interior.mdx b/packages/app-web-docs/src/docs/contributing/private-scopes/interior.mdx
index c765ed425a..745de80175 100644
--- a/packages/app-web-docs/src/docs/contributing/private-scopes/interior.mdx
+++ b/packages/app-web-docs/src/docs/contributing/private-scopes/interior.mdx
@@ -295,6 +295,10 @@ The following are internal scopes. They are not intended for user interaction or
+##### Shell Script
+
+
+
### Interior: Foreach
The body of a for-each loop
@@ -357,6 +361,10 @@ The following are internal scopes. They are not intended for user interaction or
+##### Shell Script
+
+
+
##### Talon
@@ -429,6 +437,12 @@ The following are internal scopes. They are not intended for user interaction or
+##### Shell Script
+
+
+
+
+
### Interior: If
The body of an if/elif/else branch
@@ -497,6 +511,10 @@ The following are internal scopes. They are not intended for user interaction or
+##### Shell Script
+
+
+
##### Talon
@@ -757,6 +775,10 @@ The following are internal scopes. They are not intended for user interaction or
+##### Shell Script
+
+
+
### Interior: Switch case
The body of a case/default branch in a switch statement
@@ -837,6 +859,10 @@ The following are internal scopes. They are not intended for user interaction or
+##### Shell Script
+
+
+
### Interior: Try
The body of a try/catch/finally branch
@@ -943,4 +969,10 @@ The following are internal scopes. They are not intended for user interaction or
+##### Shell Script
+
+
+
+
+
diff --git a/packages/app-web-docs/src/docs/contributing/private-scopes/string.mdx b/packages/app-web-docs/src/docs/contributing/private-scopes/string.mdx
index 4d8e58d3f2..1f541ccf32 100644
--- a/packages/app-web-docs/src/docs/contributing/private-scopes/string.mdx
+++ b/packages/app-web-docs/src/docs/contributing/private-scopes/string.mdx
@@ -89,6 +89,10 @@ The following are internal scopes. They are not intended for user interaction or
+##### Shell Script
+
+
+
##### YAML
@@ -177,6 +181,10 @@ The following are internal scopes. They are not intended for user interaction or
+##### Shell Script
+
+
+
##### Talon list
diff --git a/packages/app-web-docs/src/docs/contributing/private-scopes/textFragment.mdx b/packages/app-web-docs/src/docs/contributing/private-scopes/textFragment.mdx
index d38f4a1f53..936aab6cd7 100644
--- a/packages/app-web-docs/src/docs/contributing/private-scopes/textFragment.mdx
+++ b/packages/app-web-docs/src/docs/contributing/private-scopes/textFragment.mdx
@@ -195,6 +195,10 @@ The following are internal scopes. They are not intended for user interaction or
+##### Shell Script
+
+
+
##### Talon list
@@ -289,6 +293,10 @@ The following are internal scopes. They are not intended for user interaction or
+##### Shell Script
+
+
+
##### YAML
@@ -377,6 +385,10 @@ The following are internal scopes. They are not intended for user interaction or
+##### Shell Script
+
+
+
##### Talon list
diff --git a/packages/app-web-docs/src/docs/user/languages/README.md b/packages/app-web-docs/src/docs/user/languages/README.md
index 64ebe810e9..6a3a17ae2a 100644
--- a/packages/app-web-docs/src/docs/user/languages/README.md
+++ b/packages/app-web-docs/src/docs/user/languages/README.md
@@ -32,6 +32,7 @@ sidebar_position: 4
- [Scala](./scala.mdx)
- [Tree-sitter query (SCM)](./scm.mdx)
- [SCSS](./scss.mdx)
+- [Shell Script](./shellscript.mdx)
- [Talon](./talon.mdx)
- [Talon list](./talon-list.mdx)
- [TypeScript](./typescript.mdx)
diff --git a/packages/app-web-docs/src/docs/user/languages/fixtures/shellscript.json b/packages/app-web-docs/src/docs/user/languages/fixtures/shellscript.json
new file mode 100644
index 0000000000..11871f06bd
--- /dev/null
+++ b/packages/app-web-docs/src/docs/user/languages/fixtures/shellscript.json
@@ -0,0 +1,2034 @@
+[
+ {
+ "name": "scopes/shellscript/argument/argument.actual.iteration",
+ "languageId": "shellscript",
+ "facet": "argument.actual.iteration",
+ "code": "foo aaa bbb",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:4-0:11"
+ }
+ ],
+ "domain": "0:0-0:11"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/argument/argument.actual.multiLine",
+ "languageId": "shellscript",
+ "facet": "argument.actual.multiLine",
+ "code": "foo aaa \\\n bbb",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:4-0:7",
+ "removal": "0:4-1:2"
+ }
+ ],
+ "domain": "0:4-0:7"
+ },
+ {
+ "targets": [
+ {
+ "content": "1:2-1:5",
+ "removal": "0:7-1:5"
+ }
+ ],
+ "domain": "1:2-1:5"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/argument/argument.actual.singleLine",
+ "languageId": "shellscript",
+ "facet": "argument.actual.singleLine",
+ "code": "foo aaa bbb",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:4-0:7",
+ "removal": "0:4-0:8"
+ }
+ ],
+ "domain": "0:4-0:7"
+ },
+ {
+ "targets": [
+ {
+ "content": "0:8-0:11",
+ "removal": "0:7-0:11"
+ }
+ ],
+ "domain": "0:8-0:11"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/argumentList.actual.empty",
+ "languageId": "shellscript",
+ "facet": "argumentList.actual.empty",
+ "code": "foo",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:3-0:3",
+ "removal": "0:3-0:3"
+ }
+ ],
+ "domain": "0:0-0:3"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/argumentList.actual.multiLine",
+ "languageId": "shellscript",
+ "facet": "argumentList.actual.multiLine",
+ "code": "foo aaa \\\n bbb",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:4-1:5",
+ "removal": "0:3-1:5"
+ }
+ ],
+ "domain": "0:0-1:5"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/argumentList.actual.singleLine",
+ "languageId": "shellscript",
+ "facet": "argumentList.actual.singleLine",
+ "code": "foo aaa bbb",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:4-0:11",
+ "removal": "0:3-0:11"
+ }
+ ],
+ "domain": "0:0-0:11"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/branch/branch.if.elif.else",
+ "languageId": "shellscript",
+ "facet": "branch.if.elif.else",
+ "code": "if true; then\n :\nelif false; then\n :\nelse\n :\nfi",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-1:5",
+ "removal": "0:0-2:2"
+ }
+ ],
+ "domain": "0:0-1:5"
+ },
+ {
+ "targets": [
+ {
+ "content": "2:0-3:5",
+ "removal": "2:0-4:0"
+ }
+ ],
+ "domain": "2:0-3:5"
+ },
+ {
+ "targets": [
+ {
+ "content": "4:0-5:5",
+ "removal": "4:0-6:0"
+ }
+ ],
+ "domain": "4:0-5:5"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/branch/branch.if.else",
+ "languageId": "shellscript",
+ "facet": "branch.if.else",
+ "code": "if true; then\n :\nelse\n :\nfi",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-1:5",
+ "removal": "0:0-2:0"
+ }
+ ],
+ "domain": "0:0-1:5"
+ },
+ {
+ "targets": [
+ {
+ "content": "2:0-3:5",
+ "removal": "2:0-4:0"
+ }
+ ],
+ "domain": "2:0-3:5"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/branch/branch.if.iteration",
+ "languageId": "shellscript",
+ "facet": "branch.if.iteration",
+ "code": "if true; then\nelif false; then\nelse\nfi",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-3:2"
+ }
+ ],
+ "domain": "0:0-3:2"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/branch/branch.if",
+ "languageId": "shellscript",
+ "facet": "branch.if",
+ "code": "if true; then :; fi",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-0:19",
+ "removal": "0:0-0:19"
+ }
+ ],
+ "domain": "0:0-0:19"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/branch/branch.switchCase.iteration",
+ "languageId": "shellscript",
+ "facet": "branch.switchCase.iteration",
+ "code": "case $foo in esac",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:12-0:13"
+ }
+ ],
+ "domain": "0:12-0:13"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/branch/branch.switchCase",
+ "languageId": "shellscript",
+ "facet": "branch.switchCase",
+ "code": "case $foo in\n 0) : ;;\nesac",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "1:4-1:11",
+ "removal": "1:0-2:0"
+ }
+ ],
+ "domain": "1:4-1:11"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/branch/branch.switchCase2",
+ "languageId": "shellscript",
+ "facet": "branch.switchCase",
+ "code": "case $foo in\n *) : ;;\nesac",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "1:4-1:11",
+ "removal": "1:0-2:0"
+ }
+ ],
+ "domain": "1:4-1:11"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/branch/branch.ternary.iteration",
+ "languageId": "shellscript",
+ "facet": "branch.ternary.iteration",
+ "code": "((true ? 0 : 1))",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:2-0:14"
+ }
+ ],
+ "domain": "0:2-0:14"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/branch/branch.ternary",
+ "languageId": "shellscript",
+ "facet": "branch.ternary",
+ "code": "((true ? 0 : 1))",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:9-0:10",
+ "removal": "0:9-0:11"
+ }
+ ],
+ "domain": "0:9-0:10"
+ },
+ {
+ "targets": [
+ {
+ "content": "0:13-0:14",
+ "removal": "0:12-0:14"
+ }
+ ],
+ "domain": "0:13-0:14"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/comment.line",
+ "languageId": "shellscript",
+ "facet": "comment.line",
+ "code": "# Hello world",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-0:13",
+ "removal": "0:0-0:13"
+ }
+ ],
+ "domain": "0:0-0:13"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/condition/condition.for",
+ "languageId": "shellscript",
+ "facet": "condition.for",
+ "code": "for ((i = 0; i < 2; i++)); do :; done",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:13-0:18",
+ "removal": "0:12-0:18"
+ }
+ ],
+ "domain": "0:0-0:37"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/condition/condition.if",
+ "languageId": "shellscript",
+ "facet": "condition.if",
+ "code": "if true; then\nelif false; then\nelse\nfi",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:3-0:7",
+ "removal": "0:2-0:7"
+ }
+ ],
+ "domain": "0:0-3:2"
+ },
+ {
+ "targets": [
+ {
+ "content": "1:5-1:10",
+ "removal": "1:4-1:10"
+ }
+ ],
+ "domain": "1:0-1:16"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/condition/condition.switchCase.iteration",
+ "languageId": "shellscript",
+ "facet": "condition.switchCase.iteration",
+ "code": "case $foo in esac",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:12-0:13"
+ }
+ ],
+ "domain": "0:12-0:13"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/condition/condition.switchCase",
+ "languageId": "shellscript",
+ "facet": "condition.switchCase",
+ "code": "case $foo in\n 0) : ;;\nesac",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "1:2-1:3",
+ "removal": "1:0-1:3"
+ }
+ ],
+ "domain": "1:2-1:9"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/condition/condition.ternary",
+ "languageId": "shellscript",
+ "facet": "condition.ternary",
+ "code": "((true ? 0 : 1))",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:2-0:6",
+ "removal": "0:2-0:7"
+ }
+ ],
+ "domain": "0:2-0:14"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/condition/condition.while",
+ "languageId": "shellscript",
+ "facet": "condition.while",
+ "code": "while true; do :; done",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:6-0:10",
+ "removal": "0:5-0:10"
+ }
+ ],
+ "domain": "0:0-0:22"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/condition/condition.while2",
+ "languageId": "shellscript",
+ "facet": "condition.while",
+ "code": "until true; do :; done",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:6-0:10",
+ "removal": "0:5-0:10"
+ }
+ ],
+ "domain": "0:0-0:22"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/functionCall",
+ "languageId": "shellscript",
+ "facet": "functionCall",
+ "code": "foo",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-0:3",
+ "removal": "0:0-0:3"
+ }
+ ],
+ "domain": "0:0-0:3"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/functionCall2",
+ "languageId": "shellscript",
+ "facet": "functionCall",
+ "code": "foo aaa bbb",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-0:11",
+ "removal": "0:0-0:11"
+ }
+ ],
+ "domain": "0:0-0:11"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/functionCallee",
+ "languageId": "shellscript",
+ "facet": "functionCallee",
+ "code": "foo",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-0:3",
+ "removal": "0:0-0:3"
+ }
+ ],
+ "domain": "0:0-0:3"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/functionCallee2",
+ "languageId": "shellscript",
+ "facet": "functionCallee",
+ "code": "foo aaa bbb",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-0:3",
+ "removal": "0:0-0:4"
+ }
+ ],
+ "domain": "0:0-0:11"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/ifStatement",
+ "languageId": "shellscript",
+ "facet": "ifStatement",
+ "code": "if true; then\nelif false; then\nelse\nfi",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-3:2",
+ "removal": "0:0-3:2"
+ }
+ ],
+ "domain": "0:0-3:2"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/interior/interior.for",
+ "languageId": "shellscript",
+ "facet": "interior.for",
+ "code": "for ((foo = 0; foo < 2; foo++)); do :; done",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:36-0:38",
+ "removal": "0:35-0:39"
+ }
+ ],
+ "domain": "0:35-0:39"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/interior/interior.foreach",
+ "languageId": "shellscript",
+ "facet": "interior.foreach",
+ "code": "for v in values; do :; done",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:20-0:22",
+ "removal": "0:19-0:23"
+ }
+ ],
+ "domain": "0:19-0:23"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/interior/interior.function",
+ "languageId": "shellscript",
+ "facet": "interior.function",
+ "code": "foo() { }",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:7-0:8",
+ "removal": "0:7-0:8"
+ }
+ ],
+ "domain": "0:7-0:8"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/interior/interior.function2",
+ "languageId": "shellscript",
+ "facet": "interior.function",
+ "code": "function foo { }",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:14-0:15",
+ "removal": "0:14-0:15"
+ }
+ ],
+ "domain": "0:14-0:15"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/interior/interior.if",
+ "languageId": "shellscript",
+ "facet": "interior.if",
+ "code": "if true; then\n :\nelif false; then\n :\nelse\n :\nfi",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "1:2-1:3",
+ "removal": "0:13-2:0"
+ }
+ ],
+ "domain": "0:13-2:0"
+ },
+ {
+ "targets": [
+ {
+ "content": "3:2-3:3",
+ "removal": "2:16-4:0"
+ }
+ ],
+ "domain": "2:16-4:0"
+ },
+ {
+ "targets": [
+ {
+ "content": "5:2-5:3",
+ "removal": "4:4-6:0"
+ }
+ ],
+ "domain": "4:4-6:0"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/interior/interior.switch",
+ "languageId": "shellscript",
+ "facet": "interior.switch",
+ "code": "case $foo in esac",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:12-0:13",
+ "removal": "0:12-0:13"
+ }
+ ],
+ "domain": "0:12-0:13"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/interior/interior.switchCase",
+ "languageId": "shellscript",
+ "facet": "interior.switchCase",
+ "code": "case $foo in\n 0) : ;;\nesac",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "1:2-1:9",
+ "removal": "0:12-2:0"
+ }
+ ],
+ "domain": "0:12-2:0"
+ },
+ {
+ "targets": [
+ {
+ "content": "1:5-1:6",
+ "removal": "1:4-1:7"
+ }
+ ],
+ "domain": "1:4-1:7"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/interior/interior.while",
+ "languageId": "shellscript",
+ "facet": "interior.while",
+ "code": "while foo; do :; done",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:14-0:16",
+ "removal": "0:13-0:17"
+ }
+ ],
+ "domain": "0:13-0:17"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/interior/interior.while2",
+ "languageId": "shellscript",
+ "facet": "interior.while",
+ "code": "until foo; do :; done",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:14-0:16",
+ "removal": "0:13-0:17"
+ }
+ ],
+ "domain": "0:13-0:17"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/key.mapPair.iteration",
+ "languageId": "shellscript",
+ "facet": "key.mapPair.iteration",
+ "code": "foo=([\"aaa\"]=0 [\"bbb\"]=1)",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:5-0:24"
+ }
+ ],
+ "domain": "0:5-0:24"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/key.mapPair",
+ "languageId": "shellscript",
+ "facet": "key.mapPair",
+ "code": "foo=([\"aaa\"]=0 [\"bbb\"]=1)",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:6-0:11",
+ "removal": "0:6-0:11"
+ }
+ ],
+ "domain": "0:5-0:14"
+ },
+ {
+ "targets": [
+ {
+ "content": "0:16-0:21",
+ "removal": "0:16-0:21"
+ }
+ ],
+ "domain": "0:15-0:24"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/list",
+ "languageId": "shellscript",
+ "facet": "list",
+ "code": "foo=(aaa bbb)",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:4-0:13",
+ "removal": "0:4-0:13"
+ }
+ ],
+ "domain": "0:4-0:13"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/map",
+ "languageId": "shellscript",
+ "facet": "map",
+ "code": "foo=([\"aaa\"]=0 [\"bbb\"]=1)",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:4-0:25",
+ "removal": "0:4-0:25"
+ }
+ ],
+ "domain": "0:4-0:25"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/name/name.assignment.compound",
+ "languageId": "shellscript",
+ "facet": "name.assignment.compound",
+ "code": "foo+=0",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-0:3",
+ "removal": "0:0-0:5"
+ }
+ ],
+ "domain": "0:0-0:6"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/name/name.assignment",
+ "languageId": "shellscript",
+ "facet": "name.assignment",
+ "code": "foo=0",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-0:3",
+ "removal": "0:0-0:4"
+ }
+ ],
+ "domain": "0:0-0:5"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/name/name.constant",
+ "languageId": "shellscript",
+ "facet": "name.constant",
+ "code": "readonly foo=0",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:9-0:12",
+ "removal": "0:0-0:13"
+ }
+ ],
+ "domain": "0:0-0:14"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/name/name.foreach",
+ "languageId": "shellscript",
+ "facet": "name.foreach",
+ "code": "for v in values; do :; done",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:4-0:5",
+ "removal": "0:4-0:6"
+ }
+ ],
+ "domain": "0:0-0:27"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/name/name.function",
+ "languageId": "shellscript",
+ "facet": "name.function",
+ "code": "foo() {}",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-0:3",
+ "removal": "0:0-0:3"
+ }
+ ],
+ "domain": "0:0-0:8"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/name/name.function2",
+ "languageId": "shellscript",
+ "facet": "name.function",
+ "code": "function foo {}",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:9-0:12",
+ "removal": "0:9-0:13"
+ }
+ ],
+ "domain": "0:0-0:15"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/name/name.iteration.block",
+ "languageId": "shellscript",
+ "facet": "name.iteration.block",
+ "code": "foo() { }",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-0:9"
+ }
+ ],
+ "domain": "0:0-0:9"
+ },
+ {
+ "targets": [
+ {
+ "content": "0:7-0:8"
+ }
+ ],
+ "domain": "0:7-0:8"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/name/name.iteration.block3",
+ "languageId": "shellscript",
+ "facet": "name.iteration.block",
+ "code": "while true; do :; done",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-0:22"
+ }
+ ],
+ "domain": "0:0-0:22"
+ },
+ {
+ "targets": [
+ {
+ "content": "0:14-0:18"
+ }
+ ],
+ "domain": "0:14-0:18"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/name/name.iteration.document",
+ "languageId": "shellscript",
+ "facet": "name.iteration.document",
+ "code": "\ndeclare foo\n",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-2:0"
+ }
+ ],
+ "domain": "0:0-2:0"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/name/name.variable.initialized",
+ "languageId": "shellscript",
+ "facet": "name.variable.initialized",
+ "code": "local foo=0",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:6-0:9",
+ "removal": "0:0-0:10"
+ }
+ ],
+ "domain": "0:0-0:11"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/name/name.variable.initialized2",
+ "languageId": "shellscript",
+ "facet": "name.variable.initialized",
+ "code": "declare foo=0",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:8-0:11",
+ "removal": "0:0-0:12"
+ }
+ ],
+ "domain": "0:0-0:13"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/name/name.variable.uninitialized",
+ "languageId": "shellscript",
+ "facet": "name.variable.uninitialized",
+ "code": "declare foo",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:8-0:11",
+ "removal": "0:7-0:11"
+ }
+ ],
+ "domain": "0:0-0:11"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/name/name.variable.uninitialized2",
+ "languageId": "shellscript",
+ "facet": "name.variable.uninitialized",
+ "code": "local foo",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:6-0:9",
+ "removal": "0:5-0:9"
+ }
+ ],
+ "domain": "0:0-0:9"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/namedFunction/namedFunction.iteration.document",
+ "languageId": "shellscript",
+ "facet": "namedFunction.iteration.document",
+ "code": "\nfoo() {}\n",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-2:0"
+ }
+ ],
+ "domain": "0:0-2:0"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/namedFunction/namedFunction",
+ "languageId": "shellscript",
+ "facet": "namedFunction",
+ "code": "foo() {}",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-0:8",
+ "removal": "0:0-0:8"
+ }
+ ],
+ "domain": "0:0-0:8"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/namedFunction/namedFunction2",
+ "languageId": "shellscript",
+ "facet": "namedFunction",
+ "code": "function foo {}",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-0:15",
+ "removal": "0:0-0:15"
+ }
+ ],
+ "domain": "0:0-0:15"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/namedFunction/namedFunction3",
+ "languageId": "shellscript",
+ "facet": "namedFunction",
+ "code": "function foo() {}",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-0:17",
+ "removal": "0:0-0:17"
+ }
+ ],
+ "domain": "0:0-0:17"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/regularExpression",
+ "languageId": "shellscript",
+ "facet": "regularExpression",
+ "code": "[[ $foo =~ ^\\w+$ ]]",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:11-0:16",
+ "removal": "0:11-0:17"
+ }
+ ],
+ "domain": "0:11-0:16"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/statement/statement.assignment.compound",
+ "languageId": "shellscript",
+ "facet": "statement.assignment.compound",
+ "code": "foo+=1",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-0:6",
+ "removal": "0:0-0:6"
+ }
+ ],
+ "domain": "0:0-0:6"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/statement/statement.assignment",
+ "languageId": "shellscript",
+ "facet": "statement.assignment",
+ "code": "foo=0",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-0:5",
+ "removal": "0:0-0:5"
+ }
+ ],
+ "domain": "0:0-0:5"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/statement/statement.break",
+ "languageId": "shellscript",
+ "facet": "statement.break",
+ "code": "while true; do\n break\ndone",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-2:4",
+ "removal": "0:0-2:4"
+ }
+ ],
+ "domain": "0:0-2:4"
+ },
+ {
+ "targets": [
+ {
+ "content": "1:4-1:9",
+ "removal": "1:0-2:0"
+ }
+ ],
+ "domain": "1:4-1:9"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/statement/statement.constant",
+ "languageId": "shellscript",
+ "facet": "statement.constant",
+ "code": "readonly foo=0",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-0:14",
+ "removal": "0:0-0:14"
+ }
+ ],
+ "domain": "0:0-0:14"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/statement/statement.continue",
+ "languageId": "shellscript",
+ "facet": "statement.continue",
+ "code": "while true; do\n continue\ndone",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-2:4",
+ "removal": "0:0-2:4"
+ }
+ ],
+ "domain": "0:0-2:4"
+ },
+ {
+ "targets": [
+ {
+ "content": "1:4-1:12",
+ "removal": "1:0-2:0"
+ }
+ ],
+ "domain": "1:4-1:12"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/statement/statement.for",
+ "languageId": "shellscript",
+ "facet": "statement.for",
+ "code": "for ((i = 0; i < 2; i++)); do :; done",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-0:37",
+ "removal": "0:0-0:37"
+ }
+ ],
+ "domain": "0:0-0:37"
+ },
+ {
+ "targets": [
+ {
+ "content": "0:30-0:31",
+ "removal": "0:29-0:31"
+ }
+ ],
+ "domain": "0:30-0:31"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/statement/statement.foreach",
+ "languageId": "shellscript",
+ "facet": "statement.foreach",
+ "code": "for v in values; do :; done",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-0:27",
+ "removal": "0:0-0:27"
+ }
+ ],
+ "domain": "0:0-0:27"
+ },
+ {
+ "targets": [
+ {
+ "content": "0:20-0:21",
+ "removal": "0:19-0:21"
+ }
+ ],
+ "domain": "0:20-0:21"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/statement/statement.function",
+ "languageId": "shellscript",
+ "facet": "statement.function",
+ "code": "foo() {}",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-0:8",
+ "removal": "0:0-0:8"
+ }
+ ],
+ "domain": "0:0-0:8"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/statement/statement.function2",
+ "languageId": "shellscript",
+ "facet": "statement.function",
+ "code": "function foo {}",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-0:15",
+ "removal": "0:0-0:15"
+ }
+ ],
+ "domain": "0:0-0:15"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/statement/statement.functionCall",
+ "languageId": "shellscript",
+ "facet": "statement.functionCall",
+ "code": "foo",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-0:3",
+ "removal": "0:0-0:3"
+ }
+ ],
+ "domain": "0:0-0:3"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/statement/statement.functionCall2",
+ "languageId": "shellscript",
+ "facet": "statement.functionCall",
+ "code": "foo aaa bbb",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-0:11",
+ "removal": "0:0-0:11"
+ }
+ ],
+ "domain": "0:0-0:11"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/statement/statement.if",
+ "languageId": "shellscript",
+ "facet": "statement.if",
+ "code": "if true; then\nelif false; then\nelse\nfi",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-3:2",
+ "removal": "0:0-3:2"
+ }
+ ],
+ "domain": "0:0-3:2"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/statement/statement.if2",
+ "languageId": "shellscript",
+ "facet": "statement.if",
+ "code": "if foo; then\n aaa\n bbb\nelif baz; then\n ccc\n ddd\nfi",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-6:2",
+ "removal": "0:0-6:2"
+ }
+ ],
+ "domain": "0:0-6:2"
+ },
+ {
+ "targets": [
+ {
+ "content": "1:4-1:7",
+ "removal": "1:0-2:0"
+ }
+ ],
+ "domain": "1:4-1:7"
+ },
+ {
+ "targets": [
+ {
+ "content": "2:4-2:7",
+ "removal": "2:0-3:0"
+ }
+ ],
+ "domain": "2:4-2:7"
+ },
+ {
+ "targets": [
+ {
+ "content": "4:4-4:7",
+ "removal": "4:0-5:0"
+ }
+ ],
+ "domain": "4:4-4:7"
+ },
+ {
+ "targets": [
+ {
+ "content": "5:4-5:7",
+ "removal": "5:0-6:0"
+ }
+ ],
+ "domain": "5:4-5:7"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/statement/statement.import",
+ "languageId": "shellscript",
+ "facet": "statement.import",
+ "code": "source foo.sh",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-0:13",
+ "removal": "0:0-0:13"
+ }
+ ],
+ "domain": "0:0-0:13"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/statement/statement.iteration.block",
+ "languageId": "shellscript",
+ "facet": "statement.iteration.block",
+ "code": "foo() { }",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-0:9"
+ }
+ ],
+ "domain": "0:0-0:9"
+ },
+ {
+ "targets": [
+ {
+ "content": "0:7-0:8"
+ }
+ ],
+ "domain": "0:7-0:8"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/statement/statement.iteration.block3",
+ "languageId": "shellscript",
+ "facet": "statement.iteration.block",
+ "code": "while true; do :; done",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-0:22"
+ }
+ ],
+ "domain": "0:0-0:22"
+ },
+ {
+ "targets": [
+ {
+ "content": "0:14-0:18"
+ }
+ ],
+ "domain": "0:14-0:18"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/statement/statement.iteration.document",
+ "languageId": "shellscript",
+ "facet": "statement.iteration.document",
+ "code": "\ndeclare foo\n",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-2:0"
+ }
+ ],
+ "domain": "0:0-2:0"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/statement/statement.return",
+ "languageId": "shellscript",
+ "facet": "statement.return",
+ "code": "foo() {\n return 0\n}",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-2:1",
+ "removal": "0:0-2:1"
+ }
+ ],
+ "domain": "0:0-2:1"
+ },
+ {
+ "targets": [
+ {
+ "content": "1:4-1:12",
+ "removal": "1:0-2:0"
+ }
+ ],
+ "domain": "1:4-1:12"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/statement/statement.return2",
+ "languageId": "shellscript",
+ "facet": "statement.return",
+ "code": "function foo {\n return 0\n}",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-2:1",
+ "removal": "0:0-2:1"
+ }
+ ],
+ "domain": "0:0-2:1"
+ },
+ {
+ "targets": [
+ {
+ "content": "1:4-1:12",
+ "removal": "1:0-2:0"
+ }
+ ],
+ "domain": "1:4-1:12"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/statement/statement.switch",
+ "languageId": "shellscript",
+ "facet": "statement.switch",
+ "code": "case $foo in esac",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-0:17",
+ "removal": "0:0-0:17"
+ }
+ ],
+ "domain": "0:0-0:17"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/statement/statement.update",
+ "languageId": "shellscript",
+ "facet": "statement.update",
+ "code": "((foo++))",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-0:9",
+ "removal": "0:0-0:9"
+ }
+ ],
+ "domain": "0:0-0:9"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/statement/statement.variable.initialized",
+ "languageId": "shellscript",
+ "facet": "statement.variable.initialized",
+ "code": "local foo=0",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-0:11",
+ "removal": "0:0-0:11"
+ }
+ ],
+ "domain": "0:0-0:11"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/statement/statement.variable.initialized2",
+ "languageId": "shellscript",
+ "facet": "statement.variable.initialized",
+ "code": "declare foo=0",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-0:13",
+ "removal": "0:0-0:13"
+ }
+ ],
+ "domain": "0:0-0:13"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/statement/statement.variable.uninitialized",
+ "languageId": "shellscript",
+ "facet": "statement.variable.uninitialized",
+ "code": "declare foo",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-0:11",
+ "removal": "0:0-0:11"
+ }
+ ],
+ "domain": "0:0-0:11"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/statement/statement.while",
+ "languageId": "shellscript",
+ "facet": "statement.while",
+ "code": "while true; do :; done",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-0:22",
+ "removal": "0:0-0:22"
+ }
+ ],
+ "domain": "0:0-0:22"
+ },
+ {
+ "targets": [
+ {
+ "content": "0:15-0:16",
+ "removal": "0:14-0:16"
+ }
+ ],
+ "domain": "0:15-0:16"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/statement/statement.while2",
+ "languageId": "shellscript",
+ "facet": "statement.while",
+ "code": "until true; do :; done",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-0:22",
+ "removal": "0:0-0:22"
+ }
+ ],
+ "domain": "0:0-0:22"
+ },
+ {
+ "targets": [
+ {
+ "content": "0:15-0:16",
+ "removal": "0:14-0:16"
+ }
+ ],
+ "domain": "0:15-0:16"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/string.multiLine",
+ "languageId": "shellscript",
+ "facet": "string.multiLine",
+ "code": "\"Hello\nworld\"",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-1:6",
+ "removal": "0:0-1:6"
+ }
+ ],
+ "domain": "0:0-1:6"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/string.singleLine",
+ "languageId": "shellscript",
+ "facet": "string.singleLine",
+ "code": "\"Hello world\"",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-0:13",
+ "removal": "0:0-0:13"
+ }
+ ],
+ "domain": "0:0-0:13"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/textFragment.comment.line",
+ "languageId": "shellscript",
+ "facet": "textFragment.comment.line",
+ "code": "# Hello world",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-0:13",
+ "removal": "0:0-0:13"
+ }
+ ],
+ "domain": "0:0-0:13"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/textFragment.string.multiLine",
+ "languageId": "shellscript",
+ "facet": "textFragment.string.multiLine",
+ "code": "\"Hello\nworld\"",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:1-1:5",
+ "removal": "0:1-1:5"
+ }
+ ],
+ "domain": "0:1-1:5"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/textFragment.string.singleLine",
+ "languageId": "shellscript",
+ "facet": "textFragment.string.singleLine",
+ "code": "\"Hello world\"",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:1-0:12",
+ "removal": "0:1-0:12"
+ }
+ ],
+ "domain": "0:1-0:12"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/value/value.assignment.compound",
+ "languageId": "shellscript",
+ "facet": "value.assignment.compound",
+ "code": "foo+=0",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:5-0:6",
+ "removal": "0:3-0:6"
+ }
+ ],
+ "domain": "0:0-0:6"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/value/value.assignment",
+ "languageId": "shellscript",
+ "facet": "value.assignment",
+ "code": "foo=0",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:4-0:5",
+ "removal": "0:3-0:5"
+ }
+ ],
+ "domain": "0:0-0:5"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/value/value.constant",
+ "languageId": "shellscript",
+ "facet": "value.constant",
+ "code": "readonly foo=0",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:13-0:14",
+ "removal": "0:12-0:14"
+ }
+ ],
+ "domain": "0:0-0:14"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/value/value.foreach",
+ "languageId": "shellscript",
+ "facet": "value.foreach",
+ "code": "for v in values; do :; done",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:9-0:15",
+ "removal": "0:8-0:15"
+ }
+ ],
+ "domain": "0:0-0:27"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/value/value.iteration.block",
+ "languageId": "shellscript",
+ "facet": "value.iteration.block",
+ "code": "foo() { }",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-0:9"
+ }
+ ],
+ "domain": "0:0-0:9"
+ },
+ {
+ "targets": [
+ {
+ "content": "0:7-0:8"
+ }
+ ],
+ "domain": "0:7-0:8"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/value/value.iteration.block3",
+ "languageId": "shellscript",
+ "facet": "value.iteration.block",
+ "code": "while true; do :; done",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-0:22"
+ }
+ ],
+ "domain": "0:0-0:22"
+ },
+ {
+ "targets": [
+ {
+ "content": "0:14-0:18"
+ }
+ ],
+ "domain": "0:14-0:18"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/value/value.iteration.document",
+ "languageId": "shellscript",
+ "facet": "value.iteration.document",
+ "code": "\ndeclare foo\n",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-2:0"
+ }
+ ],
+ "domain": "0:0-2:0"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/value/value.mapPair.iteration",
+ "languageId": "shellscript",
+ "facet": "value.mapPair.iteration",
+ "code": "foo=([\"aaa\"]=0 [\"bbb\"]=1)",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-0:25"
+ }
+ ],
+ "domain": "0:0-0:25"
+ },
+ {
+ "targets": [
+ {
+ "content": "0:5-0:24"
+ }
+ ],
+ "domain": "0:5-0:24"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/value/value.mapPair",
+ "languageId": "shellscript",
+ "facet": "value.mapPair",
+ "code": "foo=([\"aaa\"]=0 [\"bbb\"]=1)",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:4-0:25",
+ "removal": "0:3-0:25"
+ }
+ ],
+ "domain": "0:0-0:25"
+ },
+ {
+ "targets": [
+ {
+ "content": "0:13-0:14",
+ "removal": "0:13-0:14"
+ }
+ ],
+ "domain": "0:5-0:14"
+ },
+ {
+ "targets": [
+ {
+ "content": "0:23-0:24",
+ "removal": "0:23-0:24"
+ }
+ ],
+ "domain": "0:15-0:24"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/value/value.return",
+ "languageId": "shellscript",
+ "facet": "value.return",
+ "code": "foo() {\n return 0;\n}",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "1:11-1:12",
+ "removal": "1:10-1:12"
+ }
+ ],
+ "domain": "1:4-1:12"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/value/value.return2",
+ "languageId": "shellscript",
+ "facet": "value.return",
+ "code": "function foo {\n return 0;\n}",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "1:11-1:12",
+ "removal": "1:10-1:12"
+ }
+ ],
+ "domain": "1:4-1:12"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/value/value.switch",
+ "languageId": "shellscript",
+ "facet": "value.switch",
+ "code": "case $foo in esac",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:5-0:9",
+ "removal": "0:5-0:10"
+ }
+ ],
+ "domain": "0:0-0:17"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/value/value.variable",
+ "languageId": "shellscript",
+ "facet": "value.variable",
+ "code": "local foo=0",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:10-0:11",
+ "removal": "0:9-0:11"
+ }
+ ],
+ "domain": "0:0-0:11"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/value/value.variable2",
+ "languageId": "shellscript",
+ "facet": "value.variable",
+ "code": "declare foo=0",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:12-0:13",
+ "removal": "0:11-0:13"
+ }
+ ],
+ "domain": "0:0-0:13"
+ }
+ ]
+ }
+]
diff --git a/packages/app-web-docs/src/docs/user/languages/shellscript.mdx b/packages/app-web-docs/src/docs/user/languages/shellscript.mdx
new file mode 100644
index 0000000000..6818b739e6
--- /dev/null
+++ b/packages/app-web-docs/src/docs/user/languages/shellscript.mdx
@@ -0,0 +1,592 @@
+import { ScopeVisualizer, ScopeVisualizerOptions, ScopeVisualizerProvider } from "@site/src/docs/components/ScopeVisualizer";
+import scopeTests from "./fixtures/shellscript.json";
+
+# Shell Script
+
+
+
+Below are visualizations of all our scope tests for this language. These were created primarily for testing purposes rather than as documentation. There are quite a few, and they may feel a bit overwhelming from a documentation standpoint.
+
+## Scopes
+
+
+
+### Argument list
+
+#### 1. Argument list: Actual empty
+
+An empty list of arguments in a function call. Insertion delimiter should be empty.
+
+
+
+#### 2. Argument list: Actual multi line
+
+A multi-line list of arguments in a function call. Insertion delimiter should include a newline.
+
+
+
+#### 3. Argument list: Actual single line
+
+A single-line list of arguments in a function call
+
+
+
+### Argument or parameter
+
+#### 1. Argument: Actual multi line
+
+A multi-line argument in a function call. Insertion delimiter should include a newline.
+
+
+
+#### 2. Argument: Actual single line
+
+A single-line argument in a function call
+
+
+
+#### 3. Argument: Actual (iteration)
+
+Iteration scope for arguments in a function call: the argument list. The domain should be the entire function call.
+
+
+
+### Branch
+
+#### 1. Branch: If
+
+An if branch
+
+
+
+#### 2. Branch: If elif else
+
+An if-elif-else branch. The removal range for the if branch should include the trailing `else` keyword.
+
+
+
+#### 3. Branch: If else
+
+An if-else branch
+
+
+
+#### 4. Branch: Switch case
+
+A case/default branch in a switch statement
+
+
+
+
+
+#### 5. Branch: Ternary
+
+A branch in a ternary expression
+
+
+
+#### 6. Branch: If (iteration)
+
+Iteration scope for if/elif/else branches: the if/elif/else statement.
+
+
+
+#### 7. Branch: Switch case (iteration)
+
+Iteration scope for case/default branches in a switch statement: the switch statement body.
+
+
+
+#### 8. Branch: Ternary (iteration)
+
+Iteration scope for ternary expression branches: the ternary expression.
+
+
+
+### Collection key
+
+#### 1. Key: Map pair
+
+Key (LHS) of a key-value pair in a map
+
+
+
+#### 2. Key: Map pair (iteration)
+
+Iteration scope for keys of key-value pairs in a map: should be between the braces.
+
+
+
+### Comment
+
+#### 1. Comment: Line
+
+A line comment
+
+
+
+### Condition
+
+#### 1. Condition: For
+
+A condition in a for loop
+
+
+
+#### 2. Condition: If
+
+A condition in an if statement
+
+
+
+#### 3. Condition: Switch case
+
+A condition in a switch statement
+
+
+
+#### 4. Condition: Ternary
+
+A condition in a ternary expression
+
+
+
+#### 5. Condition: While
+
+A condition in a while loop
+
+
+
+
+
+#### 6. Condition: Switch case (iteration)
+
+Iteration scope for conditions in a switch statement: the switch statement body.
+
+
+
+### Function call
+
+#### 1. Function call
+
+A function call
+
+
+
+
+
+### Function callee
+
+#### 1. Function callee
+
+The function being called in a function call
+
+
+
+
+
+### If statement
+
+#### 1. If statement
+
+An if statement
+
+
+
+### List
+
+#### 1. List
+
+A list/array
+
+
+
+### Map
+
+#### 1. Map
+
+A map/dictionary
+
+
+
+### Name
+
+#### 1. Name: Assignment
+
+Name (LHS) of an assignment statement
+
+
+
+#### 2. Name: Assignment compound
+
+Name (LHS) of a compound assignment statement, eg +=/-=
+
+
+
+#### 3. Name: Constant
+
+Name (LHS) of a constant declaration
+
+
+
+#### 4. Name: Foreach
+
+Iteration variable name in a for-each loop
+
+
+
+#### 5. Name: Function
+
+Name of a function declaration
+
+
+
+
+
+#### 6. Name: Variable initialized
+
+Name (LHS) of an initialized variable declaration
+
+
+
+
+
+#### 7. Name: Variable uninitialized
+
+Name (LHS) of an uninitialized variable declaration
+
+
+
+
+
+#### 8. Name (iteration block)
+
+Iteration scope for names: statement blocks (body of functions/if-statements/for-loops/etc).
+
+
+
+
+
+#### 9. Name (iteration document)
+
+Iteration scope for names: the entire document including leading and trailing empty lines.
+
+
+
+### Named function
+
+#### 1. Named function
+
+A named function declaration
+
+
+
+
+
+
+
+#### 2. Named function (iteration document)
+
+Iteration scope for named functions: the entire document including leading and trailing empty lines.
+
+
+
+### Regular expression
+
+#### 1. Regular expression
+
+A regular expression
+
+
+
+### Statement
+
+#### 1. Statement: Assignment
+
+An assignment statement
+
+
+
+#### 2. Statement: Assignment compound
+
+A compound assignment statement, eg +=/-=
+
+
+
+#### 3. Statement: Break
+
+A break statement
+
+
+
+#### 4. Statement: Constant
+
+A constant declaration
+
+
+
+#### 5. Statement: Continue
+
+A continue statement
+
+
+
+#### 6. Statement: For
+
+A for loop
+
+
+
+#### 7. Statement: Foreach
+
+A for-each loop
+
+
+
+#### 8. Statement: Function
+
+A named function declaration
+
+
+
+
+
+#### 9. Statement: Function call
+
+A function call statement
+
+
+
+
+
+#### 10. Statement: If
+
+An if/elif/else statement
+
+
+
+
+
+#### 11. Statement: Import
+
+An import statement
+
+
+
+#### 12. Statement: Return
+
+A return statement
+
+
+
+
+
+#### 13. Statement: Switch
+
+A switch statement
+
+
+
+#### 14. Statement: Update
+
+An update statement, eg ++/--
+
+
+
+#### 15. Statement: Variable initialized
+
+An initialized variable declaration
+
+
+
+
+
+#### 16. Statement: Variable uninitialized
+
+An uninitialized variable declaration
+
+
+
+#### 17. Statement: While
+
+A while loop
+
+
+
+
+
+#### 18. Statement (iteration block)
+
+Iteration scope for statements: statement blocks (body of functions/if-statements/for-loops/etc).
+
+
+
+
+
+#### 19. Statement (iteration document)
+
+Iteration scope for statements: the entire document including leading and trailing empty lines.
+
+
+
+### Value
+
+#### 1. Value: Assignment
+
+Value (RHS) of an assignment statement
+
+
+
+#### 2. Value: Assignment compound
+
+Value (RHS) of a compound assignment statement, eg +=/-=
+
+
+
+#### 3. Value: Constant
+
+Value (RHS) of a constant declaration
+
+
+
+#### 4. Value: Foreach
+
+Iterable in a for-each loop
+
+
+
+#### 5. Value: Map pair
+
+Value (RHS) of a key-value pair in a map
+
+
+
+#### 6. Value: Return
+
+Return value of a function
+
+
+
+
+
+#### 7. Value: Switch
+
+Value / subject of a switch statement
+
+
+
+#### 8. Value: Variable
+
+Value (RHS) of a variable declaration
+
+
+
+
+
+#### 9. Value (iteration block)
+
+Iteration scope for values: statement blocks (body of functions/if-statements/for-loops/etc).
+
+
+
+
+
+#### 10. Value (iteration document)
+
+Iteration scope for values: the entire document including leading and trailing empty lines.
+
+
+
+#### 11. Value: Map pair (iteration)
+
+Iteration scope for values of key-value pairs in a map: should be between the braces.
+
+
+
+## Internal scopes
+
+The following are internal scopes. They are not intended for user interaction or spoken use. These scopes exist solely for internal Cursorless functionality.
+
+### Interior
+
+#### 1. Interior: For
+
+The body of a for loop
+
+
+
+#### 2. Interior: Foreach
+
+The body of a for-each loop
+
+
+
+#### 3. Interior: Function
+
+The body of a function declaration
+
+
+
+
+
+#### 4. Interior: If
+
+The body of an if/elif/else branch
+
+
+
+#### 5. Interior: Switch
+
+The body of a switch statement
+
+
+
+#### 6. Interior: Switch case
+
+The body of a case/default branch in a switch statement
+
+
+
+#### 7. Interior: While
+
+The body of a while loop
+
+
+
+
+
+### String
+
+#### 1. String: Multi line
+
+A multi-line string
+
+
+
+#### 2. String: Single line
+
+A single-line string
+
+
+
+### Text fragment
+
+#### 1. Text fragment: Comment line
+
+Internally used text fragment consisting of a line comment
+
+
+
+#### 2. Text fragment: String multi line
+
+Internally used text fragment consisting of a multi-line string
+
+
+
+#### 3. Text fragment: String single line
+
+Internally used text fragment consisting of a single-line string
+
+
+
+
diff --git a/packages/app-web-docs/src/docs/user/scopes/argumentList.mdx b/packages/app-web-docs/src/docs/user/scopes/argumentList.mdx
index 5a81785acc..965e17ad88 100644
--- a/packages/app-web-docs/src/docs/user/scopes/argumentList.mdx
+++ b/packages/app-web-docs/src/docs/user/scopes/argumentList.mdx
@@ -225,6 +225,10 @@ Default: `arg list`
+##### Shell Script
+
+
+
##### Talon
@@ -549,6 +553,10 @@ Default: `arg list`
+##### Shell Script
+
+
+
### Argument list: Actual single line
A single-line list of arguments in a function call
@@ -623,6 +631,10 @@ Default: `arg list`
+##### Shell Script
+
+
+
##### Talon
diff --git a/packages/app-web-docs/src/docs/user/scopes/argumentOrParameter.mdx b/packages/app-web-docs/src/docs/user/scopes/argumentOrParameter.mdx
index d0eca0b6bb..211f1783b1 100644
--- a/packages/app-web-docs/src/docs/user/scopes/argumentOrParameter.mdx
+++ b/packages/app-web-docs/src/docs/user/scopes/argumentOrParameter.mdx
@@ -353,6 +353,10 @@ Default: `arg`
+##### Shell Script
+
+
+
### Argument: Actual single line
A single-line argument in a function call
@@ -445,6 +449,10 @@ Default: `arg`
+##### Shell Script
+
+
+
##### Talon
@@ -1013,6 +1021,10 @@ Default: `arg`
+##### Shell Script
+
+
+
##### Talon
diff --git a/packages/app-web-docs/src/docs/user/scopes/branch.mdx b/packages/app-web-docs/src/docs/user/scopes/branch.mdx
index 048d35a0cf..baa502a056 100644
--- a/packages/app-web-docs/src/docs/user/scopes/branch.mdx
+++ b/packages/app-web-docs/src/docs/user/scopes/branch.mdx
@@ -91,6 +91,10 @@ Default: `branch`
+##### Shell Script
+
+
+
### Branch: If elif else
An if-elif-else branch. The removal range for the if branch should include the trailing `else` keyword.
@@ -155,6 +159,10 @@ Default: `branch`
+##### Shell Script
+
+
+
### Branch: If else
An if-else branch
@@ -219,6 +227,10 @@ Default: `branch`
+##### Shell Script
+
+
+
### Branch: Loop
A for / while loop branch. For most languages this is not supported, but eg in Python you can have an else branch for a loop.
@@ -315,6 +327,12 @@ Default: `branch`
+##### Shell Script
+
+
+
+
+
### Branch: Ternary
A branch in a ternary expression
@@ -355,6 +373,10 @@ Default: `branch`
+##### Shell Script
+
+
+
### Branch: Try
A try/catch/finally branch
@@ -469,6 +491,10 @@ Default: `branch`
+##### Shell Script
+
+
+
### Branch: Loop (iteration)
Iteration scope for loop branches: the loop statement.
@@ -539,6 +565,10 @@ Default: `branch`
+##### Shell Script
+
+
+
### Branch: Ternary (iteration)
Iteration scope for ternary expression branches: the ternary expression.
@@ -579,6 +609,10 @@ Default: `branch`
+##### Shell Script
+
+
+
### Branch: Try (iteration)
Iteration scope for try/catch/finally branches: the try/catch/finally statement.
diff --git a/packages/app-web-docs/src/docs/user/scopes/collectionKey.mdx b/packages/app-web-docs/src/docs/user/scopes/collectionKey.mdx
index 2fcac46cf4..8f65b4494d 100644
--- a/packages/app-web-docs/src/docs/user/scopes/collectionKey.mdx
+++ b/packages/app-web-docs/src/docs/user/scopes/collectionKey.mdx
@@ -107,6 +107,10 @@ Default: `key`
+##### Shell Script
+
+
+
##### Talon list
@@ -181,6 +185,10 @@ Default: `key`
+##### Shell Script
+
+
+
##### Talon list
diff --git a/packages/app-web-docs/src/docs/user/scopes/comment.mdx b/packages/app-web-docs/src/docs/user/scopes/comment.mdx
index 4bc58fca3a..61fb07c692 100644
--- a/packages/app-web-docs/src/docs/user/scopes/comment.mdx
+++ b/packages/app-web-docs/src/docs/user/scopes/comment.mdx
@@ -195,6 +195,10 @@ Default: `comment`
+##### Shell Script
+
+
+
##### Talon list
diff --git a/packages/app-web-docs/src/docs/user/scopes/condition.mdx b/packages/app-web-docs/src/docs/user/scopes/condition.mdx
index 33d3922aee..d6d5a1bcaf 100644
--- a/packages/app-web-docs/src/docs/user/scopes/condition.mdx
+++ b/packages/app-web-docs/src/docs/user/scopes/condition.mdx
@@ -103,6 +103,10 @@ Default: `condition`
+##### Shell Script
+
+
+
### Condition: If
A condition in an if statement
@@ -171,6 +175,10 @@ Default: `condition`
+##### Shell Script
+
+
+
##### Talon
@@ -253,6 +261,10 @@ Default: `condition`
+##### Shell Script
+
+
+
### Condition: Ternary
A condition in a ternary expression
@@ -293,6 +305,10 @@ Default: `condition`
+##### Shell Script
+
+
+
### Condition: While
A condition in a while loop
@@ -349,6 +365,12 @@ Default: `condition`
+##### Shell Script
+
+
+
+
+
### Condition: Switch case (iteration)
Iteration scope for conditions in a switch statement: the switch statement body.
@@ -409,4 +431,8 @@ Default: `condition`
+##### Shell Script
+
+
+
diff --git a/packages/app-web-docs/src/docs/user/scopes/fixtures/argumentList.json b/packages/app-web-docs/src/docs/user/scopes/fixtures/argumentList.json
index cd775e34c2..95b14d421d 100644
--- a/packages/app-web-docs/src/docs/user/scopes/fixtures/argumentList.json
+++ b/packages/app-web-docs/src/docs/user/scopes/fixtures/argumentList.json
@@ -5415,6 +5415,57 @@
}
]
},
+ {
+ "name": "scopes/shellscript/argumentList.actual.empty",
+ "languageId": "shellscript",
+ "facet": "argumentList.actual.empty",
+ "code": "foo",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:3-0:3",
+ "removal": "0:3-0:3"
+ }
+ ],
+ "domain": "0:0-0:3"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/argumentList.actual.multiLine",
+ "languageId": "shellscript",
+ "facet": "argumentList.actual.multiLine",
+ "code": "foo aaa \\\n bbb",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:4-1:5",
+ "removal": "0:3-1:5"
+ }
+ ],
+ "domain": "0:0-1:5"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/argumentList.actual.singleLine",
+ "languageId": "shellscript",
+ "facet": "argumentList.actual.singleLine",
+ "code": "foo aaa bbb",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:4-0:11",
+ "removal": "0:3-0:11"
+ }
+ ],
+ "domain": "0:0-0:11"
+ }
+ ]
+ },
{
"name": "scopes/talon/argumentList/argumentList.actual.empty",
"languageId": "talon",
diff --git a/packages/app-web-docs/src/docs/user/scopes/fixtures/argumentOrParameter.json b/packages/app-web-docs/src/docs/user/scopes/fixtures/argumentOrParameter.json
index 132a82b39c..f89c2c6ff9 100644
--- a/packages/app-web-docs/src/docs/user/scopes/fixtures/argumentOrParameter.json
+++ b/packages/app-web-docs/src/docs/user/scopes/fixtures/argumentOrParameter.json
@@ -7658,6 +7658,74 @@
}
]
},
+ {
+ "name": "scopes/shellscript/argument/argument.actual.iteration",
+ "languageId": "shellscript",
+ "facet": "argument.actual.iteration",
+ "code": "foo aaa bbb",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:4-0:11"
+ }
+ ],
+ "domain": "0:0-0:11"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/argument/argument.actual.multiLine",
+ "languageId": "shellscript",
+ "facet": "argument.actual.multiLine",
+ "code": "foo aaa \\\n bbb",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:4-0:7",
+ "removal": "0:4-1:2"
+ }
+ ],
+ "domain": "0:4-0:7"
+ },
+ {
+ "targets": [
+ {
+ "content": "1:2-1:5",
+ "removal": "0:7-1:5"
+ }
+ ],
+ "domain": "1:2-1:5"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/argument/argument.actual.singleLine",
+ "languageId": "shellscript",
+ "facet": "argument.actual.singleLine",
+ "code": "foo aaa bbb",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:4-0:7",
+ "removal": "0:4-0:8"
+ }
+ ],
+ "domain": "0:4-0:7"
+ },
+ {
+ "targets": [
+ {
+ "content": "0:8-0:11",
+ "removal": "0:7-0:11"
+ }
+ ],
+ "domain": "0:8-0:11"
+ }
+ ]
+ },
{
"name": "scopes/talon/argument/argument.actual.iteration",
"languageId": "talon",
diff --git a/packages/app-web-docs/src/docs/user/scopes/fixtures/branch.json b/packages/app-web-docs/src/docs/user/scopes/fixtures/branch.json
index cb35cfaec7..7e7ad75716 100644
--- a/packages/app-web-docs/src/docs/user/scopes/fixtures/branch.json
+++ b/packages/app-web-docs/src/docs/user/scopes/fixtures/branch.json
@@ -3173,5 +3173,191 @@
"domain": "0:0-0:11"
}
]
+ },
+ {
+ "name": "scopes/shellscript/branch/branch.if.elif.else",
+ "languageId": "shellscript",
+ "facet": "branch.if.elif.else",
+ "code": "if true; then\n :\nelif false; then\n :\nelse\n :\nfi",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-1:5",
+ "removal": "0:0-2:2"
+ }
+ ],
+ "domain": "0:0-1:5"
+ },
+ {
+ "targets": [
+ {
+ "content": "2:0-3:5",
+ "removal": "2:0-4:0"
+ }
+ ],
+ "domain": "2:0-3:5"
+ },
+ {
+ "targets": [
+ {
+ "content": "4:0-5:5",
+ "removal": "4:0-6:0"
+ }
+ ],
+ "domain": "4:0-5:5"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/branch/branch.if.else",
+ "languageId": "shellscript",
+ "facet": "branch.if.else",
+ "code": "if true; then\n :\nelse\n :\nfi",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-1:5",
+ "removal": "0:0-2:0"
+ }
+ ],
+ "domain": "0:0-1:5"
+ },
+ {
+ "targets": [
+ {
+ "content": "2:0-3:5",
+ "removal": "2:0-4:0"
+ }
+ ],
+ "domain": "2:0-3:5"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/branch/branch.if.iteration",
+ "languageId": "shellscript",
+ "facet": "branch.if.iteration",
+ "code": "if true; then\nelif false; then\nelse\nfi",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-3:2"
+ }
+ ],
+ "domain": "0:0-3:2"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/branch/branch.if",
+ "languageId": "shellscript",
+ "facet": "branch.if",
+ "code": "if true; then :; fi",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-0:19",
+ "removal": "0:0-0:19"
+ }
+ ],
+ "domain": "0:0-0:19"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/branch/branch.switchCase.iteration",
+ "languageId": "shellscript",
+ "facet": "branch.switchCase.iteration",
+ "code": "case $foo in esac",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:12-0:13"
+ }
+ ],
+ "domain": "0:12-0:13"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/branch/branch.switchCase",
+ "languageId": "shellscript",
+ "facet": "branch.switchCase",
+ "code": "case $foo in\n 0) : ;;\nesac",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "1:4-1:11",
+ "removal": "1:0-2:0"
+ }
+ ],
+ "domain": "1:4-1:11"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/branch/branch.switchCase2",
+ "languageId": "shellscript",
+ "facet": "branch.switchCase",
+ "code": "case $foo in\n *) : ;;\nesac",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "1:4-1:11",
+ "removal": "1:0-2:0"
+ }
+ ],
+ "domain": "1:4-1:11"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/branch/branch.ternary.iteration",
+ "languageId": "shellscript",
+ "facet": "branch.ternary.iteration",
+ "code": "((true ? 0 : 1))",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:2-0:14"
+ }
+ ],
+ "domain": "0:2-0:14"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/branch/branch.ternary",
+ "languageId": "shellscript",
+ "facet": "branch.ternary",
+ "code": "((true ? 0 : 1))",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:9-0:10",
+ "removal": "0:9-0:11"
+ }
+ ],
+ "domain": "0:9-0:10"
+ },
+ {
+ "targets": [
+ {
+ "content": "0:13-0:14",
+ "removal": "0:12-0:14"
+ }
+ ],
+ "domain": "0:13-0:14"
+ }
+ ]
}
]
diff --git a/packages/app-web-docs/src/docs/user/scopes/fixtures/collectionKey.json b/packages/app-web-docs/src/docs/user/scopes/fixtures/collectionKey.json
index f9b4330b3a..dfa4bed4ba 100644
--- a/packages/app-web-docs/src/docs/user/scopes/fixtures/collectionKey.json
+++ b/packages/app-web-docs/src/docs/user/scopes/fixtures/collectionKey.json
@@ -671,6 +671,48 @@
}
]
},
+ {
+ "name": "scopes/shellscript/key.mapPair.iteration",
+ "languageId": "shellscript",
+ "facet": "key.mapPair.iteration",
+ "code": "foo=([\"aaa\"]=0 [\"bbb\"]=1)",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:5-0:24"
+ }
+ ],
+ "domain": "0:5-0:24"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/key.mapPair",
+ "languageId": "shellscript",
+ "facet": "key.mapPair",
+ "code": "foo=([\"aaa\"]=0 [\"bbb\"]=1)",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:6-0:11",
+ "removal": "0:6-0:11"
+ }
+ ],
+ "domain": "0:5-0:14"
+ },
+ {
+ "targets": [
+ {
+ "content": "0:16-0:21",
+ "removal": "0:16-0:21"
+ }
+ ],
+ "domain": "0:15-0:24"
+ }
+ ]
+ },
{
"name": "scopes/talon/key/key.mapPair.iteration",
"languageId": "talon",
diff --git a/packages/app-web-docs/src/docs/user/scopes/fixtures/comment.json b/packages/app-web-docs/src/docs/user/scopes/fixtures/comment.json
index dc2fcfef7e..59bfe0a6fe 100644
--- a/packages/app-web-docs/src/docs/user/scopes/fixtures/comment.json
+++ b/packages/app-web-docs/src/docs/user/scopes/fixtures/comment.json
@@ -696,6 +696,23 @@
}
]
},
+ {
+ "name": "scopes/shellscript/comment.line",
+ "languageId": "shellscript",
+ "facet": "comment.line",
+ "code": "# Hello world",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-0:13",
+ "removal": "0:0-0:13"
+ }
+ ],
+ "domain": "0:0-0:13"
+ }
+ ]
+ },
{
"name": "scopes/talon/comment.line",
"languageId": "talon",
diff --git a/packages/app-web-docs/src/docs/user/scopes/fixtures/condition.json b/packages/app-web-docs/src/docs/user/scopes/fixtures/condition.json
index 0383798f75..d47bb1f43c 100644
--- a/packages/app-web-docs/src/docs/user/scopes/fixtures/condition.json
+++ b/packages/app-web-docs/src/docs/user/scopes/fixtures/condition.json
@@ -1717,6 +1717,133 @@
}
]
},
+ {
+ "name": "scopes/shellscript/condition/condition.for",
+ "languageId": "shellscript",
+ "facet": "condition.for",
+ "code": "for ((i = 0; i < 2; i++)); do :; done",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:13-0:18",
+ "removal": "0:12-0:18"
+ }
+ ],
+ "domain": "0:0-0:37"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/condition/condition.if",
+ "languageId": "shellscript",
+ "facet": "condition.if",
+ "code": "if true; then\nelif false; then\nelse\nfi",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:3-0:7",
+ "removal": "0:2-0:7"
+ }
+ ],
+ "domain": "0:0-3:2"
+ },
+ {
+ "targets": [
+ {
+ "content": "1:5-1:10",
+ "removal": "1:4-1:10"
+ }
+ ],
+ "domain": "1:0-1:16"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/condition/condition.switchCase.iteration",
+ "languageId": "shellscript",
+ "facet": "condition.switchCase.iteration",
+ "code": "case $foo in esac",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:12-0:13"
+ }
+ ],
+ "domain": "0:12-0:13"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/condition/condition.switchCase",
+ "languageId": "shellscript",
+ "facet": "condition.switchCase",
+ "code": "case $foo in\n 0) : ;;\nesac",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "1:2-1:3",
+ "removal": "1:0-1:3"
+ }
+ ],
+ "domain": "1:2-1:9"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/condition/condition.ternary",
+ "languageId": "shellscript",
+ "facet": "condition.ternary",
+ "code": "((true ? 0 : 1))",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:2-0:6",
+ "removal": "0:2-0:7"
+ }
+ ],
+ "domain": "0:2-0:14"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/condition/condition.while",
+ "languageId": "shellscript",
+ "facet": "condition.while",
+ "code": "while true; do :; done",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:6-0:10",
+ "removal": "0:5-0:10"
+ }
+ ],
+ "domain": "0:0-0:22"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/condition/condition.while2",
+ "languageId": "shellscript",
+ "facet": "condition.while",
+ "code": "until true; do :; done",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:6-0:10",
+ "removal": "0:5-0:10"
+ }
+ ],
+ "domain": "0:0-0:22"
+ }
+ ]
+ },
{
"name": "scopes/talon/condition.if",
"languageId": "talon",
diff --git a/packages/app-web-docs/src/docs/user/scopes/fixtures/functionCall.json b/packages/app-web-docs/src/docs/user/scopes/fixtures/functionCall.json
index 7495b02342..fdc04209ec 100644
--- a/packages/app-web-docs/src/docs/user/scopes/fixtures/functionCall.json
+++ b/packages/app-web-docs/src/docs/user/scopes/fixtures/functionCall.json
@@ -1349,6 +1349,40 @@
}
]
},
+ {
+ "name": "scopes/shellscript/functionCall",
+ "languageId": "shellscript",
+ "facet": "functionCall",
+ "code": "foo",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-0:3",
+ "removal": "0:0-0:3"
+ }
+ ],
+ "domain": "0:0-0:3"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/functionCall2",
+ "languageId": "shellscript",
+ "facet": "functionCall",
+ "code": "foo aaa bbb",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-0:11",
+ "removal": "0:0-0:11"
+ }
+ ],
+ "domain": "0:0-0:11"
+ }
+ ]
+ },
{
"name": "scopes/talon/functionCall.method",
"languageId": "talon",
diff --git a/packages/app-web-docs/src/docs/user/scopes/fixtures/functionCallee.json b/packages/app-web-docs/src/docs/user/scopes/fixtures/functionCallee.json
index 7f87206203..6dd457b98e 100644
--- a/packages/app-web-docs/src/docs/user/scopes/fixtures/functionCallee.json
+++ b/packages/app-web-docs/src/docs/user/scopes/fixtures/functionCallee.json
@@ -1349,6 +1349,40 @@
}
]
},
+ {
+ "name": "scopes/shellscript/functionCallee",
+ "languageId": "shellscript",
+ "facet": "functionCallee",
+ "code": "foo",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-0:3",
+ "removal": "0:0-0:3"
+ }
+ ],
+ "domain": "0:0-0:3"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/functionCallee2",
+ "languageId": "shellscript",
+ "facet": "functionCallee",
+ "code": "foo aaa bbb",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-0:3",
+ "removal": "0:0-0:4"
+ }
+ ],
+ "domain": "0:0-0:11"
+ }
+ ]
+ },
{
"name": "scopes/talon/functionCallee.method",
"languageId": "talon",
diff --git a/packages/app-web-docs/src/docs/user/scopes/fixtures/ifStatement.json b/packages/app-web-docs/src/docs/user/scopes/fixtures/ifStatement.json
index fc4b6e49d4..9789c6912b 100644
--- a/packages/app-web-docs/src/docs/user/scopes/fixtures/ifStatement.json
+++ b/packages/app-web-docs/src/docs/user/scopes/fixtures/ifStatement.json
@@ -271,6 +271,23 @@
}
]
},
+ {
+ "name": "scopes/shellscript/ifStatement",
+ "languageId": "shellscript",
+ "facet": "ifStatement",
+ "code": "if true; then\nelif false; then\nelse\nfi",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-3:2",
+ "removal": "0:0-3:2"
+ }
+ ],
+ "domain": "0:0-3:2"
+ }
+ ]
+ },
{
"name": "scopes/talon/ifStatement",
"languageId": "talon",
diff --git a/packages/app-web-docs/src/docs/user/scopes/fixtures/list.json b/packages/app-web-docs/src/docs/user/scopes/fixtures/list.json
index 9882297992..f81dd46a06 100644
--- a/packages/app-web-docs/src/docs/user/scopes/fixtures/list.json
+++ b/packages/app-web-docs/src/docs/user/scopes/fixtures/list.json
@@ -475,6 +475,23 @@
}
]
},
+ {
+ "name": "scopes/shellscript/list",
+ "languageId": "shellscript",
+ "facet": "list",
+ "code": "foo=(aaa bbb)",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:4-0:13",
+ "removal": "0:4-0:13"
+ }
+ ],
+ "domain": "0:4-0:13"
+ }
+ ]
+ },
{
"name": "scopes/yaml/list",
"languageId": "yaml",
diff --git a/packages/app-web-docs/src/docs/user/scopes/fixtures/map.json b/packages/app-web-docs/src/docs/user/scopes/fixtures/map.json
index 5176eb1081..5dcd665e45 100644
--- a/packages/app-web-docs/src/docs/user/scopes/fixtures/map.json
+++ b/packages/app-web-docs/src/docs/user/scopes/fixtures/map.json
@@ -314,6 +314,23 @@
}
]
},
+ {
+ "name": "scopes/shellscript/map",
+ "languageId": "shellscript",
+ "facet": "map",
+ "code": "foo=([\"aaa\"]=0 [\"bbb\"]=1)",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:4-0:25",
+ "removal": "0:4-0:25"
+ }
+ ],
+ "domain": "0:4-0:25"
+ }
+ ]
+ },
{
"name": "scopes/yaml/map",
"languageId": "yaml",
diff --git a/packages/app-web-docs/src/docs/user/scopes/fixtures/name.json b/packages/app-web-docs/src/docs/user/scopes/fixtures/name.json
index e12e130fe9..e2d0b04bd6 100644
--- a/packages/app-web-docs/src/docs/user/scopes/fixtures/name.json
+++ b/packages/app-web-docs/src/docs/user/scopes/fixtures/name.json
@@ -11957,6 +11957,240 @@
}
]
},
+ {
+ "name": "scopes/shellscript/name/name.assignment.compound",
+ "languageId": "shellscript",
+ "facet": "name.assignment.compound",
+ "code": "foo+=0",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-0:3",
+ "removal": "0:0-0:5"
+ }
+ ],
+ "domain": "0:0-0:6"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/name/name.assignment",
+ "languageId": "shellscript",
+ "facet": "name.assignment",
+ "code": "foo=0",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-0:3",
+ "removal": "0:0-0:4"
+ }
+ ],
+ "domain": "0:0-0:5"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/name/name.constant",
+ "languageId": "shellscript",
+ "facet": "name.constant",
+ "code": "readonly foo=0",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:9-0:12",
+ "removal": "0:0-0:13"
+ }
+ ],
+ "domain": "0:0-0:14"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/name/name.foreach",
+ "languageId": "shellscript",
+ "facet": "name.foreach",
+ "code": "for v in values; do :; done",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:4-0:5",
+ "removal": "0:4-0:6"
+ }
+ ],
+ "domain": "0:0-0:27"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/name/name.function",
+ "languageId": "shellscript",
+ "facet": "name.function",
+ "code": "foo() {}",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-0:3",
+ "removal": "0:0-0:3"
+ }
+ ],
+ "domain": "0:0-0:8"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/name/name.function2",
+ "languageId": "shellscript",
+ "facet": "name.function",
+ "code": "function foo {}",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:9-0:12",
+ "removal": "0:9-0:13"
+ }
+ ],
+ "domain": "0:0-0:15"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/name/name.iteration.block",
+ "languageId": "shellscript",
+ "facet": "name.iteration.block",
+ "code": "foo() { }",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-0:9"
+ }
+ ],
+ "domain": "0:0-0:9"
+ },
+ {
+ "targets": [
+ {
+ "content": "0:7-0:8"
+ }
+ ],
+ "domain": "0:7-0:8"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/name/name.iteration.block3",
+ "languageId": "shellscript",
+ "facet": "name.iteration.block",
+ "code": "while true; do :; done",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-0:22"
+ }
+ ],
+ "domain": "0:0-0:22"
+ },
+ {
+ "targets": [
+ {
+ "content": "0:14-0:18"
+ }
+ ],
+ "domain": "0:14-0:18"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/name/name.iteration.document",
+ "languageId": "shellscript",
+ "facet": "name.iteration.document",
+ "code": "\ndeclare foo\n",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-2:0"
+ }
+ ],
+ "domain": "0:0-2:0"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/name/name.variable.initialized",
+ "languageId": "shellscript",
+ "facet": "name.variable.initialized",
+ "code": "local foo=0",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:6-0:9",
+ "removal": "0:0-0:10"
+ }
+ ],
+ "domain": "0:0-0:11"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/name/name.variable.initialized2",
+ "languageId": "shellscript",
+ "facet": "name.variable.initialized",
+ "code": "declare foo=0",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:8-0:11",
+ "removal": "0:0-0:12"
+ }
+ ],
+ "domain": "0:0-0:13"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/name/name.variable.uninitialized",
+ "languageId": "shellscript",
+ "facet": "name.variable.uninitialized",
+ "code": "declare foo",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:8-0:11",
+ "removal": "0:7-0:11"
+ }
+ ],
+ "domain": "0:0-0:11"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/name/name.variable.uninitialized2",
+ "languageId": "shellscript",
+ "facet": "name.variable.uninitialized",
+ "code": "local foo",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:6-0:9",
+ "removal": "0:5-0:9"
+ }
+ ],
+ "domain": "0:0-0:9"
+ }
+ ]
+ },
{
"name": "scopes/talon/name/name.assignment",
"languageId": "talon",
diff --git a/packages/app-web-docs/src/docs/user/scopes/fixtures/namedFunction.json b/packages/app-web-docs/src/docs/user/scopes/fixtures/namedFunction.json
index e40d5075bd..5e6d39ad84 100644
--- a/packages/app-web-docs/src/docs/user/scopes/fixtures/namedFunction.json
+++ b/packages/app-web-docs/src/docs/user/scopes/fixtures/namedFunction.json
@@ -1893,6 +1893,73 @@
}
]
},
+ {
+ "name": "scopes/shellscript/namedFunction/namedFunction.iteration.document",
+ "languageId": "shellscript",
+ "facet": "namedFunction.iteration.document",
+ "code": "\nfoo() {}\n",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-2:0"
+ }
+ ],
+ "domain": "0:0-2:0"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/namedFunction/namedFunction",
+ "languageId": "shellscript",
+ "facet": "namedFunction",
+ "code": "foo() {}",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-0:8",
+ "removal": "0:0-0:8"
+ }
+ ],
+ "domain": "0:0-0:8"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/namedFunction/namedFunction2",
+ "languageId": "shellscript",
+ "facet": "namedFunction",
+ "code": "function foo {}",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-0:15",
+ "removal": "0:0-0:15"
+ }
+ ],
+ "domain": "0:0-0:15"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/namedFunction/namedFunction3",
+ "languageId": "shellscript",
+ "facet": "namedFunction",
+ "code": "function foo() {}",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-0:17",
+ "removal": "0:0-0:17"
+ }
+ ],
+ "domain": "0:0-0:17"
+ }
+ ]
+ },
{
"name": "scopes/typescript.core/namedFunction/namedFunction.constructor",
"languageId": "typescript.core",
diff --git a/packages/app-web-docs/src/docs/user/scopes/fixtures/regularExpression.json b/packages/app-web-docs/src/docs/user/scopes/fixtures/regularExpression.json
index 8b16de0bf2..1623983a7f 100644
--- a/packages/app-web-docs/src/docs/user/scopes/fixtures/regularExpression.json
+++ b/packages/app-web-docs/src/docs/user/scopes/fixtures/regularExpression.json
@@ -32,5 +32,22 @@
"domain": "0:0-0:8"
}
]
+ },
+ {
+ "name": "scopes/shellscript/regularExpression",
+ "languageId": "shellscript",
+ "facet": "regularExpression",
+ "code": "[[ $foo =~ ^\\w+$ ]]",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:11-0:16",
+ "removal": "0:11-0:17"
+ }
+ ],
+ "domain": "0:11-0:16"
+ }
+ ]
}
]
diff --git a/packages/app-web-docs/src/docs/user/scopes/fixtures/statement.json b/packages/app-web-docs/src/docs/user/scopes/fixtures/statement.json
index 6aad6cfbe9..fc80eec426 100644
--- a/packages/app-web-docs/src/docs/user/scopes/fixtures/statement.json
+++ b/packages/app-web-docs/src/docs/user/scopes/fixtures/statement.json
@@ -10592,6 +10592,569 @@
}
]
},
+ {
+ "name": "scopes/shellscript/statement/statement.assignment.compound",
+ "languageId": "shellscript",
+ "facet": "statement.assignment.compound",
+ "code": "foo+=1",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-0:6",
+ "removal": "0:0-0:6"
+ }
+ ],
+ "domain": "0:0-0:6"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/statement/statement.assignment",
+ "languageId": "shellscript",
+ "facet": "statement.assignment",
+ "code": "foo=0",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-0:5",
+ "removal": "0:0-0:5"
+ }
+ ],
+ "domain": "0:0-0:5"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/statement/statement.break",
+ "languageId": "shellscript",
+ "facet": "statement.break",
+ "code": "while true; do\n break\ndone",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-2:4",
+ "removal": "0:0-2:4"
+ }
+ ],
+ "domain": "0:0-2:4"
+ },
+ {
+ "targets": [
+ {
+ "content": "1:4-1:9",
+ "removal": "1:0-2:0"
+ }
+ ],
+ "domain": "1:4-1:9"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/statement/statement.constant",
+ "languageId": "shellscript",
+ "facet": "statement.constant",
+ "code": "readonly foo=0",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-0:14",
+ "removal": "0:0-0:14"
+ }
+ ],
+ "domain": "0:0-0:14"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/statement/statement.continue",
+ "languageId": "shellscript",
+ "facet": "statement.continue",
+ "code": "while true; do\n continue\ndone",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-2:4",
+ "removal": "0:0-2:4"
+ }
+ ],
+ "domain": "0:0-2:4"
+ },
+ {
+ "targets": [
+ {
+ "content": "1:4-1:12",
+ "removal": "1:0-2:0"
+ }
+ ],
+ "domain": "1:4-1:12"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/statement/statement.for",
+ "languageId": "shellscript",
+ "facet": "statement.for",
+ "code": "for ((i = 0; i < 2; i++)); do :; done",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-0:37",
+ "removal": "0:0-0:37"
+ }
+ ],
+ "domain": "0:0-0:37"
+ },
+ {
+ "targets": [
+ {
+ "content": "0:30-0:31",
+ "removal": "0:29-0:31"
+ }
+ ],
+ "domain": "0:30-0:31"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/statement/statement.foreach",
+ "languageId": "shellscript",
+ "facet": "statement.foreach",
+ "code": "for v in values; do :; done",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-0:27",
+ "removal": "0:0-0:27"
+ }
+ ],
+ "domain": "0:0-0:27"
+ },
+ {
+ "targets": [
+ {
+ "content": "0:20-0:21",
+ "removal": "0:19-0:21"
+ }
+ ],
+ "domain": "0:20-0:21"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/statement/statement.function",
+ "languageId": "shellscript",
+ "facet": "statement.function",
+ "code": "foo() {}",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-0:8",
+ "removal": "0:0-0:8"
+ }
+ ],
+ "domain": "0:0-0:8"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/statement/statement.function2",
+ "languageId": "shellscript",
+ "facet": "statement.function",
+ "code": "function foo {}",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-0:15",
+ "removal": "0:0-0:15"
+ }
+ ],
+ "domain": "0:0-0:15"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/statement/statement.functionCall",
+ "languageId": "shellscript",
+ "facet": "statement.functionCall",
+ "code": "foo",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-0:3",
+ "removal": "0:0-0:3"
+ }
+ ],
+ "domain": "0:0-0:3"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/statement/statement.functionCall2",
+ "languageId": "shellscript",
+ "facet": "statement.functionCall",
+ "code": "foo aaa bbb",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-0:11",
+ "removal": "0:0-0:11"
+ }
+ ],
+ "domain": "0:0-0:11"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/statement/statement.if",
+ "languageId": "shellscript",
+ "facet": "statement.if",
+ "code": "if true; then\nelif false; then\nelse\nfi",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-3:2",
+ "removal": "0:0-3:2"
+ }
+ ],
+ "domain": "0:0-3:2"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/statement/statement.if2",
+ "languageId": "shellscript",
+ "facet": "statement.if",
+ "code": "if foo; then\n aaa\n bbb\nelif baz; then\n ccc\n ddd\nfi",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-6:2",
+ "removal": "0:0-6:2"
+ }
+ ],
+ "domain": "0:0-6:2"
+ },
+ {
+ "targets": [
+ {
+ "content": "1:4-1:7",
+ "removal": "1:0-2:0"
+ }
+ ],
+ "domain": "1:4-1:7"
+ },
+ {
+ "targets": [
+ {
+ "content": "2:4-2:7",
+ "removal": "2:0-3:0"
+ }
+ ],
+ "domain": "2:4-2:7"
+ },
+ {
+ "targets": [
+ {
+ "content": "4:4-4:7",
+ "removal": "4:0-5:0"
+ }
+ ],
+ "domain": "4:4-4:7"
+ },
+ {
+ "targets": [
+ {
+ "content": "5:4-5:7",
+ "removal": "5:0-6:0"
+ }
+ ],
+ "domain": "5:4-5:7"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/statement/statement.import",
+ "languageId": "shellscript",
+ "facet": "statement.import",
+ "code": "source foo.sh",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-0:13",
+ "removal": "0:0-0:13"
+ }
+ ],
+ "domain": "0:0-0:13"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/statement/statement.iteration.block",
+ "languageId": "shellscript",
+ "facet": "statement.iteration.block",
+ "code": "foo() { }",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-0:9"
+ }
+ ],
+ "domain": "0:0-0:9"
+ },
+ {
+ "targets": [
+ {
+ "content": "0:7-0:8"
+ }
+ ],
+ "domain": "0:7-0:8"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/statement/statement.iteration.block3",
+ "languageId": "shellscript",
+ "facet": "statement.iteration.block",
+ "code": "while true; do :; done",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-0:22"
+ }
+ ],
+ "domain": "0:0-0:22"
+ },
+ {
+ "targets": [
+ {
+ "content": "0:14-0:18"
+ }
+ ],
+ "domain": "0:14-0:18"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/statement/statement.iteration.document",
+ "languageId": "shellscript",
+ "facet": "statement.iteration.document",
+ "code": "\ndeclare foo\n",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-2:0"
+ }
+ ],
+ "domain": "0:0-2:0"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/statement/statement.return",
+ "languageId": "shellscript",
+ "facet": "statement.return",
+ "code": "foo() {\n return 0\n}",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-2:1",
+ "removal": "0:0-2:1"
+ }
+ ],
+ "domain": "0:0-2:1"
+ },
+ {
+ "targets": [
+ {
+ "content": "1:4-1:12",
+ "removal": "1:0-2:0"
+ }
+ ],
+ "domain": "1:4-1:12"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/statement/statement.return2",
+ "languageId": "shellscript",
+ "facet": "statement.return",
+ "code": "function foo {\n return 0\n}",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-2:1",
+ "removal": "0:0-2:1"
+ }
+ ],
+ "domain": "0:0-2:1"
+ },
+ {
+ "targets": [
+ {
+ "content": "1:4-1:12",
+ "removal": "1:0-2:0"
+ }
+ ],
+ "domain": "1:4-1:12"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/statement/statement.switch",
+ "languageId": "shellscript",
+ "facet": "statement.switch",
+ "code": "case $foo in esac",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-0:17",
+ "removal": "0:0-0:17"
+ }
+ ],
+ "domain": "0:0-0:17"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/statement/statement.update",
+ "languageId": "shellscript",
+ "facet": "statement.update",
+ "code": "((foo++))",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-0:9",
+ "removal": "0:0-0:9"
+ }
+ ],
+ "domain": "0:0-0:9"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/statement/statement.variable.initialized",
+ "languageId": "shellscript",
+ "facet": "statement.variable.initialized",
+ "code": "local foo=0",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-0:11",
+ "removal": "0:0-0:11"
+ }
+ ],
+ "domain": "0:0-0:11"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/statement/statement.variable.initialized2",
+ "languageId": "shellscript",
+ "facet": "statement.variable.initialized",
+ "code": "declare foo=0",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-0:13",
+ "removal": "0:0-0:13"
+ }
+ ],
+ "domain": "0:0-0:13"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/statement/statement.variable.uninitialized",
+ "languageId": "shellscript",
+ "facet": "statement.variable.uninitialized",
+ "code": "declare foo",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-0:11",
+ "removal": "0:0-0:11"
+ }
+ ],
+ "domain": "0:0-0:11"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/statement/statement.while",
+ "languageId": "shellscript",
+ "facet": "statement.while",
+ "code": "while true; do :; done",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-0:22",
+ "removal": "0:0-0:22"
+ }
+ ],
+ "domain": "0:0-0:22"
+ },
+ {
+ "targets": [
+ {
+ "content": "0:15-0:16",
+ "removal": "0:14-0:16"
+ }
+ ],
+ "domain": "0:15-0:16"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/statement/statement.while2",
+ "languageId": "shellscript",
+ "facet": "statement.while",
+ "code": "until true; do :; done",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-0:22",
+ "removal": "0:0-0:22"
+ }
+ ],
+ "domain": "0:0-0:22"
+ },
+ {
+ "targets": [
+ {
+ "content": "0:15-0:16",
+ "removal": "0:14-0:16"
+ }
+ ],
+ "domain": "0:15-0:16"
+ }
+ ]
+ },
{
"name": "scopes/talon/statement.assignment",
"languageId": "talon",
diff --git a/packages/app-web-docs/src/docs/user/scopes/fixtures/value.json b/packages/app-web-docs/src/docs/user/scopes/fixtures/value.json
index 7e83d6749d..c868b52dbc 100644
--- a/packages/app-web-docs/src/docs/user/scopes/fixtures/value.json
+++ b/packages/app-web-docs/src/docs/user/scopes/fixtures/value.json
@@ -8544,6 +8544,282 @@
}
]
},
+ {
+ "name": "scopes/shellscript/value/value.assignment.compound",
+ "languageId": "shellscript",
+ "facet": "value.assignment.compound",
+ "code": "foo+=0",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:5-0:6",
+ "removal": "0:3-0:6"
+ }
+ ],
+ "domain": "0:0-0:6"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/value/value.assignment",
+ "languageId": "shellscript",
+ "facet": "value.assignment",
+ "code": "foo=0",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:4-0:5",
+ "removal": "0:3-0:5"
+ }
+ ],
+ "domain": "0:0-0:5"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/value/value.constant",
+ "languageId": "shellscript",
+ "facet": "value.constant",
+ "code": "readonly foo=0",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:13-0:14",
+ "removal": "0:12-0:14"
+ }
+ ],
+ "domain": "0:0-0:14"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/value/value.foreach",
+ "languageId": "shellscript",
+ "facet": "value.foreach",
+ "code": "for v in values; do :; done",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:9-0:15",
+ "removal": "0:8-0:15"
+ }
+ ],
+ "domain": "0:0-0:27"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/value/value.iteration.block",
+ "languageId": "shellscript",
+ "facet": "value.iteration.block",
+ "code": "foo() { }",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-0:9"
+ }
+ ],
+ "domain": "0:0-0:9"
+ },
+ {
+ "targets": [
+ {
+ "content": "0:7-0:8"
+ }
+ ],
+ "domain": "0:7-0:8"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/value/value.iteration.block3",
+ "languageId": "shellscript",
+ "facet": "value.iteration.block",
+ "code": "while true; do :; done",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-0:22"
+ }
+ ],
+ "domain": "0:0-0:22"
+ },
+ {
+ "targets": [
+ {
+ "content": "0:14-0:18"
+ }
+ ],
+ "domain": "0:14-0:18"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/value/value.iteration.document",
+ "languageId": "shellscript",
+ "facet": "value.iteration.document",
+ "code": "\ndeclare foo\n",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-2:0"
+ }
+ ],
+ "domain": "0:0-2:0"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/value/value.mapPair.iteration",
+ "languageId": "shellscript",
+ "facet": "value.mapPair.iteration",
+ "code": "foo=([\"aaa\"]=0 [\"bbb\"]=1)",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:0-0:25"
+ }
+ ],
+ "domain": "0:0-0:25"
+ },
+ {
+ "targets": [
+ {
+ "content": "0:5-0:24"
+ }
+ ],
+ "domain": "0:5-0:24"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/value/value.mapPair",
+ "languageId": "shellscript",
+ "facet": "value.mapPair",
+ "code": "foo=([\"aaa\"]=0 [\"bbb\"]=1)",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:4-0:25",
+ "removal": "0:3-0:25"
+ }
+ ],
+ "domain": "0:0-0:25"
+ },
+ {
+ "targets": [
+ {
+ "content": "0:13-0:14",
+ "removal": "0:13-0:14"
+ }
+ ],
+ "domain": "0:5-0:14"
+ },
+ {
+ "targets": [
+ {
+ "content": "0:23-0:24",
+ "removal": "0:23-0:24"
+ }
+ ],
+ "domain": "0:15-0:24"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/value/value.return",
+ "languageId": "shellscript",
+ "facet": "value.return",
+ "code": "foo() {\n return 0;\n}",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "1:11-1:12",
+ "removal": "1:10-1:12"
+ }
+ ],
+ "domain": "1:4-1:12"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/value/value.return2",
+ "languageId": "shellscript",
+ "facet": "value.return",
+ "code": "function foo {\n return 0;\n}",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "1:11-1:12",
+ "removal": "1:10-1:12"
+ }
+ ],
+ "domain": "1:4-1:12"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/value/value.switch",
+ "languageId": "shellscript",
+ "facet": "value.switch",
+ "code": "case $foo in esac",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:5-0:9",
+ "removal": "0:5-0:10"
+ }
+ ],
+ "domain": "0:0-0:17"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/value/value.variable",
+ "languageId": "shellscript",
+ "facet": "value.variable",
+ "code": "local foo=0",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:10-0:11",
+ "removal": "0:9-0:11"
+ }
+ ],
+ "domain": "0:0-0:11"
+ }
+ ]
+ },
+ {
+ "name": "scopes/shellscript/value/value.variable2",
+ "languageId": "shellscript",
+ "facet": "value.variable",
+ "code": "declare foo=0",
+ "scopes": [
+ {
+ "targets": [
+ {
+ "content": "0:12-0:13",
+ "removal": "0:11-0:13"
+ }
+ ],
+ "domain": "0:0-0:13"
+ }
+ ]
+ },
{
"name": "scopes/talon/value/value.assignment",
"languageId": "talon",
diff --git a/packages/app-web-docs/src/docs/user/scopes/functionCall.mdx b/packages/app-web-docs/src/docs/user/scopes/functionCall.mdx
index 5f59b79d62..97459f7fac 100644
--- a/packages/app-web-docs/src/docs/user/scopes/functionCall.mdx
+++ b/packages/app-web-docs/src/docs/user/scopes/functionCall.mdx
@@ -103,6 +103,12 @@ Default: `call`
+##### Shell Script
+
+
+
+
+
##### Talon
diff --git a/packages/app-web-docs/src/docs/user/scopes/functionCallee.mdx b/packages/app-web-docs/src/docs/user/scopes/functionCallee.mdx
index e872a7732d..ec58ebef2f 100644
--- a/packages/app-web-docs/src/docs/user/scopes/functionCallee.mdx
+++ b/packages/app-web-docs/src/docs/user/scopes/functionCallee.mdx
@@ -103,6 +103,12 @@ Default: `callee`
+##### Shell Script
+
+
+
+
+
##### Talon
diff --git a/packages/app-web-docs/src/docs/user/scopes/ifStatement.mdx b/packages/app-web-docs/src/docs/user/scopes/ifStatement.mdx
index 4e764215b5..85578983c4 100644
--- a/packages/app-web-docs/src/docs/user/scopes/ifStatement.mdx
+++ b/packages/app-web-docs/src/docs/user/scopes/ifStatement.mdx
@@ -95,6 +95,10 @@ Default: `if state`
+##### Shell Script
+
+
+
##### Talon
diff --git a/packages/app-web-docs/src/docs/user/scopes/list.mdx b/packages/app-web-docs/src/docs/user/scopes/list.mdx
index a12e4c84ba..7542c4c56c 100644
--- a/packages/app-web-docs/src/docs/user/scopes/list.mdx
+++ b/packages/app-web-docs/src/docs/user/scopes/list.mdx
@@ -121,6 +121,10 @@ Default: `list`
+##### Shell Script
+
+
+
##### YAML
diff --git a/packages/app-web-docs/src/docs/user/scopes/map.mdx b/packages/app-web-docs/src/docs/user/scopes/map.mdx
index db56a00d71..650e173dcb 100644
--- a/packages/app-web-docs/src/docs/user/scopes/map.mdx
+++ b/packages/app-web-docs/src/docs/user/scopes/map.mdx
@@ -93,6 +93,10 @@ Default: `map`
+##### Shell Script
+
+
+
##### YAML
diff --git a/packages/app-web-docs/src/docs/user/scopes/name.mdx b/packages/app-web-docs/src/docs/user/scopes/name.mdx
index e5f630966d..1763ce0176 100644
--- a/packages/app-web-docs/src/docs/user/scopes/name.mdx
+++ b/packages/app-web-docs/src/docs/user/scopes/name.mdx
@@ -417,6 +417,10 @@ Default: `name`
+##### Shell Script
+
+
+
##### Talon
@@ -469,6 +473,10 @@ Default: `name`
+##### Shell Script
+
+
+
### Name: Assignment destructuring
Name (LHS) of an assignment statement using a destructuring pattern
@@ -631,6 +639,10 @@ Default: `name`
+##### Shell Script
+
+
+
##### TypeScript
@@ -919,6 +931,10 @@ Default: `name`
+##### Shell Script
+
+
+
##### Talon
@@ -1025,6 +1041,12 @@ Default: `name`
+##### Shell Script
+
+
+
+
+
##### TypeScript
@@ -1345,6 +1367,12 @@ Default: `name`
+##### Shell Script
+
+
+
+
+
##### Talon list
@@ -1409,6 +1437,12 @@ Default: `name`
+##### Shell Script
+
+
+
+
+
##### TypeScript
@@ -1555,6 +1589,12 @@ Default: `name`
+##### Shell Script
+
+
+
+
+
##### Talon
@@ -1705,6 +1745,10 @@ Default: `name`
+##### Shell Script
+
+
+
##### Talon list
diff --git a/packages/app-web-docs/src/docs/user/scopes/namedFunction.mdx b/packages/app-web-docs/src/docs/user/scopes/namedFunction.mdx
index 00536a1513..fb8a5f4ba5 100644
--- a/packages/app-web-docs/src/docs/user/scopes/namedFunction.mdx
+++ b/packages/app-web-docs/src/docs/user/scopes/namedFunction.mdx
@@ -147,6 +147,14 @@ Default: `funk`
+##### Shell Script
+
+
+
+
+
+
+
##### TypeScript
@@ -405,4 +413,8 @@ Default: `funk`
+##### Shell Script
+
+
+
diff --git a/packages/app-web-docs/src/docs/user/scopes/regularExpression.mdx b/packages/app-web-docs/src/docs/user/scopes/regularExpression.mdx
index ac6162dca5..ea65782ec6 100644
--- a/packages/app-web-docs/src/docs/user/scopes/regularExpression.mdx
+++ b/packages/app-web-docs/src/docs/user/scopes/regularExpression.mdx
@@ -39,4 +39,8 @@ Default: `regex`
+##### Shell Script
+
+
+
diff --git a/packages/app-web-docs/src/docs/user/scopes/statement.mdx b/packages/app-web-docs/src/docs/user/scopes/statement.mdx
index 8676b6883f..5ebbd68846 100644
--- a/packages/app-web-docs/src/docs/user/scopes/statement.mdx
+++ b/packages/app-web-docs/src/docs/user/scopes/statement.mdx
@@ -89,6 +89,10 @@ Default: `state`
+##### Shell Script
+
+
+
##### Talon
@@ -141,6 +145,10 @@ Default: `state`
+##### Shell Script
+
+
+
### Statement: Assignment destructuring
An assignment statement using a destructuring pattern
@@ -217,6 +225,10 @@ Default: `state`
+##### Shell Script
+
+
+
### Statement: Class
A class/struct declaration
@@ -343,6 +355,10 @@ Default: `state`
+##### Shell Script
+
+
+
### Statement: Constructor
A constructor declaration
@@ -437,6 +453,10 @@ Default: `state`
+##### Shell Script
+
+
+
### Statement: Do while
A do-while loop
@@ -637,6 +657,10 @@ Default: `state`
+##### Shell Script
+
+
+
### Statement: Foreach
A for-each loop
@@ -699,6 +723,10 @@ Default: `state`
+##### Shell Script
+
+
+
##### Talon
@@ -801,6 +829,12 @@ Default: `state`
+##### Shell Script
+
+
+
+
+
### Statement: Function call
A function call statement
@@ -865,6 +899,12 @@ Default: `state`
+##### Shell Script
+
+
+
+
+
##### Talon
@@ -929,6 +969,12 @@ Default: `state`
+##### Shell Script
+
+
+
+
+
##### Talon
@@ -981,6 +1027,10 @@ Default: `state`
+##### Shell Script
+
+
+
### Statement: Interface
An interface declaration
@@ -1273,6 +1323,12 @@ Default: `state`
+##### Shell Script
+
+
+
+
+
### Statement: Static
A static initialization block in a class, eg `static { ... }`
@@ -1347,6 +1403,10 @@ Default: `state`
+##### Shell Script
+
+
+
### Statement: Throw
A throw statement
@@ -1537,6 +1597,10 @@ Default: `state`
+##### Shell Script
+
+
+
### Statement: Variable destructuring
A variable declaration using a destructuring pattern, eg `const { x, y } = point`
@@ -1633,6 +1697,12 @@ Default: `state`
+##### Shell Script
+
+
+
+
+
##### Talon list
@@ -1691,6 +1761,10 @@ Default: `state`
+##### Shell Script
+
+
+
### Statement: While
A while loop
@@ -1747,6 +1821,12 @@ Default: `state`
+##### Shell Script
+
+
+
+
+
### Statement: Yield
A yield statement
@@ -1913,6 +1993,12 @@ Default: `state`
+##### Shell Script
+
+
+
+
+
##### Talon
@@ -2053,6 +2139,10 @@ Default: `state`
+##### Shell Script
+
+
+
##### Talon list
diff --git a/packages/app-web-docs/src/docs/user/scopes/value.mdx b/packages/app-web-docs/src/docs/user/scopes/value.mdx
index c6982bdcdd..e5d2ff3778 100644
--- a/packages/app-web-docs/src/docs/user/scopes/value.mdx
+++ b/packages/app-web-docs/src/docs/user/scopes/value.mdx
@@ -305,6 +305,10 @@ Default: `value`
+##### Shell Script
+
+
+
##### Talon
@@ -361,6 +365,10 @@ Default: `value`
+##### Shell Script
+
+
+
### Value: Assignment destructuring
Value (RHS) of an assignment statement using a destructuring pattern
@@ -445,6 +453,10 @@ Default: `value`
+##### Shell Script
+
+
+
### Value: Field class
Value (RHS) of a field declaration in a class/struct
@@ -595,6 +607,10 @@ Default: `value`
+##### Shell Script
+
+
+
##### Talon
@@ -659,6 +675,10 @@ Default: `value`
+##### Shell Script
+
+
+
##### Talon list
@@ -749,6 +769,12 @@ Default: `value`
+##### Shell Script
+
+
+
+
+
### Value: Return lambda
Implicit return value of an anonymous function
@@ -861,6 +887,10 @@ Default: `value`
+##### Shell Script
+
+
+
### Value: Throw
Value of a throw statement
@@ -1033,6 +1063,12 @@ Default: `value`
+##### Shell Script
+
+
+
+
+
##### Talon list
@@ -1235,6 +1271,12 @@ Default: `value`
+##### Shell Script
+
+
+
+
+
##### Talon
@@ -1371,6 +1413,10 @@ Default: `value`
+##### Shell Script
+
+
+
##### Talon list
@@ -1659,6 +1705,10 @@ Default: `value`
+##### Shell Script
+
+
+
##### Talon list
diff --git a/packages/lib-common/src/references/languageReferences.ts b/packages/lib-common/src/references/languageReferences.ts
index 38783b0608..c8b6ad64be 100644
--- a/packages/lib-common/src/references/languageReferences.ts
+++ b/packages/lib-common/src/references/languageReferences.ts
@@ -32,6 +32,7 @@ export type LanguageId =
| "scala"
| "scm"
| "scss"
+ | "shellscript"
| "talon"
| "talon-list"
| "typescript"
@@ -127,6 +128,9 @@ export const languageReferences: Record = {
scss: {
name: "SCSS",
},
+ shellscript: {
+ name: "Shell Script",
+ },
talon: {
name: "Talon",
},
diff --git a/packages/lib-common/src/scopeSupportFacets/languageScopeSupport.ts b/packages/lib-common/src/scopeSupportFacets/languageScopeSupport.ts
index 1b8dad136b..fff865031c 100644
--- a/packages/lib-common/src/scopeSupportFacets/languageScopeSupport.ts
+++ b/packages/lib-common/src/scopeSupportFacets/languageScopeSupport.ts
@@ -27,6 +27,7 @@ import { scalaScopeSupport } from "./scala";
import { scmScopeSupport } from "./scm";
import type { LanguageScopeSupportFacetMap } from "./scopeSupportFacets.types";
import { scssScopeSupport } from "./scss";
+import { shellscriptScopeSupport } from "./shellscript";
import { talonScopeSupport } from "./talon";
import { talonListScopeSupport } from "./talonList";
import { typescriptScopeSupport } from "./typescript";
@@ -68,6 +69,7 @@ export const languageScopeSupport: Record<
scala: scalaScopeSupport,
scm: scmScopeSupport,
scss: scssScopeSupport,
+ shellscript: shellscriptScopeSupport,
"talon-list": talonListScopeSupport,
talon: talonScopeSupport,
typescript: typescriptScopeSupport,
diff --git a/packages/lib-common/src/scopeSupportFacets/shellscript.ts b/packages/lib-common/src/scopeSupportFacets/shellscript.ts
new file mode 100644
index 0000000000..1c60bbec90
--- /dev/null
+++ b/packages/lib-common/src/scopeSupportFacets/shellscript.ts
@@ -0,0 +1,367 @@
+/* eslint-disable @typescript-eslint/naming-convention */
+
+import type { LanguageScopeSupportFacetMap } from "./scopeSupportFacets.types";
+import { ScopeSupportFacetLevel } from "./scopeSupportFacets.types";
+
+const { supported, notApplicable } = ScopeSupportFacetLevel;
+
+export const shellscriptScopeSupport: LanguageScopeSupportFacetMap = {
+ list: supported,
+ regularExpression: supported,
+ map: supported,
+ ifStatement: supported,
+ functionCall: supported,
+ functionCallee: supported,
+ "comment.line": supported,
+
+ "argument.actual.singleLine": supported,
+ "argument.actual.multiLine": supported,
+ "argument.actual.iteration": supported,
+
+ "branch.if": supported,
+ "branch.if.elif.else": supported,
+ "branch.if.else": supported,
+ "branch.if.iteration": supported,
+ "branch.switchCase": supported,
+ "branch.switchCase.iteration": supported,
+ "branch.ternary": supported,
+ "branch.ternary.iteration": supported,
+
+ "condition.if": supported,
+ "condition.while": supported,
+ "condition.for": supported,
+ "condition.switchCase": supported,
+ "condition.switchCase.iteration": supported,
+ "condition.ternary": supported,
+
+ namedFunction: supported,
+ "namedFunction.iteration.document": supported,
+
+ "statement.function": supported,
+ "statement.functionCall": supported,
+ "statement.if": supported,
+ "statement.switch": supported,
+ "statement.for": supported,
+ "statement.foreach": supported,
+ "statement.while": supported,
+ "statement.variable.uninitialized": supported,
+ "statement.variable.initialized": supported,
+ "statement.constant": supported,
+ "statement.assignment": supported,
+ "statement.assignment.compound": supported,
+ "statement.return": supported,
+ "statement.break": supported,
+ "statement.continue": supported,
+ "statement.import": supported,
+ "statement.update": supported,
+ "statement.iteration.document": supported,
+ "statement.iteration.block": supported,
+
+ "string.singleLine": supported,
+ "string.multiLine": supported,
+
+ "textFragment.comment.line": supported,
+ "textFragment.string.singleLine": supported,
+ "textFragment.string.multiLine": supported,
+
+ "name.variable.uninitialized": supported,
+ "name.variable.initialized": supported,
+ "name.constant": supported,
+ "name.assignment": supported,
+ "name.assignment.compound": supported,
+ "name.foreach": supported,
+ "name.function": supported,
+ "name.iteration.document": supported,
+ "name.iteration.block": supported,
+
+ "value.variable": supported,
+ "value.constant": supported,
+ "value.assignment": supported,
+ "value.assignment.compound": supported,
+ "value.mapPair": supported,
+ "value.mapPair.iteration": supported,
+ "value.foreach": supported,
+ "value.return": supported,
+ "value.switch": supported,
+ "value.iteration.block": supported,
+ "value.iteration.document": supported,
+
+ "interior.function": supported,
+ "interior.if": supported,
+ "interior.switchCase": supported,
+ "interior.switch": supported,
+ "interior.for": supported,
+ "interior.foreach": supported,
+ "interior.while": supported,
+
+ "key.mapPair": supported,
+ "key.mapPair.iteration": supported,
+
+ "argumentList.actual.empty": supported,
+ "argumentList.actual.singleLine": supported,
+ "argumentList.actual.multiLine": supported,
+
+ /* NOT APPLICABLE */
+
+ // Classes, interfaces, methods, and constructors
+ "argument.actual.method.singleLine": notApplicable,
+ "argument.actual.method.multiLine": notApplicable,
+ "argument.actual.method.iteration": notApplicable,
+ "argument.actual.constructor.singleLine": notApplicable,
+ "argument.actual.constructor.multiLine": notApplicable,
+ "argument.actual.constructor.iteration": notApplicable,
+ "argument.formal.method.singleLine": notApplicable,
+ "argument.formal.method.multiLine": notApplicable,
+ "argument.formal.method.iteration": notApplicable,
+ "argument.formal.constructor.singleLine": notApplicable,
+ "argument.formal.constructor.multiLine": notApplicable,
+ "argument.formal.constructor.iteration": notApplicable,
+ "argumentList.actual.method.empty": notApplicable,
+ "argumentList.actual.method.singleLine": notApplicable,
+ "argumentList.actual.method.multiLine": notApplicable,
+ "argumentList.actual.constructor.empty": notApplicable,
+ "argumentList.actual.constructor.singleLine": notApplicable,
+ "argumentList.actual.constructor.multiLine": notApplicable,
+ "argumentList.formal.method.empty": notApplicable,
+ "argumentList.formal.method.singleLine": notApplicable,
+ "argumentList.formal.method.multiLine": notApplicable,
+ "argumentList.formal.constructor.empty": notApplicable,
+ "argumentList.formal.constructor.singleLine": notApplicable,
+ "argumentList.formal.constructor.multiLine": notApplicable,
+ class: notApplicable,
+ "class.iteration.document": notApplicable,
+ "class.iteration.class": notApplicable,
+ "functionCall.constructor": notApplicable,
+ "functionCall.method": notApplicable,
+ "functionCall.chain": notApplicable,
+ "functionCallee.constructor": notApplicable,
+ "functionCallee.method": notApplicable,
+ "functionCallee.chain": notApplicable,
+ "namedFunction.constructor": notApplicable,
+ "namedFunction.method": notApplicable,
+ "namedFunction.iteration.class": notApplicable,
+ "statement.class": notApplicable,
+ "statement.interface": notApplicable,
+ "statement.field.class": notApplicable,
+ "statement.field.interface": notApplicable,
+ "statement.constructor": notApplicable,
+ "statement.method": notApplicable,
+ "statement.method.interface": notApplicable,
+ "statement.static": notApplicable,
+ "statement.iteration.class": notApplicable,
+ "statement.iteration.interface": notApplicable,
+ "name.method": notApplicable,
+ "name.method.interface": notApplicable,
+ "name.constructor": notApplicable,
+ "name.class": notApplicable,
+ "name.interface": notApplicable,
+ "name.field.class": notApplicable,
+ "name.field.interface": notApplicable,
+ "name.argument.formal.method": notApplicable,
+ "name.argument.formal.method.iteration": notApplicable,
+ "name.argument.formal.constructor": notApplicable,
+ "name.argument.formal.constructor.iteration": notApplicable,
+ "name.iteration.class": notApplicable,
+ "name.iteration.interface": notApplicable,
+ "value.field.class": notApplicable,
+ "value.field.interface": notApplicable,
+ "value.argument.formal.method": notApplicable,
+ "value.argument.formal.method.iteration": notApplicable,
+ "value.argument.formal.constructor": notApplicable,
+ "value.argument.formal.constructor.iteration": notApplicable,
+ "value.iteration.class": notApplicable,
+ "type.return.method": notApplicable,
+ "type.field.class": notApplicable,
+ "type.field.interface": notApplicable,
+ "type.class": notApplicable,
+ "type.interface": notApplicable,
+ "type.argument.formal.method": notApplicable,
+ "type.argument.formal.method.iteration": notApplicable,
+ "type.argument.formal.constructor": notApplicable,
+ "type.argument.formal.constructor.iteration": notApplicable,
+ "type.iteration.class": notApplicable,
+ "type.iteration.interface": notApplicable,
+ "interior.class": notApplicable,
+ "interior.interface": notApplicable,
+ "interior.constructor": notApplicable,
+ "interior.method": notApplicable,
+ "interior.static": notApplicable,
+ fieldAccess: notApplicable,
+
+ // Enums
+ "argument.actual.enum.singleLine": notApplicable,
+ "argument.actual.enum.multiLine": notApplicable,
+ "argument.actual.enum.iteration": notApplicable,
+ "argumentList.actual.enum.empty": notApplicable,
+ "argumentList.actual.enum.singleLine": notApplicable,
+ "argumentList.actual.enum.multiLine": notApplicable,
+ "functionCall.enum": notApplicable,
+ "functionCallee.enum": notApplicable,
+ "statement.enum": notApplicable,
+ "name.enum": notApplicable,
+ "name.field.enum": notApplicable,
+ "name.iteration.enum": notApplicable,
+ "value.field.enum": notApplicable,
+ "value.iteration.enum": notApplicable,
+ "type.enum": notApplicable,
+ "interior.enum": notApplicable,
+
+ // Anonymous functions
+ anonymousFunction: notApplicable,
+ "argument.formal.lambda.singleLine": notApplicable,
+ "argument.formal.lambda.multiLine": notApplicable,
+ "argument.formal.lambda.iteration": notApplicable,
+ "argumentList.formal.lambda.empty": notApplicable,
+ "argumentList.formal.lambda.singleLine": notApplicable,
+ "argumentList.formal.lambda.multiLine": notApplicable,
+ "name.argument.formal.lambda": notApplicable,
+ "name.argument.formal.lambda.iteration": notApplicable,
+ "value.return.lambda": notApplicable,
+ "value.argument.formal.lambda": notApplicable,
+ "value.argument.formal.lambda.iteration": notApplicable,
+ "type.return.lambda": notApplicable,
+ "type.argument.formal.lambda": notApplicable,
+ "type.argument.formal.lambda.iteration": notApplicable,
+ "interior.lambda": notApplicable,
+
+ // Exceptions and try / catch
+ "argument.formal.catch": notApplicable,
+ "branch.try": notApplicable,
+ "branch.try.iteration": notApplicable,
+ "statement.try": notApplicable,
+ "statement.throw": notApplicable,
+ "name.argument.catch": notApplicable,
+ "value.throw": notApplicable,
+ "type.argument.catch": notApplicable,
+ "interior.try": notApplicable,
+
+ // Formal parameters and default argument values
+ "argument.formal.singleLine": notApplicable,
+ "argument.formal.multiLine": notApplicable,
+ "argument.formal.iteration": notApplicable,
+ "argumentList.formal.empty": notApplicable,
+ "argumentList.formal.singleLine": notApplicable,
+ "argumentList.formal.multiLine": notApplicable,
+ "name.argument.formal": notApplicable,
+ "name.argument.formal.iteration": notApplicable,
+ "value.argument.formal": notApplicable,
+ "value.argument.formal.iteration": notApplicable,
+ "type.argument.formal": notApplicable,
+ "type.argument.formal.iteration": notApplicable,
+
+ // Keyword arguments
+ "name.argument.actual": notApplicable,
+ "name.argument.actual.iteration": notApplicable,
+ "value.argument.actual": notApplicable,
+ "value.argument.actual.iteration": notApplicable,
+
+ // Pattern destructuring
+ "statement.variable.destructuring": notApplicable,
+ "statement.assignment.destructuring": notApplicable,
+ "name.variable.destructuring": notApplicable,
+ "name.assignment.destructuring": notApplicable,
+ "value.variable.destructuring": notApplicable,
+ "value.assignment.destructuring": notApplicable,
+
+ // Type aliases
+ "statement.typeAlias": notApplicable,
+ "name.typeAlias": notApplicable,
+ "value.typeAlias": notApplicable,
+ "type.alias": notApplicable,
+
+ // Type annotations and generic types
+ "functionCall.generic": notApplicable,
+ "functionCallee.generic": notApplicable,
+ "type.variable.uninitialized": notApplicable,
+ "type.variable.initialized": notApplicable,
+ "type.constant": notApplicable,
+ "type.return": notApplicable,
+ "type.foreach": notApplicable,
+ "type.cast": notApplicable,
+ "type.typeArgument": notApplicable,
+ "type.typeArgument.iteration": notApplicable,
+ "type.iteration.block": notApplicable,
+ "type.iteration.document": notApplicable,
+
+ // Element and tags
+ "textFragment.element": notApplicable,
+ "value.attribute": notApplicable,
+ "interior.element": notApplicable,
+ element: notApplicable,
+ tags: notApplicable,
+ startTag: notApplicable,
+ endTag: notApplicable,
+ attribute: notApplicable,
+ "key.attribute": notApplicable,
+
+ // Sections and document structure
+ section: notApplicable,
+ "section.iteration.document": notApplicable,
+ "section.iteration.parent": notApplicable,
+ chapter: notApplicable,
+ subSection: notApplicable,
+ subSubSection: notApplicable,
+ sectionLevelOne: notApplicable,
+ sectionLevelTwo: notApplicable,
+ sectionLevelThree: notApplicable,
+ sectionLevelFour: notApplicable,
+ sectionLevelFive: notApplicable,
+ sectionLevelSix: notApplicable,
+ namedParagraph: notApplicable,
+ subParagraph: notApplicable,
+ part: notApplicable,
+
+ // Notebook cells
+ "interior.cell": notApplicable,
+ notebookCell: notApplicable,
+
+ // Namespaces and package declarations
+ "statement.package": notApplicable,
+ "statement.namespace": notApplicable,
+ "name.namespace": notApplicable,
+ "interior.namespace": notApplicable,
+
+ // Resource management blocks
+ "statement.resource": notApplicable,
+ "name.resource": notApplicable,
+ "value.resource": notApplicable,
+ "type.resource": notApplicable,
+ "interior.resource": notApplicable,
+
+ // Generator yield
+ "statement.yield": notApplicable,
+ "value.yield": notApplicable,
+
+ // Do-while loops
+ "condition.doWhile": notApplicable,
+ "statement.doWhile": notApplicable,
+ "interior.doWhile": notApplicable,
+
+ // Loop else branches
+ "branch.loop": notApplicable,
+ "branch.loop.iteration": notApplicable,
+
+ // Block comments
+ "comment.block": notApplicable,
+ "textFragment.comment.block": notApplicable,
+
+ // Unenclosed comma-separated collections
+ "collectionItem.unenclosed.singleLine": notApplicable,
+ "collectionItem.unenclosed.multiLine": notApplicable,
+ "collectionItem.unenclosed.iteration": notApplicable,
+
+ // Commands (as in Talon); shell invocations use calls and callees.
+ command: notApplicable,
+ "statement.command": notApplicable,
+ "name.command": notApplicable,
+ "value.command": notApplicable,
+ "interior.command": notApplicable,
+
+ // Markup environments, selectors, units, and custom delimiter pairs
+ "statement.misc": notApplicable,
+ pairDelimiter: notApplicable,
+ disqualifyDelimiter: notApplicable,
+ environment: notApplicable,
+ selector: notApplicable,
+ unit: notApplicable,
+};
diff --git a/packages/lib-engine/src/languages/TreeSitterQuery/queryPredicateOperators.ts b/packages/lib-engine/src/languages/TreeSitterQuery/queryPredicateOperators.ts
index 796fcfce00..21d396057b 100644
--- a/packages/lib-engine/src/languages/TreeSitterQuery/queryPredicateOperators.ts
+++ b/packages/lib-engine/src/languages/TreeSitterQuery/queryPredicateOperators.ts
@@ -92,6 +92,23 @@ class NotParentType extends QueryPredicateOperator {
}
}
+/**
+ * A predicate operator that returns true if none of the node's direct children
+ * have any of the given types. For example, `(#not-child-type? @foo else_clause
+ * elif_clause)` rejects an if statement with an else or elif clause. Named and
+ * anonymous children are checked; descendants below the direct children are not
+ * checked.
+ */
+class NotChildType extends QueryPredicateOperator {
+ name = "not-child-type?" as const;
+ schema = z.tuple([q.node, q.string]).rest(q.string);
+ run(capture: MutableQueryCapture, ...types: string[]) {
+ return !getNode(capture).children.some((child) =>
+ types.includes(child.type),
+ );
+ }
+}
+
/**
* A predicate operator that returns true if the node is the nth child of its
* parent. For example, `(#is-nth-child? @foo 0)` will reject the match if the
@@ -211,7 +228,7 @@ class ShrinkToMatch extends QueryPredicateOperator {
const match = text.match(new RegExp(pattern, "dsu"));
if (match?.index == null) {
- throw new Error(`No match for pattern '${pattern}'`);
+ throw new Error(`No match for pattern '${pattern}' on text '${text}'`);
}
const offsets = match.indices?.groups?.keep ?? match.indices?.[0];
@@ -462,6 +479,7 @@ export const queryPredicateOperators = [
new TrimEnd(),
new DocumentRange(),
new NotParentType(),
+ new NotChildType(),
new IsNthChild(),
new ChildRange(),
new CharacterRange(),
diff --git a/resources/fixtures/recorded/languages/shellscript/changeThirdWordDash.yml b/resources/fixtures/recorded/languages/shellscript/changeThirdWordDash.yml
deleted file mode 100644
index 921a845de3..0000000000
--- a/resources/fixtures/recorded/languages/shellscript/changeThirdWordDash.yml
+++ /dev/null
@@ -1,31 +0,0 @@
-languageId: shellscript
-command:
- version: 7
- spokenForm: change third sub dash
- action:
- name: clearAndSetSelection
- target:
- type: primitive
- modifiers:
- - type: ordinalScope
- scopeType: {type: word}
- start: 2
- length: 1
- mark: {type: decoratedSymbol, symbolColor: default, character: '-'}
- usePrePhraseSnapshot: true
-initialState:
- documentContents: |2
- npm version patch --force --commit-hooks false --git-tag-version false
- selections:
- - anchor: {line: 1, character: 0}
- active: {line: 1, character: 0}
- marks:
- default.-:
- start: {line: 0, character: 48}
- end: {line: 0, character: 65}
-finalState:
- documentContents: |2
- npm version patch --force --commit-hooks false --git-tag- false
- selections:
- - anchor: {line: 0, character: 58}
- active: {line: 0, character: 58}
diff --git a/resources/fixtures/recorded/languages/shellscript/chuckFirstWordBat.yml b/resources/fixtures/recorded/languages/shellscript/chuckFirstWordBat.yml
deleted file mode 100644
index 68f6d0b8f1..0000000000
--- a/resources/fixtures/recorded/languages/shellscript/chuckFirstWordBat.yml
+++ /dev/null
@@ -1,31 +0,0 @@
-languageId: shellscript
-command:
- version: 7
- spokenForm: chuck first sub bat
- action:
- name: remove
- target:
- type: primitive
- modifiers:
- - type: ordinalScope
- scopeType: {type: word}
- start: 0
- length: 1
- mark: {type: decoratedSymbol, symbolColor: default, character: b}
- usePrePhraseSnapshot: true
-initialState:
- documentContents: |2
- npm version patch --foo-bar --force --commit-hooks false --git-tag-version false
- selections:
- - anchor: {line: 1, character: 0}
- active: {line: 1, character: 0}
- marks:
- default.b:
- start: {line: 0, character: 19}
- end: {line: 0, character: 28}
-finalState:
- documentContents: |2
- npm version patch --bar --force --commit-hooks false --git-tag-version false
- selections:
- - anchor: {line: 1, character: 0}
- active: {line: 1, character: 0}
diff --git a/resources/fixtures/recorded/languages/shellscript/chuckSecondWordCap.yml b/resources/fixtures/recorded/languages/shellscript/chuckSecondWordCap.yml
deleted file mode 100644
index 8745943452..0000000000
--- a/resources/fixtures/recorded/languages/shellscript/chuckSecondWordCap.yml
+++ /dev/null
@@ -1,31 +0,0 @@
-languageId: shellscript
-command:
- version: 7
- spokenForm: chuck second sub cap
- action:
- name: remove
- target:
- type: primitive
- modifiers:
- - type: ordinalScope
- scopeType: {type: word}
- start: 1
- length: 1
- mark: {type: decoratedSymbol, symbolColor: default, character: c}
- usePrePhraseSnapshot: true
-initialState:
- documentContents: |2
- npm version patch --force --commit-hooks false --git-tag-version false
- selections:
- - anchor: {line: 1, character: 0}
- active: {line: 1, character: 0}
- marks:
- default.c:
- start: {line: 0, character: 27}
- end: {line: 0, character: 41}
-finalState:
- documentContents: |2
- npm version patch --force --commit false --git-tag-version false
- selections:
- - anchor: {line: 1, character: 0}
- active: {line: 1, character: 0}
diff --git a/resources/fixtures/scopes/shellscript/argument/argument.actual.iteration.scope b/resources/fixtures/scopes/shellscript/argument/argument.actual.iteration.scope
new file mode 100644
index 0000000000..6635834b72
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/argument/argument.actual.iteration.scope
@@ -0,0 +1,10 @@
+foo aaa bbb
+---
+
+[Content] = 0:4-0:11
+ >-------<
+0| foo aaa bbb
+
+[Domain] = 0:0-0:11
+ >-----------<
+0| foo aaa bbb
diff --git a/resources/fixtures/scopes/shellscript/argument/argument.actual.multiLine.scope b/resources/fixtures/scopes/shellscript/argument/argument.actual.multiLine.scope
new file mode 100644
index 0000000000..ff77b08051
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/argument/argument.actual.multiLine.scope
@@ -0,0 +1,42 @@
+foo aaa \
+ bbb
+---
+
+[#1 Content] =
+[#1 Domain] = 0:4-0:7
+ >---<
+0| foo aaa \
+
+[#1 Removal] = 0:4-1:2
+ >-----
+0| foo aaa \
+1| bbb
+ --<
+
+[#1 Trailing delimiter] = 0:7-1:2
+ >--
+0| foo aaa \
+1| bbb
+ --<
+
+[#1 Insertion delimiter] = " \\\n"
+
+
+[#2 Content] =
+[#2 Domain] = 1:2-1:5
+ >---<
+1| bbb
+
+[#2 Removal] = 0:7-1:5
+ >--
+0| foo aaa \
+1| bbb
+ -----<
+
+[#2 Leading delimiter] = 0:7-1:2
+ >--
+0| foo aaa \
+1| bbb
+ --<
+
+[#2 Insertion delimiter] = " \\\n"
diff --git a/resources/fixtures/scopes/shellscript/argument/argument.actual.singleLine.scope b/resources/fixtures/scopes/shellscript/argument/argument.actual.singleLine.scope
new file mode 100644
index 0000000000..9ad2666f83
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/argument/argument.actual.singleLine.scope
@@ -0,0 +1,33 @@
+foo aaa bbb
+---
+
+[#1 Content] =
+[#1 Domain] = 0:4-0:7
+ >---<
+0| foo aaa bbb
+
+[#1 Removal] = 0:4-0:8
+ >----<
+0| foo aaa bbb
+
+[#1 Trailing delimiter] = 0:7-0:8
+ >-<
+0| foo aaa bbb
+
+[#1 Insertion delimiter] = " "
+
+
+[#2 Content] =
+[#2 Domain] = 0:8-0:11
+ >---<
+0| foo aaa bbb
+
+[#2 Removal] = 0:7-0:11
+ >----<
+0| foo aaa bbb
+
+[#2 Leading delimiter] = 0:7-0:8
+ >-<
+0| foo aaa bbb
+
+[#2 Insertion delimiter] = " "
diff --git a/resources/fixtures/scopes/shellscript/argumentList.actual.empty.scope b/resources/fixtures/scopes/shellscript/argumentList.actual.empty.scope
new file mode 100644
index 0000000000..ef25b7bec2
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/argumentList.actual.empty.scope
@@ -0,0 +1,13 @@
+foo
+---
+
+[Content] =
+[Removal] = 0:3-0:3
+ ><
+0| foo
+
+[Domain] = 0:0-0:3
+ >---<
+0| foo
+
+[Insertion delimiter] = " "
diff --git a/resources/fixtures/scopes/shellscript/argumentList.actual.multiLine.scope b/resources/fixtures/scopes/shellscript/argumentList.actual.multiLine.scope
new file mode 100644
index 0000000000..26cf997579
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/argumentList.actual.multiLine.scope
@@ -0,0 +1,27 @@
+foo aaa \
+ bbb
+---
+
+[Content] = 0:4-1:5
+ >-----
+0| foo aaa \
+1| bbb
+ -----<
+
+[Removal] = 0:3-1:5
+ >------
+0| foo aaa \
+1| bbb
+ -----<
+
+[Leading delimiter] = 0:3-0:4
+ >-<
+0| foo aaa \
+
+[Domain] = 0:0-1:5
+ >---------
+0| foo aaa \
+1| bbb
+ -----<
+
+[Insertion delimiter] = " "
diff --git a/resources/fixtures/scopes/shellscript/argumentList.actual.singleLine.scope b/resources/fixtures/scopes/shellscript/argumentList.actual.singleLine.scope
new file mode 100644
index 0000000000..83e8347e77
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/argumentList.actual.singleLine.scope
@@ -0,0 +1,20 @@
+foo aaa bbb
+---
+
+[Content] = 0:4-0:11
+ >-------<
+0| foo aaa bbb
+
+[Removal] = 0:3-0:11
+ >--------<
+0| foo aaa bbb
+
+[Leading delimiter] = 0:3-0:4
+ >-<
+0| foo aaa bbb
+
+[Domain] = 0:0-0:11
+ >-----------<
+0| foo aaa bbb
+
+[Insertion delimiter] = " "
diff --git a/resources/fixtures/scopes/shellscript/branch/branch.if.elif.else.scope b/resources/fixtures/scopes/shellscript/branch/branch.if.elif.else.scope
new file mode 100644
index 0000000000..bac97e09b0
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/branch/branch.if.elif.else.scope
@@ -0,0 +1,58 @@
+if true; then
+ :
+elif false; then
+ :
+else
+ :
+fi
+---
+
+[#1 Content] =
+[#1 Domain] = 0:0-1:5
+ >-------------
+0| if true; then
+1| :
+ -----<
+
+[#1 Removal] = 0:0-2:2
+ >-------------
+0| if true; then
+1| :
+2| elif false; then
+ --<
+
+[#1 Insertion delimiter] = "\n"
+
+
+[#2 Content] =
+[#2 Domain] = 2:0-3:5
+ >----------------
+2| elif false; then
+3| :
+ -----<
+
+[#2 Removal] = 2:0-4:0
+ >----------------
+2| elif false; then
+3| :
+4| else
+ <
+
+[#2 Insertion delimiter] = "\n"
+
+
+[#3 Content] =
+[#3 Domain] = 4:0-5:5
+ >----
+4| else
+5| :
+ -----<
+
+[#3 Removal] = 4:0-6:0
+ >----
+4| else
+5| :
+6| fi
+ <
+
+[#3 Insertion delimiter] = "\n"
diff --git a/resources/fixtures/scopes/shellscript/branch/branch.if.else.scope b/resources/fixtures/scopes/shellscript/branch/branch.if.else.scope
new file mode 100644
index 0000000000..d7193d35ef
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/branch/branch.if.else.scope
@@ -0,0 +1,39 @@
+if true; then
+ :
+else
+ :
+fi
+---
+
+[#1 Content] =
+[#1 Domain] = 0:0-1:5
+ >-------------
+0| if true; then
+1| :
+ -----<
+
+[#1 Removal] = 0:0-2:0
+ >-------------
+0| if true; then
+1| :
+2| else
+ <
+
+[#1 Insertion delimiter] = "\n"
+
+
+[#2 Content] =
+[#2 Domain] = 2:0-3:5
+ >----
+2| else
+3| :
+ -----<
+
+[#2 Removal] = 2:0-4:0
+ >----
+2| else
+3| :
+4| fi
+ <
+
+[#2 Insertion delimiter] = "\n"
diff --git a/resources/fixtures/scopes/shellscript/branch/branch.if.iteration.scope b/resources/fixtures/scopes/shellscript/branch/branch.if.iteration.scope
new file mode 100644
index 0000000000..71a97625db
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/branch/branch.if.iteration.scope
@@ -0,0 +1,14 @@
+if true; then
+elif false; then
+else
+fi
+---
+
+[Content] =
+[Domain] = 0:0-3:2
+ >-------------
+0| if true; then
+1| elif false; then
+2| else
+3| fi
+ --<
diff --git a/resources/fixtures/scopes/shellscript/branch/branch.if.scope b/resources/fixtures/scopes/shellscript/branch/branch.if.scope
new file mode 100644
index 0000000000..cfcf7c1bd4
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/branch/branch.if.scope
@@ -0,0 +1,10 @@
+if true; then :; fi
+---
+
+[Content] =
+[Removal] =
+[Domain] = 0:0-0:19
+ >-------------------<
+0| if true; then :; fi
+
+[Insertion delimiter] = "\n"
diff --git a/resources/fixtures/scopes/shellscript/branch/branch.switchCase.iteration.scope b/resources/fixtures/scopes/shellscript/branch/branch.switchCase.iteration.scope
new file mode 100644
index 0000000000..7f8b71c51d
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/branch/branch.switchCase.iteration.scope
@@ -0,0 +1,7 @@
+case $foo in esac
+---
+
+[Content] =
+[Domain] = 0:12-0:13
+ >-<
+0| case $foo in esac
diff --git a/resources/fixtures/scopes/shellscript/branch/branch.switchCase.scope b/resources/fixtures/scopes/shellscript/branch/branch.switchCase.scope
new file mode 100644
index 0000000000..24f39ca802
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/branch/branch.switchCase.scope
@@ -0,0 +1,21 @@
+case $foo in
+ 0) : ;;
+esac
+---
+
+[Content] =
+[Domain] = 1:4-1:11
+ >-------<
+1| 0) : ;;
+
+[Removal] = 1:0-2:0
+ >-----------
+1| 0) : ;;
+2| esac
+ <
+
+[Leading delimiter] = 1:0-1:4
+ >----<
+1| 0) : ;;
+
+[Insertion delimiter] = "\n"
diff --git a/resources/fixtures/scopes/shellscript/branch/branch.switchCase2.scope b/resources/fixtures/scopes/shellscript/branch/branch.switchCase2.scope
new file mode 100644
index 0000000000..b8015b152a
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/branch/branch.switchCase2.scope
@@ -0,0 +1,21 @@
+case $foo in
+ *) : ;;
+esac
+---
+
+[Content] =
+[Domain] = 1:4-1:11
+ >-------<
+1| *) : ;;
+
+[Removal] = 1:0-2:0
+ >-----------
+1| *) : ;;
+2| esac
+ <
+
+[Leading delimiter] = 1:0-1:4
+ >----<
+1| *) : ;;
+
+[Insertion delimiter] = "\n"
diff --git a/resources/fixtures/scopes/shellscript/branch/branch.ternary.iteration.scope b/resources/fixtures/scopes/shellscript/branch/branch.ternary.iteration.scope
new file mode 100644
index 0000000000..37eb212d5f
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/branch/branch.ternary.iteration.scope
@@ -0,0 +1,7 @@
+((true ? 0 : 1))
+---
+
+[Content] =
+[Domain] = 0:2-0:14
+ >------------<
+0| ((true ? 0 : 1))
diff --git a/resources/fixtures/scopes/shellscript/branch/branch.ternary.scope b/resources/fixtures/scopes/shellscript/branch/branch.ternary.scope
new file mode 100644
index 0000000000..63600b864e
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/branch/branch.ternary.scope
@@ -0,0 +1,37 @@
+((true ? 0 : 1))
+---
+
+[#1 Content] =
+[#1 Domain] = 0:9-0:10
+ >-<
+0| ((true ? 0 : 1))
+
+[#1 Removal] = 0:9-0:11
+ >--<
+0| ((true ? 0 : 1))
+
+[#1 Leading delimiter] = 0:8-0:9
+ >-<
+0| ((true ? 0 : 1))
+
+[#1 Trailing delimiter] = 0:10-0:11
+ >-<
+0| ((true ? 0 : 1))
+
+[#1 Insertion delimiter] = "\n"
+
+
+[#2 Content] =
+[#2 Domain] = 0:13-0:14
+ >-<
+0| ((true ? 0 : 1))
+
+[#2 Removal] = 0:12-0:14
+ >--<
+0| ((true ? 0 : 1))
+
+[#2 Leading delimiter] = 0:12-0:13
+ >-<
+0| ((true ? 0 : 1))
+
+[#2 Insertion delimiter] = "\n"
diff --git a/resources/fixtures/scopes/shellscript/comment.line.scope b/resources/fixtures/scopes/shellscript/comment.line.scope
new file mode 100644
index 0000000000..42719cdbb8
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/comment.line.scope
@@ -0,0 +1,10 @@
+# Hello world
+---
+
+[Content] =
+[Removal] =
+[Domain] = 0:0-0:13
+ >-------------<
+0| # Hello world
+
+[Insertion delimiter] = "\n"
diff --git a/resources/fixtures/scopes/shellscript/condition/condition.for.scope b/resources/fixtures/scopes/shellscript/condition/condition.for.scope
new file mode 100644
index 0000000000..f4b8efd5fd
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/condition/condition.for.scope
@@ -0,0 +1,20 @@
+for ((i = 0; i < 2; i++)); do :; done
+---
+
+[Content] = 0:13-0:18
+ >-----<
+0| for ((i = 0; i < 2; i++)); do :; done
+
+[Removal] = 0:12-0:18
+ >------<
+0| for ((i = 0; i < 2; i++)); do :; done
+
+[Leading delimiter] = 0:12-0:13
+ >-<
+0| for ((i = 0; i < 2; i++)); do :; done
+
+[Domain] = 0:0-0:37
+ >-------------------------------------<
+0| for ((i = 0; i < 2; i++)); do :; done
+
+[Insertion delimiter] = " "
diff --git a/resources/fixtures/scopes/shellscript/condition/condition.if.scope b/resources/fixtures/scopes/shellscript/condition/condition.if.scope
new file mode 100644
index 0000000000..a67d508a88
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/condition/condition.if.scope
@@ -0,0 +1,46 @@
+if true; then
+elif false; then
+else
+fi
+---
+
+[#1 Content] = 0:3-0:7
+ >----<
+0| if true; then
+
+[#1 Removal] = 0:2-0:7
+ >-----<
+0| if true; then
+
+[#1 Leading delimiter] = 0:2-0:3
+ >-<
+0| if true; then
+
+[#1 Domain] = 0:0-3:2
+ >-------------
+0| if true; then
+1| elif false; then
+2| else
+3| fi
+ --<
+
+[#1 Insertion delimiter] = " "
+
+
+[#2 Content] = 1:5-1:10
+ >-----<
+1| elif false; then
+
+[#2 Removal] = 1:4-1:10
+ >------<
+1| elif false; then
+
+[#2 Leading delimiter] = 1:4-1:5
+ >-<
+1| elif false; then
+
+[#2 Domain] = 1:0-1:16
+ >----------------<
+1| elif false; then
+
+[#2 Insertion delimiter] = " "
diff --git a/resources/fixtures/scopes/shellscript/condition/condition.switchCase.iteration.scope b/resources/fixtures/scopes/shellscript/condition/condition.switchCase.iteration.scope
new file mode 100644
index 0000000000..7f8b71c51d
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/condition/condition.switchCase.iteration.scope
@@ -0,0 +1,7 @@
+case $foo in esac
+---
+
+[Content] =
+[Domain] = 0:12-0:13
+ >-<
+0| case $foo in esac
diff --git a/resources/fixtures/scopes/shellscript/condition/condition.switchCase.scope b/resources/fixtures/scopes/shellscript/condition/condition.switchCase.scope
new file mode 100644
index 0000000000..048ec49ece
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/condition/condition.switchCase.scope
@@ -0,0 +1,22 @@
+case $foo in
+ 0) : ;;
+esac
+---
+
+[Content] = 1:2-1:3
+ >-<
+1| 0) : ;;
+
+[Removal] = 1:0-1:3
+ >---<
+1| 0) : ;;
+
+[Leading delimiter] = 1:0-1:2
+ >--<
+1| 0) : ;;
+
+[Domain] = 1:2-1:9
+ >-------<
+1| 0) : ;;
+
+[Insertion delimiter] = " "
diff --git a/resources/fixtures/scopes/shellscript/condition/condition.ternary.scope b/resources/fixtures/scopes/shellscript/condition/condition.ternary.scope
new file mode 100644
index 0000000000..dd10d78891
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/condition/condition.ternary.scope
@@ -0,0 +1,20 @@
+((true ? 0 : 1))
+---
+
+[Content] = 0:2-0:6
+ >----<
+0| ((true ? 0 : 1))
+
+[Removal] = 0:2-0:7
+ >-----<
+0| ((true ? 0 : 1))
+
+[Trailing delimiter] = 0:6-0:7
+ >-<
+0| ((true ? 0 : 1))
+
+[Domain] = 0:2-0:14
+ >------------<
+0| ((true ? 0 : 1))
+
+[Insertion delimiter] = " "
diff --git a/resources/fixtures/scopes/shellscript/condition/condition.while.scope b/resources/fixtures/scopes/shellscript/condition/condition.while.scope
new file mode 100644
index 0000000000..4616dcdca9
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/condition/condition.while.scope
@@ -0,0 +1,20 @@
+while true; do :; done
+---
+
+[Content] = 0:6-0:10
+ >----<
+0| while true; do :; done
+
+[Removal] = 0:5-0:10
+ >-----<
+0| while true; do :; done
+
+[Leading delimiter] = 0:5-0:6
+ >-<
+0| while true; do :; done
+
+[Domain] = 0:0-0:22
+ >----------------------<
+0| while true; do :; done
+
+[Insertion delimiter] = " "
diff --git a/resources/fixtures/scopes/shellscript/condition/condition.while2.scope b/resources/fixtures/scopes/shellscript/condition/condition.while2.scope
new file mode 100644
index 0000000000..eb65d51f95
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/condition/condition.while2.scope
@@ -0,0 +1,20 @@
+until true; do :; done
+---
+
+[Content] = 0:6-0:10
+ >----<
+0| until true; do :; done
+
+[Removal] = 0:5-0:10
+ >-----<
+0| until true; do :; done
+
+[Leading delimiter] = 0:5-0:6
+ >-<
+0| until true; do :; done
+
+[Domain] = 0:0-0:22
+ >----------------------<
+0| until true; do :; done
+
+[Insertion delimiter] = " "
diff --git a/resources/fixtures/scopes/shellscript/functionCall.scope b/resources/fixtures/scopes/shellscript/functionCall.scope
new file mode 100644
index 0000000000..112d8624cf
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/functionCall.scope
@@ -0,0 +1,10 @@
+foo
+---
+
+[Content] =
+[Removal] =
+[Domain] = 0:0-0:3
+ >---<
+0| foo
+
+[Insertion delimiter] = " "
diff --git a/resources/fixtures/scopes/shellscript/functionCall2.scope b/resources/fixtures/scopes/shellscript/functionCall2.scope
new file mode 100644
index 0000000000..0f47076007
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/functionCall2.scope
@@ -0,0 +1,10 @@
+foo aaa bbb
+---
+
+[Content] =
+[Removal] =
+[Domain] = 0:0-0:11
+ >-----------<
+0| foo aaa bbb
+
+[Insertion delimiter] = " "
diff --git a/resources/fixtures/scopes/shellscript/functionCallee.scope b/resources/fixtures/scopes/shellscript/functionCallee.scope
new file mode 100644
index 0000000000..112d8624cf
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/functionCallee.scope
@@ -0,0 +1,10 @@
+foo
+---
+
+[Content] =
+[Removal] =
+[Domain] = 0:0-0:3
+ >---<
+0| foo
+
+[Insertion delimiter] = " "
diff --git a/resources/fixtures/scopes/shellscript/functionCallee2.scope b/resources/fixtures/scopes/shellscript/functionCallee2.scope
new file mode 100644
index 0000000000..3ab340cc86
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/functionCallee2.scope
@@ -0,0 +1,20 @@
+foo aaa bbb
+---
+
+[Content] = 0:0-0:3
+ >---<
+0| foo aaa bbb
+
+[Removal] = 0:0-0:4
+ >----<
+0| foo aaa bbb
+
+[Trailing delimiter] = 0:3-0:4
+ >-<
+0| foo aaa bbb
+
+[Domain] = 0:0-0:11
+ >-----------<
+0| foo aaa bbb
+
+[Insertion delimiter] = " "
diff --git a/resources/fixtures/scopes/shellscript/ifStatement.scope b/resources/fixtures/scopes/shellscript/ifStatement.scope
new file mode 100644
index 0000000000..8f054040c6
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/ifStatement.scope
@@ -0,0 +1,17 @@
+if true; then
+elif false; then
+else
+fi
+---
+
+[Content] =
+[Removal] =
+[Domain] = 0:0-3:2
+ >-------------
+0| if true; then
+1| elif false; then
+2| else
+3| fi
+ --<
+
+[Insertion delimiter] = "\n"
diff --git a/resources/fixtures/scopes/shellscript/interior/interior.for.scope b/resources/fixtures/scopes/shellscript/interior/interior.for.scope
new file mode 100644
index 0000000000..80856e6348
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/interior/interior.for.scope
@@ -0,0 +1,13 @@
+for ((foo = 0; foo < 2; foo++)); do :; done
+---
+
+[Content] = 0:36-0:38
+ >--<
+0| for ((foo = 0; foo < 2; foo++)); do :; done
+
+[Removal] =
+[Domain] = 0:35-0:39
+ >----<
+0| for ((foo = 0; foo < 2; foo++)); do :; done
+
+[Insertion delimiter] = " "
diff --git a/resources/fixtures/scopes/shellscript/interior/interior.foreach.scope b/resources/fixtures/scopes/shellscript/interior/interior.foreach.scope
new file mode 100644
index 0000000000..7eed3cdcca
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/interior/interior.foreach.scope
@@ -0,0 +1,13 @@
+for v in values; do :; done
+---
+
+[Content] = 0:20-0:22
+ >--<
+0| for v in values; do :; done
+
+[Removal] =
+[Domain] = 0:19-0:23
+ >----<
+0| for v in values; do :; done
+
+[Insertion delimiter] = " "
diff --git a/resources/fixtures/scopes/shellscript/interior/interior.function.scope b/resources/fixtures/scopes/shellscript/interior/interior.function.scope
new file mode 100644
index 0000000000..2c1e9c958c
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/interior/interior.function.scope
@@ -0,0 +1,10 @@
+foo() { }
+---
+
+[Content] =
+[Removal] =
+[Domain] = 0:7-0:8
+ >-<
+0| foo() { }
+
+[Insertion delimiter] = " "
diff --git a/resources/fixtures/scopes/shellscript/interior/interior.function2.scope b/resources/fixtures/scopes/shellscript/interior/interior.function2.scope
new file mode 100644
index 0000000000..31d9a921b6
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/interior/interior.function2.scope
@@ -0,0 +1,10 @@
+function foo { }
+---
+
+[Content] =
+[Removal] =
+[Domain] = 0:14-0:15
+ >-<
+0| function foo { }
+
+[Insertion delimiter] = " "
diff --git a/resources/fixtures/scopes/shellscript/interior/interior.if.scope b/resources/fixtures/scopes/shellscript/interior/interior.if.scope
new file mode 100644
index 0000000000..3855751553
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/interior/interior.if.scope
@@ -0,0 +1,52 @@
+if true; then
+ :
+elif false; then
+ :
+else
+ :
+fi
+---
+
+[#1 Content] = 1:2-1:3
+ >-<
+1| :
+
+[#1 Removal] =
+[#1 Domain] = 0:13-2:0
+ >
+0| if true; then
+1| :
+2| elif false; then
+ <
+
+[#1 Insertion delimiter] = " "
+
+
+[#2 Content] = 3:2-3:3
+ >-<
+3| :
+
+[#2 Removal] =
+[#2 Domain] = 2:16-4:0
+ >
+2| elif false; then
+3| :
+4| else
+ <
+
+[#2 Insertion delimiter] = " "
+
+
+[#3 Content] = 5:2-5:3
+ >-<
+5| :
+
+[#3 Removal] =
+[#3 Domain] = 4:4-6:0
+ >
+4| else
+5| :
+6| fi
+ <
+
+[#3 Insertion delimiter] = " "
diff --git a/resources/fixtures/scopes/shellscript/interior/interior.switch.scope b/resources/fixtures/scopes/shellscript/interior/interior.switch.scope
new file mode 100644
index 0000000000..0f6d8c02a2
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/interior/interior.switch.scope
@@ -0,0 +1,10 @@
+case $foo in esac
+---
+
+[Content] =
+[Removal] =
+[Domain] = 0:12-0:13
+ >-<
+0| case $foo in esac
+
+[Insertion delimiter] = " "
diff --git a/resources/fixtures/scopes/shellscript/interior/interior.switchCase.scope b/resources/fixtures/scopes/shellscript/interior/interior.switchCase.scope
new file mode 100644
index 0000000000..457d561e3b
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/interior/interior.switchCase.scope
@@ -0,0 +1,30 @@
+case $foo in
+ 0) : ;;
+esac
+---
+
+[#1 Content] = 1:2-1:9
+ >-------<
+1| 0) : ;;
+
+[#1 Removal] =
+[#1 Domain] = 0:12-2:0
+ >
+0| case $foo in
+1| 0) : ;;
+2| esac
+ <
+
+[#1 Insertion delimiter] = " "
+
+
+[#2 Content] = 1:5-1:6
+ >-<
+1| 0) : ;;
+
+[#2 Removal] =
+[#2 Domain] = 1:4-1:7
+ >---<
+1| 0) : ;;
+
+[#2 Insertion delimiter] = " "
diff --git a/resources/fixtures/scopes/shellscript/interior/interior.while.scope b/resources/fixtures/scopes/shellscript/interior/interior.while.scope
new file mode 100644
index 0000000000..a5b3df39af
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/interior/interior.while.scope
@@ -0,0 +1,13 @@
+while foo; do :; done
+---
+
+[Content] = 0:14-0:16
+ >--<
+0| while foo; do :; done
+
+[Removal] =
+[Domain] = 0:13-0:17
+ >----<
+0| while foo; do :; done
+
+[Insertion delimiter] = " "
diff --git a/resources/fixtures/scopes/shellscript/interior/interior.while2.scope b/resources/fixtures/scopes/shellscript/interior/interior.while2.scope
new file mode 100644
index 0000000000..63ab18bc2e
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/interior/interior.while2.scope
@@ -0,0 +1,13 @@
+until foo; do :; done
+---
+
+[Content] = 0:14-0:16
+ >--<
+0| until foo; do :; done
+
+[Removal] =
+[Domain] = 0:13-0:17
+ >----<
+0| until foo; do :; done
+
+[Insertion delimiter] = " "
diff --git a/resources/fixtures/scopes/shellscript/key.mapPair.iteration.scope b/resources/fixtures/scopes/shellscript/key.mapPair.iteration.scope
new file mode 100644
index 0000000000..1ca06d9e0f
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/key.mapPair.iteration.scope
@@ -0,0 +1,7 @@
+foo=(["aaa"]=0 ["bbb"]=1)
+---
+
+[Content] =
+[Domain] = 0:5-0:24
+ >-------------------<
+0| foo=(["aaa"]=0 ["bbb"]=1)
diff --git a/resources/fixtures/scopes/shellscript/key.mapPair.scope b/resources/fixtures/scopes/shellscript/key.mapPair.scope
new file mode 100644
index 0000000000..97524f2b03
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/key.mapPair.scope
@@ -0,0 +1,25 @@
+foo=(["aaa"]=0 ["bbb"]=1)
+---
+
+[#1 Content] =
+[#1 Removal] = 0:6-0:11
+ >-----<
+0| foo=(["aaa"]=0 ["bbb"]=1)
+
+[#1 Domain] = 0:5-0:14
+ >---------<
+0| foo=(["aaa"]=0 ["bbb"]=1)
+
+[#1 Insertion delimiter] = " "
+
+
+[#2 Content] =
+[#2 Removal] = 0:16-0:21
+ >-----<
+0| foo=(["aaa"]=0 ["bbb"]=1)
+
+[#2 Domain] = 0:15-0:24
+ >---------<
+0| foo=(["aaa"]=0 ["bbb"]=1)
+
+[#2 Insertion delimiter] = " "
diff --git a/resources/fixtures/scopes/shellscript/list.scope b/resources/fixtures/scopes/shellscript/list.scope
new file mode 100644
index 0000000000..169ac2c693
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/list.scope
@@ -0,0 +1,10 @@
+foo=(aaa bbb)
+---
+
+[Content] =
+[Removal] =
+[Domain] = 0:4-0:13
+ >---------<
+0| foo=(aaa bbb)
+
+[Insertion delimiter] = " "
diff --git a/resources/fixtures/scopes/shellscript/map.scope b/resources/fixtures/scopes/shellscript/map.scope
new file mode 100644
index 0000000000..d8d71be3f7
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/map.scope
@@ -0,0 +1,10 @@
+foo=(["aaa"]=0 ["bbb"]=1)
+---
+
+[Content] =
+[Removal] =
+[Domain] = 0:4-0:25
+ >---------------------<
+0| foo=(["aaa"]=0 ["bbb"]=1)
+
+[Insertion delimiter] = " "
diff --git a/resources/fixtures/scopes/shellscript/name/name.assignment.compound.scope b/resources/fixtures/scopes/shellscript/name/name.assignment.compound.scope
new file mode 100644
index 0000000000..58b54b8ae7
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/name/name.assignment.compound.scope
@@ -0,0 +1,20 @@
+foo+=0
+---
+
+[Content] = 0:0-0:3
+ >---<
+0| foo+=0
+
+[Removal] = 0:0-0:5
+ >-----<
+0| foo+=0
+
+[Trailing delimiter] = 0:3-0:5
+ >--<
+0| foo+=0
+
+[Domain] = 0:0-0:6
+ >------<
+0| foo+=0
+
+[Insertion delimiter] = " "
diff --git a/resources/fixtures/scopes/shellscript/name/name.assignment.scope b/resources/fixtures/scopes/shellscript/name/name.assignment.scope
new file mode 100644
index 0000000000..d4b5ad34a8
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/name/name.assignment.scope
@@ -0,0 +1,20 @@
+foo=0
+---
+
+[Content] = 0:0-0:3
+ >---<
+0| foo=0
+
+[Removal] = 0:0-0:4
+ >----<
+0| foo=0
+
+[Trailing delimiter] = 0:3-0:4
+ >-<
+0| foo=0
+
+[Domain] = 0:0-0:5
+ >-----<
+0| foo=0
+
+[Insertion delimiter] = " "
diff --git a/resources/fixtures/scopes/shellscript/name/name.constant.scope b/resources/fixtures/scopes/shellscript/name/name.constant.scope
new file mode 100644
index 0000000000..70fecbd162
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/name/name.constant.scope
@@ -0,0 +1,20 @@
+readonly foo=0
+---
+
+[Content] = 0:9-0:12
+ >---<
+0| readonly foo=0
+
+[Removal] = 0:0-0:13
+ >-------------<
+0| readonly foo=0
+
+[Leading delimiter] = 0:8-0:9
+ >-<
+0| readonly foo=0
+
+[Domain] = 0:0-0:14
+ >--------------<
+0| readonly foo=0
+
+[Insertion delimiter] = " "
diff --git a/resources/fixtures/scopes/shellscript/name/name.foreach.scope b/resources/fixtures/scopes/shellscript/name/name.foreach.scope
new file mode 100644
index 0000000000..7595e725f9
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/name/name.foreach.scope
@@ -0,0 +1,24 @@
+for v in values; do :; done
+---
+
+[Content] = 0:4-0:5
+ >-<
+0| for v in values; do :; done
+
+[Removal] = 0:4-0:6
+ >--<
+0| for v in values; do :; done
+
+[Leading delimiter] = 0:3-0:4
+ >-<
+0| for v in values; do :; done
+
+[Trailing delimiter] = 0:5-0:6
+ >-<
+0| for v in values; do :; done
+
+[Domain] = 0:0-0:27
+ >---------------------------<
+0| for v in values; do :; done
+
+[Insertion delimiter] = " "
diff --git a/resources/fixtures/scopes/shellscript/name/name.function.scope b/resources/fixtures/scopes/shellscript/name/name.function.scope
new file mode 100644
index 0000000000..23835632d4
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/name/name.function.scope
@@ -0,0 +1,13 @@
+foo() {}
+---
+
+[Content] =
+[Removal] = 0:0-0:3
+ >---<
+0| foo() {}
+
+[Domain] = 0:0-0:8
+ >--------<
+0| foo() {}
+
+[Insertion delimiter] = " "
diff --git a/resources/fixtures/scopes/shellscript/name/name.function2.scope b/resources/fixtures/scopes/shellscript/name/name.function2.scope
new file mode 100644
index 0000000000..26008b0139
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/name/name.function2.scope
@@ -0,0 +1,24 @@
+function foo {}
+---
+
+[Content] = 0:9-0:12
+ >---<
+0| function foo {}
+
+[Removal] = 0:9-0:13
+ >----<
+0| function foo {}
+
+[Leading delimiter] = 0:8-0:9
+ >-<
+0| function foo {}
+
+[Trailing delimiter] = 0:12-0:13
+ >-<
+0| function foo {}
+
+[Domain] = 0:0-0:15
+ >---------------<
+0| function foo {}
+
+[Insertion delimiter] = " "
diff --git a/resources/fixtures/scopes/shellscript/name/name.iteration.block.scope b/resources/fixtures/scopes/shellscript/name/name.iteration.block.scope
new file mode 100644
index 0000000000..c034392b82
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/name/name.iteration.block.scope
@@ -0,0 +1,13 @@
+foo() { }
+---
+
+[#1 Content] =
+[#1 Domain] = 0:0-0:9
+ >---------<
+0| foo() { }
+
+
+[#2 Content] =
+[#2 Domain] = 0:7-0:8
+ >-<
+0| foo() { }
diff --git a/resources/fixtures/scopes/shellscript/name/name.iteration.block3.scope b/resources/fixtures/scopes/shellscript/name/name.iteration.block3.scope
new file mode 100644
index 0000000000..61135ad7e7
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/name/name.iteration.block3.scope
@@ -0,0 +1,13 @@
+while true; do :; done
+---
+
+[#1 Content] =
+[#1 Domain] = 0:0-0:22
+ >----------------------<
+0| while true; do :; done
+
+
+[#2 Content] =
+[#2 Domain] = 0:14-0:18
+ >----<
+0| while true; do :; done
diff --git a/resources/fixtures/scopes/shellscript/name/name.iteration.document.scope b/resources/fixtures/scopes/shellscript/name/name.iteration.document.scope
new file mode 100644
index 0000000000..c73f4c1df8
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/name/name.iteration.document.scope
@@ -0,0 +1,12 @@
+
+declare foo
+
+---
+
+[Content] =
+[Domain] = 0:0-2:0
+ >
+0|
+1| declare foo
+2|
+ <
diff --git a/resources/fixtures/scopes/shellscript/name/name.variable.initialized.scope b/resources/fixtures/scopes/shellscript/name/name.variable.initialized.scope
new file mode 100644
index 0000000000..199289c1c7
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/name/name.variable.initialized.scope
@@ -0,0 +1,20 @@
+local foo=0
+---
+
+[Content] = 0:6-0:9
+ >---<
+0| local foo=0
+
+[Removal] = 0:0-0:10
+ >----------<
+0| local foo=0
+
+[Leading delimiter] = 0:5-0:6
+ >-<
+0| local foo=0
+
+[Domain] = 0:0-0:11
+ >-----------<
+0| local foo=0
+
+[Insertion delimiter] = " "
diff --git a/resources/fixtures/scopes/shellscript/name/name.variable.initialized2.scope b/resources/fixtures/scopes/shellscript/name/name.variable.initialized2.scope
new file mode 100644
index 0000000000..6882fd0c37
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/name/name.variable.initialized2.scope
@@ -0,0 +1,20 @@
+declare foo=0
+---
+
+[Content] = 0:8-0:11
+ >---<
+0| declare foo=0
+
+[Removal] = 0:0-0:12
+ >------------<
+0| declare foo=0
+
+[Leading delimiter] = 0:7-0:8
+ >-<
+0| declare foo=0
+
+[Domain] = 0:0-0:13
+ >-------------<
+0| declare foo=0
+
+[Insertion delimiter] = " "
diff --git a/resources/fixtures/scopes/shellscript/name/name.variable.uninitialized.scope b/resources/fixtures/scopes/shellscript/name/name.variable.uninitialized.scope
new file mode 100644
index 0000000000..ea092e785a
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/name/name.variable.uninitialized.scope
@@ -0,0 +1,20 @@
+declare foo
+---
+
+[Content] = 0:8-0:11
+ >---<
+0| declare foo
+
+[Removal] = 0:7-0:11
+ >----<
+0| declare foo
+
+[Leading delimiter] = 0:7-0:8
+ >-<
+0| declare foo
+
+[Domain] = 0:0-0:11
+ >-----------<
+0| declare foo
+
+[Insertion delimiter] = " "
diff --git a/resources/fixtures/scopes/shellscript/name/name.variable.uninitialized2.scope b/resources/fixtures/scopes/shellscript/name/name.variable.uninitialized2.scope
new file mode 100644
index 0000000000..46082a20ce
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/name/name.variable.uninitialized2.scope
@@ -0,0 +1,20 @@
+local foo
+---
+
+[Content] = 0:6-0:9
+ >---<
+0| local foo
+
+[Removal] = 0:5-0:9
+ >----<
+0| local foo
+
+[Leading delimiter] = 0:5-0:6
+ >-<
+0| local foo
+
+[Domain] = 0:0-0:9
+ >---------<
+0| local foo
+
+[Insertion delimiter] = " "
diff --git a/resources/fixtures/scopes/shellscript/namedFunction/namedFunction.iteration.document.scope b/resources/fixtures/scopes/shellscript/namedFunction/namedFunction.iteration.document.scope
new file mode 100644
index 0000000000..9edaf417f2
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/namedFunction/namedFunction.iteration.document.scope
@@ -0,0 +1,12 @@
+
+foo() {}
+
+---
+
+[Content] =
+[Domain] = 0:0-2:0
+ >
+0|
+1| foo() {}
+2|
+ <
diff --git a/resources/fixtures/scopes/shellscript/namedFunction/namedFunction.scope b/resources/fixtures/scopes/shellscript/namedFunction/namedFunction.scope
new file mode 100644
index 0000000000..356c17f949
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/namedFunction/namedFunction.scope
@@ -0,0 +1,10 @@
+foo() {}
+---
+
+[Content] =
+[Removal] =
+[Domain] = 0:0-0:8
+ >--------<
+0| foo() {}
+
+[Insertion delimiter] = "\n\n"
diff --git a/resources/fixtures/scopes/shellscript/namedFunction/namedFunction2.scope b/resources/fixtures/scopes/shellscript/namedFunction/namedFunction2.scope
new file mode 100644
index 0000000000..3ce77f6134
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/namedFunction/namedFunction2.scope
@@ -0,0 +1,10 @@
+function foo {}
+---
+
+[Content] =
+[Removal] =
+[Domain] = 0:0-0:15
+ >---------------<
+0| function foo {}
+
+[Insertion delimiter] = "\n\n"
diff --git a/resources/fixtures/scopes/shellscript/namedFunction/namedFunction3.scope b/resources/fixtures/scopes/shellscript/namedFunction/namedFunction3.scope
new file mode 100644
index 0000000000..bb0fb08770
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/namedFunction/namedFunction3.scope
@@ -0,0 +1,10 @@
+function foo() {}
+---
+
+[Content] =
+[Removal] =
+[Domain] = 0:0-0:17
+ >-----------------<
+0| function foo() {}
+
+[Insertion delimiter] = "\n\n"
diff --git a/resources/fixtures/scopes/shellscript/regularExpression.scope b/resources/fixtures/scopes/shellscript/regularExpression.scope
new file mode 100644
index 0000000000..c41400363c
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/regularExpression.scope
@@ -0,0 +1,21 @@
+[[ $foo =~ ^\w+$ ]]
+---
+
+[Content] =
+[Domain] = 0:11-0:16
+ >-----<
+0| [[ $foo =~ ^\w+$ ]]
+
+[Removal] = 0:11-0:17
+ >------<
+0| [[ $foo =~ ^\w+$ ]]
+
+[Leading delimiter] = 0:10-0:11
+ >-<
+0| [[ $foo =~ ^\w+$ ]]
+
+[Trailing delimiter] = 0:16-0:17
+ >-<
+0| [[ $foo =~ ^\w+$ ]]
+
+[Insertion delimiter] = " "
diff --git a/resources/fixtures/scopes/shellscript/statement/statement.assignment.compound.scope b/resources/fixtures/scopes/shellscript/statement/statement.assignment.compound.scope
new file mode 100644
index 0000000000..e2c1463f8e
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/statement/statement.assignment.compound.scope
@@ -0,0 +1,10 @@
+foo+=1
+---
+
+[Content] =
+[Removal] =
+[Domain] = 0:0-0:6
+ >------<
+0| foo+=1
+
+[Insertion delimiter] = "\n"
diff --git a/resources/fixtures/scopes/shellscript/statement/statement.assignment.scope b/resources/fixtures/scopes/shellscript/statement/statement.assignment.scope
new file mode 100644
index 0000000000..bc214c0000
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/statement/statement.assignment.scope
@@ -0,0 +1,10 @@
+foo=0
+---
+
+[Content] =
+[Removal] =
+[Domain] = 0:0-0:5
+ >-----<
+0| foo=0
+
+[Insertion delimiter] = "\n"
diff --git a/resources/fixtures/scopes/shellscript/statement/statement.break.scope b/resources/fixtures/scopes/shellscript/statement/statement.break.scope
new file mode 100644
index 0000000000..c697e2b0da
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/statement/statement.break.scope
@@ -0,0 +1,33 @@
+while true; do
+ break
+done
+---
+
+[#1 Content] =
+[#1 Removal] =
+[#1 Domain] = 0:0-2:4
+ >--------------
+0| while true; do
+1| break
+2| done
+ ----<
+
+[#1 Insertion delimiter] = "\n"
+
+
+[#2 Content] =
+[#2 Domain] = 1:4-1:9
+ >-----<
+1| break
+
+[#2 Removal] = 1:0-2:0
+ >---------
+1| break
+2| done
+ <
+
+[#2 Leading delimiter] = 1:0-1:4
+ >----<
+1| break
+
+[#2 Insertion delimiter] = "\n"
diff --git a/resources/fixtures/scopes/shellscript/statement/statement.constant.scope b/resources/fixtures/scopes/shellscript/statement/statement.constant.scope
new file mode 100644
index 0000000000..c3ca8b7148
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/statement/statement.constant.scope
@@ -0,0 +1,10 @@
+readonly foo=0
+---
+
+[Content] =
+[Removal] =
+[Domain] = 0:0-0:14
+ >--------------<
+0| readonly foo=0
+
+[Insertion delimiter] = "\n"
diff --git a/resources/fixtures/scopes/shellscript/statement/statement.continue.scope b/resources/fixtures/scopes/shellscript/statement/statement.continue.scope
new file mode 100644
index 0000000000..6c6d30c7e1
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/statement/statement.continue.scope
@@ -0,0 +1,33 @@
+while true; do
+ continue
+done
+---
+
+[#1 Content] =
+[#1 Removal] =
+[#1 Domain] = 0:0-2:4
+ >--------------
+0| while true; do
+1| continue
+2| done
+ ----<
+
+[#1 Insertion delimiter] = "\n"
+
+
+[#2 Content] =
+[#2 Domain] = 1:4-1:12
+ >--------<
+1| continue
+
+[#2 Removal] = 1:0-2:0
+ >------------
+1| continue
+2| done
+ <
+
+[#2 Leading delimiter] = 1:0-1:4
+ >----<
+1| continue
+
+[#2 Insertion delimiter] = "\n"
diff --git a/resources/fixtures/scopes/shellscript/statement/statement.for.scope b/resources/fixtures/scopes/shellscript/statement/statement.for.scope
new file mode 100644
index 0000000000..94a2090df0
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/statement/statement.for.scope
@@ -0,0 +1,26 @@
+for ((i = 0; i < 2; i++)); do :; done
+---
+
+[#1 Content] =
+[#1 Removal] =
+[#1 Domain] = 0:0-0:37
+ >-------------------------------------<
+0| for ((i = 0; i < 2; i++)); do :; done
+
+[#1 Insertion delimiter] = "\n"
+
+
+[#2 Content] =
+[#2 Domain] = 0:30-0:31
+ >-<
+0| for ((i = 0; i < 2; i++)); do :; done
+
+[#2 Removal] = 0:29-0:31
+ >--<
+0| for ((i = 0; i < 2; i++)); do :; done
+
+[#2 Leading delimiter] = 0:29-0:30
+ >-<
+0| for ((i = 0; i < 2; i++)); do :; done
+
+[#2 Insertion delimiter] = "\n"
diff --git a/resources/fixtures/scopes/shellscript/statement/statement.foreach.scope b/resources/fixtures/scopes/shellscript/statement/statement.foreach.scope
new file mode 100644
index 0000000000..db884dca01
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/statement/statement.foreach.scope
@@ -0,0 +1,26 @@
+for v in values; do :; done
+---
+
+[#1 Content] =
+[#1 Removal] =
+[#1 Domain] = 0:0-0:27
+ >---------------------------<
+0| for v in values; do :; done
+
+[#1 Insertion delimiter] = "\n"
+
+
+[#2 Content] =
+[#2 Domain] = 0:20-0:21
+ >-<
+0| for v in values; do :; done
+
+[#2 Removal] = 0:19-0:21
+ >--<
+0| for v in values; do :; done
+
+[#2 Leading delimiter] = 0:19-0:20
+ >-<
+0| for v in values; do :; done
+
+[#2 Insertion delimiter] = "\n"
diff --git a/resources/fixtures/scopes/shellscript/statement/statement.function.scope b/resources/fixtures/scopes/shellscript/statement/statement.function.scope
new file mode 100644
index 0000000000..27771a509b
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/statement/statement.function.scope
@@ -0,0 +1,10 @@
+foo() {}
+---
+
+[Content] =
+[Removal] =
+[Domain] = 0:0-0:8
+ >--------<
+0| foo() {}
+
+[Insertion delimiter] = "\n"
diff --git a/resources/fixtures/scopes/shellscript/statement/statement.function2.scope b/resources/fixtures/scopes/shellscript/statement/statement.function2.scope
new file mode 100644
index 0000000000..8e3f364473
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/statement/statement.function2.scope
@@ -0,0 +1,10 @@
+function foo {}
+---
+
+[Content] =
+[Removal] =
+[Domain] = 0:0-0:15
+ >---------------<
+0| function foo {}
+
+[Insertion delimiter] = "\n"
diff --git a/resources/fixtures/scopes/shellscript/statement/statement.functionCall.scope b/resources/fixtures/scopes/shellscript/statement/statement.functionCall.scope
new file mode 100644
index 0000000000..56385bcce4
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/statement/statement.functionCall.scope
@@ -0,0 +1,10 @@
+foo
+---
+
+[Content] =
+[Removal] =
+[Domain] = 0:0-0:3
+ >---<
+0| foo
+
+[Insertion delimiter] = "\n"
diff --git a/resources/fixtures/scopes/shellscript/statement/statement.functionCall2.scope b/resources/fixtures/scopes/shellscript/statement/statement.functionCall2.scope
new file mode 100644
index 0000000000..54dce4076a
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/statement/statement.functionCall2.scope
@@ -0,0 +1,10 @@
+foo aaa bbb
+---
+
+[Content] =
+[Removal] =
+[Domain] = 0:0-0:11
+ >-----------<
+0| foo aaa bbb
+
+[Insertion delimiter] = "\n"
diff --git a/resources/fixtures/scopes/shellscript/statement/statement.if.scope b/resources/fixtures/scopes/shellscript/statement/statement.if.scope
new file mode 100644
index 0000000000..8f054040c6
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/statement/statement.if.scope
@@ -0,0 +1,17 @@
+if true; then
+elif false; then
+else
+fi
+---
+
+[Content] =
+[Removal] =
+[Domain] = 0:0-3:2
+ >-------------
+0| if true; then
+1| elif false; then
+2| else
+3| fi
+ --<
+
+[Insertion delimiter] = "\n"
diff --git a/resources/fixtures/scopes/shellscript/statement/statement.if2.scope b/resources/fixtures/scopes/shellscript/statement/statement.if2.scope
new file mode 100644
index 0000000000..cd6e9454db
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/statement/statement.if2.scope
@@ -0,0 +1,95 @@
+if foo; then
+ aaa
+ bbb
+elif baz; then
+ ccc
+ ddd
+fi
+---
+
+[#1 Content] =
+[#1 Removal] =
+[#1 Domain] = 0:0-6:2
+ >------------
+0| if foo; then
+1| aaa
+2| bbb
+3| elif baz; then
+4| ccc
+5| ddd
+6| fi
+ --<
+
+[#1 Insertion delimiter] = "\n"
+
+
+[#2 Content] =
+[#2 Domain] = 1:4-1:7
+ >---<
+1| aaa
+
+[#2 Removal] = 1:0-2:0
+ >-------
+1| aaa
+2| bbb
+ <
+
+[#2 Leading delimiter] = 1:0-1:4
+ >----<
+1| aaa
+
+[#2 Insertion delimiter] = "\n"
+
+
+[#3 Content] =
+[#3 Domain] = 2:4-2:7
+ >---<
+2| bbb
+
+[#3 Removal] = 2:0-3:0
+ >-------
+2| bbb
+3| elif baz; then
+ <
+
+[#3 Leading delimiter] = 2:0-2:4
+ >----<
+2| bbb
+
+[#3 Insertion delimiter] = "\n"
+
+
+[#4 Content] =
+[#4 Domain] = 4:4-4:7
+ >---<
+4| ccc
+
+[#4 Removal] = 4:0-5:0
+ >-------
+4| ccc
+5| ddd
+ <
+
+[#4 Leading delimiter] = 4:0-4:4
+ >----<
+4| ccc
+
+[#4 Insertion delimiter] = "\n"
+
+
+[#5 Content] =
+[#5 Domain] = 5:4-5:7
+ >---<
+5| ddd
+
+[#5 Removal] = 5:0-6:0
+ >-------
+5| ddd
+6| fi
+ <
+
+[#5 Leading delimiter] = 5:0-5:4
+ >----<
+5| ddd
+
+[#5 Insertion delimiter] = "\n"
diff --git a/resources/fixtures/scopes/shellscript/statement/statement.import.scope b/resources/fixtures/scopes/shellscript/statement/statement.import.scope
new file mode 100644
index 0000000000..7437db33ae
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/statement/statement.import.scope
@@ -0,0 +1,10 @@
+source foo.sh
+---
+
+[Content] =
+[Removal] =
+[Domain] = 0:0-0:13
+ >-------------<
+0| source foo.sh
+
+[Insertion delimiter] = "\n"
diff --git a/resources/fixtures/scopes/shellscript/statement/statement.iteration.block.scope b/resources/fixtures/scopes/shellscript/statement/statement.iteration.block.scope
new file mode 100644
index 0000000000..c034392b82
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/statement/statement.iteration.block.scope
@@ -0,0 +1,13 @@
+foo() { }
+---
+
+[#1 Content] =
+[#1 Domain] = 0:0-0:9
+ >---------<
+0| foo() { }
+
+
+[#2 Content] =
+[#2 Domain] = 0:7-0:8
+ >-<
+0| foo() { }
diff --git a/resources/fixtures/scopes/shellscript/statement/statement.iteration.block3.scope b/resources/fixtures/scopes/shellscript/statement/statement.iteration.block3.scope
new file mode 100644
index 0000000000..61135ad7e7
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/statement/statement.iteration.block3.scope
@@ -0,0 +1,13 @@
+while true; do :; done
+---
+
+[#1 Content] =
+[#1 Domain] = 0:0-0:22
+ >----------------------<
+0| while true; do :; done
+
+
+[#2 Content] =
+[#2 Domain] = 0:14-0:18
+ >----<
+0| while true; do :; done
diff --git a/resources/fixtures/scopes/shellscript/statement/statement.iteration.document.scope b/resources/fixtures/scopes/shellscript/statement/statement.iteration.document.scope
new file mode 100644
index 0000000000..c73f4c1df8
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/statement/statement.iteration.document.scope
@@ -0,0 +1,12 @@
+
+declare foo
+
+---
+
+[Content] =
+[Domain] = 0:0-2:0
+ >
+0|
+1| declare foo
+2|
+ <
diff --git a/resources/fixtures/scopes/shellscript/statement/statement.return.scope b/resources/fixtures/scopes/shellscript/statement/statement.return.scope
new file mode 100644
index 0000000000..c826bddb97
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/statement/statement.return.scope
@@ -0,0 +1,33 @@
+foo() {
+ return 0
+}
+---
+
+[#1 Content] =
+[#1 Removal] =
+[#1 Domain] = 0:0-2:1
+ >-------
+0| foo() {
+1| return 0
+2| }
+ -<
+
+[#1 Insertion delimiter] = "\n"
+
+
+[#2 Content] =
+[#2 Domain] = 1:4-1:12
+ >--------<
+1| return 0
+
+[#2 Removal] = 1:0-2:0
+ >------------
+1| return 0
+2| }
+ <
+
+[#2 Leading delimiter] = 1:0-1:4
+ >----<
+1| return 0
+
+[#2 Insertion delimiter] = "\n"
diff --git a/resources/fixtures/scopes/shellscript/statement/statement.return2.scope b/resources/fixtures/scopes/shellscript/statement/statement.return2.scope
new file mode 100644
index 0000000000..a139463f2c
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/statement/statement.return2.scope
@@ -0,0 +1,33 @@
+function foo {
+ return 0
+}
+---
+
+[#1 Content] =
+[#1 Removal] =
+[#1 Domain] = 0:0-2:1
+ >--------------
+0| function foo {
+1| return 0
+2| }
+ -<
+
+[#1 Insertion delimiter] = "\n"
+
+
+[#2 Content] =
+[#2 Domain] = 1:4-1:12
+ >--------<
+1| return 0
+
+[#2 Removal] = 1:0-2:0
+ >------------
+1| return 0
+2| }
+ <
+
+[#2 Leading delimiter] = 1:0-1:4
+ >----<
+1| return 0
+
+[#2 Insertion delimiter] = "\n"
diff --git a/resources/fixtures/scopes/shellscript/statement/statement.switch.scope b/resources/fixtures/scopes/shellscript/statement/statement.switch.scope
new file mode 100644
index 0000000000..cce61292a0
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/statement/statement.switch.scope
@@ -0,0 +1,10 @@
+case $foo in esac
+---
+
+[Content] =
+[Removal] =
+[Domain] = 0:0-0:17
+ >-----------------<
+0| case $foo in esac
+
+[Insertion delimiter] = "\n"
diff --git a/resources/fixtures/scopes/shellscript/statement/statement.update.scope b/resources/fixtures/scopes/shellscript/statement/statement.update.scope
new file mode 100644
index 0000000000..f3c5053f14
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/statement/statement.update.scope
@@ -0,0 +1,10 @@
+((foo++))
+---
+
+[Content] =
+[Removal] =
+[Domain] = 0:0-0:9
+ >---------<
+0| ((foo++))
+
+[Insertion delimiter] = "\n"
diff --git a/resources/fixtures/scopes/shellscript/statement/statement.variable.initialized.scope b/resources/fixtures/scopes/shellscript/statement/statement.variable.initialized.scope
new file mode 100644
index 0000000000..b4d4b22807
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/statement/statement.variable.initialized.scope
@@ -0,0 +1,10 @@
+local foo=0
+---
+
+[Content] =
+[Removal] =
+[Domain] = 0:0-0:11
+ >-----------<
+0| local foo=0
+
+[Insertion delimiter] = "\n"
diff --git a/resources/fixtures/scopes/shellscript/statement/statement.variable.initialized2.scope b/resources/fixtures/scopes/shellscript/statement/statement.variable.initialized2.scope
new file mode 100644
index 0000000000..dc5d3d5d74
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/statement/statement.variable.initialized2.scope
@@ -0,0 +1,10 @@
+declare foo=0
+---
+
+[Content] =
+[Removal] =
+[Domain] = 0:0-0:13
+ >-------------<
+0| declare foo=0
+
+[Insertion delimiter] = "\n"
diff --git a/resources/fixtures/scopes/shellscript/statement/statement.variable.uninitialized.scope b/resources/fixtures/scopes/shellscript/statement/statement.variable.uninitialized.scope
new file mode 100644
index 0000000000..7c54acedfe
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/statement/statement.variable.uninitialized.scope
@@ -0,0 +1,10 @@
+declare foo
+---
+
+[Content] =
+[Removal] =
+[Domain] = 0:0-0:11
+ >-----------<
+0| declare foo
+
+[Insertion delimiter] = "\n"
diff --git a/resources/fixtures/scopes/shellscript/statement/statement.while.scope b/resources/fixtures/scopes/shellscript/statement/statement.while.scope
new file mode 100644
index 0000000000..bffa529eff
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/statement/statement.while.scope
@@ -0,0 +1,26 @@
+while true; do :; done
+---
+
+[#1 Content] =
+[#1 Removal] =
+[#1 Domain] = 0:0-0:22
+ >----------------------<
+0| while true; do :; done
+
+[#1 Insertion delimiter] = "\n"
+
+
+[#2 Content] =
+[#2 Domain] = 0:15-0:16
+ >-<
+0| while true; do :; done
+
+[#2 Removal] = 0:14-0:16
+ >--<
+0| while true; do :; done
+
+[#2 Leading delimiter] = 0:14-0:15
+ >-<
+0| while true; do :; done
+
+[#2 Insertion delimiter] = "\n"
diff --git a/resources/fixtures/scopes/shellscript/statement/statement.while2.scope b/resources/fixtures/scopes/shellscript/statement/statement.while2.scope
new file mode 100644
index 0000000000..0a662e56f7
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/statement/statement.while2.scope
@@ -0,0 +1,26 @@
+until true; do :; done
+---
+
+[#1 Content] =
+[#1 Removal] =
+[#1 Domain] = 0:0-0:22
+ >----------------------<
+0| until true; do :; done
+
+[#1 Insertion delimiter] = "\n"
+
+
+[#2 Content] =
+[#2 Domain] = 0:15-0:16
+ >-<
+0| until true; do :; done
+
+[#2 Removal] = 0:14-0:16
+ >--<
+0| until true; do :; done
+
+[#2 Leading delimiter] = 0:14-0:15
+ >-<
+0| until true; do :; done
+
+[#2 Insertion delimiter] = "\n"
diff --git a/resources/fixtures/scopes/shellscript/string.multiLine.scope b/resources/fixtures/scopes/shellscript/string.multiLine.scope
new file mode 100644
index 0000000000..e8f7baaa0a
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/string.multiLine.scope
@@ -0,0 +1,13 @@
+"Hello
+world"
+---
+
+[Content] =
+[Removal] =
+[Domain] = 0:0-1:6
+ >------
+0| "Hello
+1| world"
+ ------<
+
+[Insertion delimiter] = " "
diff --git a/resources/fixtures/scopes/shellscript/string.singleLine.scope b/resources/fixtures/scopes/shellscript/string.singleLine.scope
new file mode 100644
index 0000000000..4b26cf31b3
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/string.singleLine.scope
@@ -0,0 +1,10 @@
+"Hello world"
+---
+
+[Content] =
+[Removal] =
+[Domain] = 0:0-0:13
+ >-------------<
+0| "Hello world"
+
+[Insertion delimiter] = " "
diff --git a/resources/fixtures/scopes/shellscript/textFragment.comment.line.scope b/resources/fixtures/scopes/shellscript/textFragment.comment.line.scope
new file mode 100644
index 0000000000..2c362ef415
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/textFragment.comment.line.scope
@@ -0,0 +1,10 @@
+# Hello world
+---
+
+[Content] =
+[Removal] =
+[Domain] = 0:0-0:13
+ >-------------<
+0| # Hello world
+
+[Insertion delimiter] = " "
diff --git a/resources/fixtures/scopes/shellscript/textFragment.string.multiLine.scope b/resources/fixtures/scopes/shellscript/textFragment.string.multiLine.scope
new file mode 100644
index 0000000000..2780f7ce95
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/textFragment.string.multiLine.scope
@@ -0,0 +1,13 @@
+"Hello
+world"
+---
+
+[Content] =
+[Removal] =
+[Domain] = 0:1-1:5
+ >-----
+0| "Hello
+1| world"
+ -----<
+
+[Insertion delimiter] = " "
diff --git a/resources/fixtures/scopes/shellscript/textFragment.string.singleLine.scope b/resources/fixtures/scopes/shellscript/textFragment.string.singleLine.scope
new file mode 100644
index 0000000000..85dcf5fa7f
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/textFragment.string.singleLine.scope
@@ -0,0 +1,10 @@
+"Hello world"
+---
+
+[Content] =
+[Removal] =
+[Domain] = 0:1-0:12
+ >-----------<
+0| "Hello world"
+
+[Insertion delimiter] = " "
diff --git a/resources/fixtures/scopes/shellscript/value/value.assignment.compound.scope b/resources/fixtures/scopes/shellscript/value/value.assignment.compound.scope
new file mode 100644
index 0000000000..36f9cc162c
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/value/value.assignment.compound.scope
@@ -0,0 +1,20 @@
+foo+=0
+---
+
+[Content] = 0:5-0:6
+ >-<
+0| foo+=0
+
+[Removal] = 0:3-0:6
+ >---<
+0| foo+=0
+
+[Leading delimiter] = 0:3-0:5
+ >--<
+0| foo+=0
+
+[Domain] = 0:0-0:6
+ >------<
+0| foo+=0
+
+[Insertion delimiter] = " "
diff --git a/resources/fixtures/scopes/shellscript/value/value.assignment.scope b/resources/fixtures/scopes/shellscript/value/value.assignment.scope
new file mode 100644
index 0000000000..d394b2b757
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/value/value.assignment.scope
@@ -0,0 +1,20 @@
+foo=0
+---
+
+[Content] = 0:4-0:5
+ >-<
+0| foo=0
+
+[Removal] = 0:3-0:5
+ >--<
+0| foo=0
+
+[Leading delimiter] = 0:3-0:4
+ >-<
+0| foo=0
+
+[Domain] = 0:0-0:5
+ >-----<
+0| foo=0
+
+[Insertion delimiter] = " "
diff --git a/resources/fixtures/scopes/shellscript/value/value.constant.scope b/resources/fixtures/scopes/shellscript/value/value.constant.scope
new file mode 100644
index 0000000000..7c3986b198
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/value/value.constant.scope
@@ -0,0 +1,20 @@
+readonly foo=0
+---
+
+[Content] = 0:13-0:14
+ >-<
+0| readonly foo=0
+
+[Removal] = 0:12-0:14
+ >--<
+0| readonly foo=0
+
+[Leading delimiter] = 0:12-0:13
+ >-<
+0| readonly foo=0
+
+[Domain] = 0:0-0:14
+ >--------------<
+0| readonly foo=0
+
+[Insertion delimiter] = " "
diff --git a/resources/fixtures/scopes/shellscript/value/value.foreach.scope b/resources/fixtures/scopes/shellscript/value/value.foreach.scope
new file mode 100644
index 0000000000..998c653f28
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/value/value.foreach.scope
@@ -0,0 +1,20 @@
+for v in values; do :; done
+---
+
+[Content] = 0:9-0:15
+ >------<
+0| for v in values; do :; done
+
+[Removal] = 0:8-0:15
+ >-------<
+0| for v in values; do :; done
+
+[Leading delimiter] = 0:8-0:9
+ >-<
+0| for v in values; do :; done
+
+[Domain] = 0:0-0:27
+ >---------------------------<
+0| for v in values; do :; done
+
+[Insertion delimiter] = " "
diff --git a/resources/fixtures/scopes/shellscript/value/value.iteration.block.scope b/resources/fixtures/scopes/shellscript/value/value.iteration.block.scope
new file mode 100644
index 0000000000..c034392b82
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/value/value.iteration.block.scope
@@ -0,0 +1,13 @@
+foo() { }
+---
+
+[#1 Content] =
+[#1 Domain] = 0:0-0:9
+ >---------<
+0| foo() { }
+
+
+[#2 Content] =
+[#2 Domain] = 0:7-0:8
+ >-<
+0| foo() { }
diff --git a/resources/fixtures/scopes/shellscript/value/value.iteration.block3.scope b/resources/fixtures/scopes/shellscript/value/value.iteration.block3.scope
new file mode 100644
index 0000000000..61135ad7e7
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/value/value.iteration.block3.scope
@@ -0,0 +1,13 @@
+while true; do :; done
+---
+
+[#1 Content] =
+[#1 Domain] = 0:0-0:22
+ >----------------------<
+0| while true; do :; done
+
+
+[#2 Content] =
+[#2 Domain] = 0:14-0:18
+ >----<
+0| while true; do :; done
diff --git a/resources/fixtures/scopes/shellscript/value/value.iteration.document.scope b/resources/fixtures/scopes/shellscript/value/value.iteration.document.scope
new file mode 100644
index 0000000000..c73f4c1df8
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/value/value.iteration.document.scope
@@ -0,0 +1,12 @@
+
+declare foo
+
+---
+
+[Content] =
+[Domain] = 0:0-2:0
+ >
+0|
+1| declare foo
+2|
+ <
diff --git a/resources/fixtures/scopes/shellscript/value/value.mapPair.iteration.scope b/resources/fixtures/scopes/shellscript/value/value.mapPair.iteration.scope
new file mode 100644
index 0000000000..7eaa34a8da
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/value/value.mapPair.iteration.scope
@@ -0,0 +1,13 @@
+foo=(["aaa"]=0 ["bbb"]=1)
+---
+
+[#1 Content] =
+[#1 Domain] = 0:0-0:25
+ >-------------------------<
+0| foo=(["aaa"]=0 ["bbb"]=1)
+
+
+[#2 Content] =
+[#2 Domain] = 0:5-0:24
+ >-------------------<
+0| foo=(["aaa"]=0 ["bbb"]=1)
diff --git a/resources/fixtures/scopes/shellscript/value/value.mapPair.scope b/resources/fixtures/scopes/shellscript/value/value.mapPair.scope
new file mode 100644
index 0000000000..511aef3cb4
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/value/value.mapPair.scope
@@ -0,0 +1,48 @@
+foo=(["aaa"]=0 ["bbb"]=1)
+---
+
+[#1 Content] = 0:4-0:25
+ >---------------------<
+0| foo=(["aaa"]=0 ["bbb"]=1)
+
+[#1 Removal] = 0:3-0:25
+ >----------------------<
+0| foo=(["aaa"]=0 ["bbb"]=1)
+
+[#1 Leading delimiter] = 0:3-0:4
+ >-<
+0| foo=(["aaa"]=0 ["bbb"]=1)
+
+[#1 Domain] = 0:0-0:25
+ >-------------------------<
+0| foo=(["aaa"]=0 ["bbb"]=1)
+
+[#1 Insertion delimiter] = " "
+
+
+[#2 Content] =
+[#2 Removal] = 0:13-0:14
+ >-<
+0| foo=(["aaa"]=0 ["bbb"]=1)
+
+[#2 Trailing delimiter] = 0:14-0:15
+ >-<
+0| foo=(["aaa"]=0 ["bbb"]=1)
+
+[#2 Domain] = 0:5-0:14
+ >---------<
+0| foo=(["aaa"]=0 ["bbb"]=1)
+
+[#2 Insertion delimiter] = " "
+
+
+[#3 Content] =
+[#3 Removal] = 0:23-0:24
+ >-<
+0| foo=(["aaa"]=0 ["bbb"]=1)
+
+[#3 Domain] = 0:15-0:24
+ >---------<
+0| foo=(["aaa"]=0 ["bbb"]=1)
+
+[#3 Insertion delimiter] = " "
diff --git a/resources/fixtures/scopes/shellscript/value/value.return.scope b/resources/fixtures/scopes/shellscript/value/value.return.scope
new file mode 100644
index 0000000000..36c47c5d36
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/value/value.return.scope
@@ -0,0 +1,22 @@
+foo() {
+ return 0;
+}
+---
+
+[Content] = 1:11-1:12
+ >-<
+1| return 0;
+
+[Removal] = 1:10-1:12
+ >--<
+1| return 0;
+
+[Leading delimiter] = 1:10-1:11
+ >-<
+1| return 0;
+
+[Domain] = 1:4-1:12
+ >--------<
+1| return 0;
+
+[Insertion delimiter] = " "
diff --git a/resources/fixtures/scopes/shellscript/value/value.return2.scope b/resources/fixtures/scopes/shellscript/value/value.return2.scope
new file mode 100644
index 0000000000..7046cf05fe
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/value/value.return2.scope
@@ -0,0 +1,22 @@
+function foo {
+ return 0;
+}
+---
+
+[Content] = 1:11-1:12
+ >-<
+1| return 0;
+
+[Removal] = 1:10-1:12
+ >--<
+1| return 0;
+
+[Leading delimiter] = 1:10-1:11
+ >-<
+1| return 0;
+
+[Domain] = 1:4-1:12
+ >--------<
+1| return 0;
+
+[Insertion delimiter] = " "
diff --git a/resources/fixtures/scopes/shellscript/value/value.switch.scope b/resources/fixtures/scopes/shellscript/value/value.switch.scope
new file mode 100644
index 0000000000..0de4077af9
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/value/value.switch.scope
@@ -0,0 +1,24 @@
+case $foo in esac
+---
+
+[Content] = 0:5-0:9
+ >----<
+0| case $foo in esac
+
+[Removal] = 0:5-0:10
+ >-----<
+0| case $foo in esac
+
+[Leading delimiter] = 0:4-0:5
+ >-<
+0| case $foo in esac
+
+[Trailing delimiter] = 0:9-0:10
+ >-<
+0| case $foo in esac
+
+[Domain] = 0:0-0:17
+ >-----------------<
+0| case $foo in esac
+
+[Insertion delimiter] = " "
diff --git a/resources/fixtures/scopes/shellscript/value/value.variable.scope b/resources/fixtures/scopes/shellscript/value/value.variable.scope
new file mode 100644
index 0000000000..b440796c7b
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/value/value.variable.scope
@@ -0,0 +1,20 @@
+local foo=0
+---
+
+[Content] = 0:10-0:11
+ >-<
+0| local foo=0
+
+[Removal] = 0:9-0:11
+ >--<
+0| local foo=0
+
+[Leading delimiter] = 0:9-0:10
+ >-<
+0| local foo=0
+
+[Domain] = 0:0-0:11
+ >-----------<
+0| local foo=0
+
+[Insertion delimiter] = " "
diff --git a/resources/fixtures/scopes/shellscript/value/value.variable2.scope b/resources/fixtures/scopes/shellscript/value/value.variable2.scope
new file mode 100644
index 0000000000..c09311a2ff
--- /dev/null
+++ b/resources/fixtures/scopes/shellscript/value/value.variable2.scope
@@ -0,0 +1,20 @@
+declare foo=0
+---
+
+[Content] = 0:12-0:13
+ >-<
+0| declare foo=0
+
+[Removal] = 0:11-0:13
+ >--<
+0| declare foo=0
+
+[Leading delimiter] = 0:11-0:12
+ >-<
+0| declare foo=0
+
+[Domain] = 0:0-0:13
+ >-------------<
+0| declare foo=0
+
+[Insertion delimiter] = " "
diff --git a/resources/playground/shellscript.sh b/resources/playground/shellscript.sh
new file mode 100644
index 0000000000..85cda440fb
--- /dev/null
+++ b/resources/playground/shellscript.sh
@@ -0,0 +1,172 @@
+#!/bin/bash
+
+
+# Variable declaration
+var="Hello, World"
+array=("apple" "banana" "cherry")
+
+# Output variables
+echo "String variable: $var"
+echo "Number variable: $number"
+echo "Array variable: ${array[*]}"
+echo A B C
+# If statement
+if [ "$number" -eq 42 ]; then
+ echo "The number is 42"
+else
+ echo "The number is not 42"
+fi
+
+# For loop
+for item in "${array[@]}"; do
+ echo "Fruit: $item"
+done
+
+# While loop
+count=0
+while [ $count -lt 3 ]; do
+ echo "Count: $count"
+ ((count++))
+done
+
+# Function declaration
+my_function() {
+ local local_var="Local Variable"
+ echo "Function argument: $1"
+ echo "$local_var from function"
+}
+
+sub_function() (foo)
+sub_function() ((foo++))
+
+my_function "Function Argument"
+
+# Case statement
+case "$number" in
+1)
+ echo "Number is 1"
+ ;;
+2)
+ echo "Number is 2"
+ ;;
+42)
+ echo "Number is the answer to everything"
+ ;;
+*)
+ echo "Number is not recognized"
+ ;;
+esac
+
+# Advanced constructs
+# Command substitution
+current_date=$(date)
+
+# Conditional execution
+ls non_existent_file || echo "File not found"
+
+# Here document
+cat < "{1..5}
+
+# Extended globbing
+shopt -s extglob
+files="file1.txt file2.txt file3.log"
+echo "Extended Globbing: ${files%%.*(txt|log)}"
+
+# Conditional execution and redirection
+false && echo "This won't execute"
+true || echo "This will execute"
+
+# Input redirection
+cat .*)")
+)
+
+;;!! elif false; then
+;;! ^^^^^
+(
+ (elif_clause
+ (_) @condition
+ "then" @interior.start.endOf
+ ) @branch @branch.removal.start @condition.domain
+ .
+ _ @branch.removal.end.startOf @interior.end.startOf
+ (#trim-end! @branch)
+)
+
+;;!! else :; fi
+(
+ (else_clause
+ "else" @interior.start.endOf
+ ) @branch @branch.removal.start
+ "fi" @branch.removal.end.startOf @interior.end.startOf
+ (#trim-end! @branch)
+)
+
+;;!! ((true ? 0 : 1))
+;;! ^^^^
+(ternary_expression
+ condition: (_) @condition
+ consequence: (_) @branch
+) @condition.domain @branch.iteration
+
+(ternary_expression
+ alternative: (_) @branch
+)
+
+;;!! case $foo in esac
+;;! ^^^^
+;;! ^
+(case_statement
+ value: (_) @value
+ "in" @interior.start.endOf @branch.iteration.start.endOf @condition.iteration.start.endOf
+ "esac" @interior.end.startOf @branch.iteration.end.startOf @condition.iteration.end.startOf
+) @value.domain
+
+;;!! 0) : ;;
+;;! ^
+(case_item
+ value: (_) @condition
+ ")" @interior.start.endOf
+ ";;" @interior.end.startOf
+) @branch @condition.domain
+
+(case_item
+ ")" @statement.iteration.start.endOf @name.iteration.start.endOf @value.iteration.start.endOf
+ ";;" @statement.iteration.end.startOf @name.iteration.end.startOf @value.iteration.end.startOf
+)
+
+;;!! return 0
+;;! ^
+(
+ (command
+ name: (command_name
+ (word) @_dummy
+ )
+ argument: (_) @value
+ ) @value.domain
+ (#eq? @_dummy return)
+)
+
+;;!! do :; done
+;;! ^^^^
+(do_group
+ "do" @interior.start.endOf
+ "done" @interior.end.startOf
+)
+
+(do_group
+ "do" @statement.iteration.start.endOf @name.iteration.start.endOf @value.iteration.start.endOf
+ "done" @statement.iteration.end.startOf @name.iteration.end.startOf @value.iteration.end.startOf
+)
+
+;;!! foo() { }
+;;! ^
+(compound_statement
+ "{" @interior.start.endOf
+ "}" @interior.end.startOf
+)
+
+(compound_statement
+ "{" @statement.iteration.start.endOf @name.iteration.start.endOf @value.iteration.start.endOf
+ "}" @statement.iteration.end.startOf @name.iteration.end.startOf @value.iteration.end.startOf
+)
+
+;;!! # foo
+;;! ^^^^^
+(comment) @comment @textFragment
+
+;;!! var="foo"
+;;! ^^^^^
+(string
+ .
+ (string_content)? @textFragment.start
+ (string_content)? @textFragment.end
+ .
+) @string
+
+;;!! foo aaa bbb
+;;! ^^^^^^^^^^^
+;;! ^^^
+(command
+ name: (_) @functionCallee
+) @functionCallee.domain @functionCall
+
+;;!! foo aaa bbb
+;;! ^^^^^^^
+(command
+ name: (_)
+ .
+ argument: (_) @argumentList.start @argumentOrParameter.iteration.start
+ argument: (_)? @argumentList.end @argumentOrParameter.iteration.end
+ .
+) @argumentList.domain @argumentOrParameter.iteration.domain
+
+;;!! foo
+;;! ><
+(command
+ name: (_) @argumentList.start.endOf
+ !argument
+) @argumentList.domain
+
+;;!! foo aaa bbb
+;;! ^^^ ^^^
+(_
+ (command
+ name: (_)
+ argument: (_)? @_.leading.endOf
+ .
+ argument: (_) @argumentOrParameter
+ .
+ argument: (_)? @_.trailing.startOf
+ ) @_dummy
+ (#single-or-multi-line-delimiter! @argumentOrParameter @_dummy " " " \\\n")
+)
+
+;;!! function foo() {}
+;;! ^^^
+(function_definition
+ name: (_) @name
+) @namedFunction @name.domain
+
+;;!! for ((i = 1; i <= 5; i++)); do
+;;! ^
+(
+ (variable_assignment
+ name: (_) @name @value.leading.endOf
+ value: (_) @value @name.trailing.startOf
+ ) @_dummy @_.domain
+ (#not-parent-type? @_dummy declaration_command)
+)
+
+;;!! local foo="bar"
+;;! ^^^
+(declaration_command
+ (variable_assignment
+ name: (_) @name
+ value: (_) @_.removal.end.startOf
+ )
+) @name.domain @_.removal.start.startOf
+
+;;!! local foo="bar"
+;;! ^^^
+(declaration_command
+ (variable_assignment
+ name: (_) @_.leading.endOf
+ value: (_) @value
+ )
+) @value.domain
+
+;;!! local foo
+;;! ^^^
+(declaration_command
+ (variable_name) @name
+) @name.domain