diff --git a/data/playground/nix/asserts.nix b/data/playground/nix/asserts.nix new file mode 100644 index 0000000000..f17323bfba --- /dev/null +++ b/data/playground/nix/asserts.nix @@ -0,0 +1,25 @@ +# https://nixos.org/manual/nix/stable/language/constructs.html#assertions + +{ localServer ? false +, httpServer ? false +, sslSupport ? false +, pythonBindings ? false +, javaSwigBindings ? false +, javahlBindings ? false +, stdenv, fetchurl +, openssl ? null, httpd ? null, db4 ? null, expat, swig ? null, j2sdk ? null +}: + +assert localerver -> db4 != null; +assert httpServer -> httpd != null && httpd.expat == expat; +assert sslSupport -> openssl != null && (httpServer -> httpd.openssl == openssl); +assert pythonBindings -> swig != null && swig.pythonSupport; +assert javaSwigBindings -> swig != null && swig.javaSupport; +assert javahlBindings -> j2sdk != null; + +stdenv.mkDerivation { + (name = "subversion-1.1.1";) + ... + openssl = if sslSupport then openssl else null; + ... +} diff --git a/data/playground/nix/attrsets.nix b/data/playground/nix/attrsets.nix new file mode 100644 index 0000000000..dfd0115a58 --- /dev/null +++ b/data/playground/nix/attrsets.nix @@ -0,0 +1,19 @@ +{ + a = { a = b; c = d; }; + a = { + a = b; + c = d; + }; + + a = { + a = { + b = 1; }; + + c = { d = [ "1" 2 ] }; + }; + + a = rec { + a = b; + b = a + 1; + }; +} diff --git a/data/playground/nix/comments.nix b/data/playground/nix/comments.nix new file mode 100644 index 0000000000..10c0d44c69 --- /dev/null +++ b/data/playground/nix/comments.nix @@ -0,0 +1,8 @@ +# Single-line comment +/* + Multi-line comment +*/ +{ + a = b; # Inline comment (test) + b = c; # Inline comment 2 +} diff --git a/data/playground/nix/complex.nix b/data/playground/nix/complex.nix new file mode 100644 index 0000000000..68e2bfef6e --- /dev/null +++ b/data/playground/nix/complex.nix @@ -0,0 +1,67 @@ +{ + inputs = { + nixpkgs.url = "github:nixos/nixpkgs/nixos-23.05"; + home-manager = { + url = "github:nix-community/home-manager/release-23.05"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + }; + + outputs = { self, nixpkgs, home-manager }: + let + mkHost = hostName: system: + (({ my-config, zfs-root, pkgs, system, ... }: + nixpkgs.lib.nixosSystem { + inherit system; + modules = [ + # Module 0: zfs-root and my-config + ./modules + + # Module 1: host-specific config, if exist + (if (builtins.pathExists + ./hosts/${hostName}/configuration.nix) then + (import ./hosts/${hostName}/configuration.nix { inherit pkgs; }) + else + { }) + + # Module 2: entry point + (({ my-config, zfs-root, pkgs, lib, ... }: { + inherit my-config zfs-root; + system.configurationRevision = if (self ? rev) then + self.rev + else + throw "refuse to build: git tree is dirty"; + system.stateVersion = "23.05"; + imports = [ + "${nixpkgs}/nixos/modules/installer/scan/not-detected.nix" + # "${nixpkgs}/nixos/modules/profiles/hardened.nix" + # "${nixpkgs}/nixos/modules/profiles/qemu-guest.nix" + ]; + }) { + inherit my-config zfs-root pkgs; + lib = nixpkgs.lib; + }) + + # Module 3: home-manager + home-manager.nixosModules.home-manager + { + home-manager.useGlobalPkgs = true; + home-manager.useUserPackages = true; + } + + # Module 4: config shared by all hosts + (import ./configuration.nix { inherit pkgs; }) + ]; + }) + + # configuration input + (import ./hosts/${hostName} { + system = system; + pkgs = nixpkgs.legacyPackages.${system}; + })); + in { + nixosConfigurations = { + exampleHost = mkHost "exampleHost" "x86_64-linux"; + }; + }; +} diff --git a/data/playground/nix/functions.nix b/data/playground/nix/functions.nix new file mode 100644 index 0000000000..3082051ec9 --- /dev/null +++ b/data/playground/nix/functions.nix @@ -0,0 +1,13 @@ +{ + # Anonymous function + a = foo: (foo + 1); + x = a: b: a + b; + + # Non-built-in function + ba = test( foo: bar: { + b = foo; + }); + + # Built-in function + x = map (x: y: x + x) [ 1 2 3 ]; +} diff --git a/data/playground/nix/lists.nix b/data/playground/nix/lists.nix new file mode 100644 index 0000000000..7b535c6ba4 --- /dev/null +++ b/data/playground/nix/lists.nix @@ -0,0 +1,7 @@ +{ + foo = [ "a" a/b/c "b" ]; + bar = [ A + B + C # foo + ]; +} diff --git a/data/playground/nix/statements.nix b/data/playground/nix/statements.nix new file mode 100644 index 0000000000..a04b68596d --- /dev/null +++ b/data/playground/nix/statements.nix @@ -0,0 +1,36 @@ +{ + key = if a then b else c; + key = + if a + then b + else c; + + a = b; # Inline comment (test) + b = c; # Inline comment 2 + a = 1 + 1; + a = a/b/c ? 0; + a = b: b + 1; + + foo = let + a = b; + c = d; + in + { + output = b; + }; + + bar = let + a = 1; + b = 2; + in a + b; + + bar = + with key; + let + a = key; + in + a; + + a = x: x + 1; + b = x: y: x + y + 1; +} diff --git a/data/playground/nix/strings.nix b/data/playground/nix/strings.nix new file mode 100644 index 0000000000..da8e2dcdab --- /dev/null +++ b/data/playground/nix/strings.nix @@ -0,0 +1,13 @@ +{ + a = "double quoted string"; + b = ''two single quote string''; + c = '' + multi-line + quote string''; + d = "Interpolated ${value} string"; + e = "Escaped \${string} "; + f = '' + "Nested" + string + ''; +} diff --git a/packages/common/src/extensionDependencies.ts b/packages/common/src/extensionDependencies.ts index d748061247..a6f4fc4744 100644 --- a/packages/common/src/extensionDependencies.ts +++ b/packages/common/src/extensionDependencies.ts @@ -6,6 +6,7 @@ export const extensionDependencies = [ "scala-lang.scala", // scala "mrob95.vscode-talonscript", // talon "jrieken.vscode-tree-sitter-query", // scm + "bbenoist.nix", // nix "mathiasfrohlich.kotlin", // kotlin // Necessary for the `drink cell` and `pour cell` tests diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeArg.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeArg.yml new file mode 100644 index 0000000000..8efcae9e8c --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeArg.yml @@ -0,0 +1,27 @@ +languageId: nix +command: + version: 6 + spokenForm: change arg + action: + name: clearAndSetSelection + target: + type: primitive + modifiers: + - type: containingScope + scopeType: { type: argumentOrParameter } + usePrePhraseSnapshot: true +initialState: + documentContents: |- + { pkgs, ... }: + { a = 1; } + selections: + - anchor: { line: 0, character: 10 } + active: { line: 0, character: 10 } + marks: {} +finalState: + documentContents: |- + : + { a = 1; } + selections: + - anchor: { line: 0, character: 0 } + active: { line: 0, character: 0 } diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeArg2.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeArg2.yml new file mode 100644 index 0000000000..629adbd188 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeArg2.yml @@ -0,0 +1,27 @@ +languageId: nix +command: + version: 6 + spokenForm: change arg + action: + name: clearAndSetSelection + target: + type: primitive + modifiers: + - type: containingScope + scopeType: { type: argumentOrParameter } + usePrePhraseSnapshot: true +initialState: + documentContents: | + { pkgs, ... }: + { a = 1; } + selections: + - anchor: { line: 0, character: 3 } + active: { line: 0, character: 3 } + marks: {} +finalState: + documentContents: | + : + { a = 1; } + selections: + - anchor: { line: 0, character: 0 } + active: { line: 0, character: 0 } diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeArg3.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeArg3.yml new file mode 100644 index 0000000000..4d77988db4 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeArg3.yml @@ -0,0 +1,31 @@ +languageId: nix +command: + version: 6 + spokenForm: change arg + action: + name: clearAndSetSelection + target: + type: primitive + modifiers: + - type: containingScope + scopeType: { type: argumentOrParameter } + usePrePhraseSnapshot: true +initialState: + documentContents: | + { + outputs = { self, nix-darwin, nixpkgs, home-manager, sops-nix, ... }@inputs: + {}; + } + selections: + - anchor: { line: 1, character: 39 } + active: { line: 1, character: 39 } + marks: {} +finalState: + documentContents: | + { + outputs = : + {}; + } + selections: + - anchor: { line: 1, character: 14 } + active: { line: 1, character: 14 } diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeArg4.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeArg4.yml new file mode 100644 index 0000000000..ecfadb77f1 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeArg4.yml @@ -0,0 +1,31 @@ +languageId: nix +command: + version: 6 + spokenForm: change arg + action: + name: clearAndSetSelection + target: + type: primitive + modifiers: + - type: containingScope + scopeType: { type: argumentOrParameter } + usePrePhraseSnapshot: true +initialState: + documentContents: | + { + outputs = inputs@{ self, nix-darwin, nixpkgs, home-manager, sops-nix, ... }: + {}; + } + selections: + - anchor: { line: 1, character: 44 } + active: { line: 1, character: 44 } + marks: {} +finalState: + documentContents: | + { + outputs = : + {}; + } + selections: + - anchor: { line: 1, character: 14 } + active: { line: 1, character: 14 } diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeBranch.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeBranch.yml new file mode 100644 index 0000000000..512aae2282 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeBranch.yml @@ -0,0 +1,29 @@ +languageId: nix +command: + version: 6 + spokenForm: change branch + action: + name: clearAndSetSelection + target: + type: primitive + modifiers: + - type: containingScope + scopeType: { type: branch } + usePrePhraseSnapshot: true +initialState: + documentContents: |- + { + foo = if a then b else c; + } + selections: + - anchor: { line: 1, character: 9 } + active: { line: 1, character: 9 } + marks: {} +finalState: + documentContents: |- + { + foo = else c; + } + selections: + - anchor: { line: 1, character: 8 } + active: { line: 1, character: 8 } diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeBranch2.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeBranch2.yml new file mode 100644 index 0000000000..b8274bb944 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeBranch2.yml @@ -0,0 +1,32 @@ +languageId: nix +command: + version: 6 + spokenForm: change branch + action: + name: clearAndSetSelection + target: + type: primitive + modifiers: + - type: containingScope + scopeType: { type: branch } + usePrePhraseSnapshot: true +initialState: + documentContents: | + { + foo = if a + then b + else c; + } + selections: + - anchor: { line: 1, character: 9 } + active: { line: 1, character: 9 } + marks: {} +finalState: + documentContents: | + { + foo = + else c; + } + selections: + - anchor: { line: 1, character: 8 } + active: { line: 1, character: 8 } diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeBranch3.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeBranch3.yml new file mode 100644 index 0000000000..c97883b27d --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeBranch3.yml @@ -0,0 +1,31 @@ +languageId: nix +command: + version: 6 + spokenForm: change branch + action: + name: clearAndSetSelection + target: + type: primitive + modifiers: + - type: containingScope + scopeType: { type: branch } + usePrePhraseSnapshot: true +initialState: + documentContents: | + { + key = if a then b else c; + + } + selections: + - anchor: { line: 1, character: 22 } + active: { line: 1, character: 22 } + marks: {} +finalState: + documentContents: | + { + key = if a then b ; + + } + selections: + - anchor: { line: 1, character: 20 } + active: { line: 1, character: 20 } diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeCall.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeCall.yml new file mode 100644 index 0000000000..e61fd37cf2 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeCall.yml @@ -0,0 +1,29 @@ +languageId: nix +command: + version: 6 + spokenForm: change call + action: + name: clearAndSetSelection + target: + type: primitive + modifiers: + - type: containingScope + scopeType: { type: functionCall } + usePrePhraseSnapshot: true +initialState: + documentContents: | + { + x = map (x: y: x + x) [ 1 2 3 ]; + } + selections: + - anchor: { line: 1, character: 28 } + active: { line: 1, character: 28 } + marks: {} +finalState: + documentContents: | + { + x = ; + } + selections: + - anchor: { line: 1, character: 6 } + active: { line: 1, character: 6 } diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeCall2.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeCall2.yml new file mode 100644 index 0000000000..88cc263789 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeCall2.yml @@ -0,0 +1,31 @@ +languageId: nix +command: + version: 6 + spokenForm: change call + action: + name: clearAndSetSelection + target: + type: primitive + modifiers: + - type: containingScope + scopeType: { type: functionCall } + usePrePhraseSnapshot: true +initialState: + documentContents: |- + { + devShells = forEachSupportedSystem ({ pkgs }: { + default = pkgs.mkShell {}; + }); + } + selections: + - anchor: { line: 1, character: 24 } + active: { line: 1, character: 24 } + marks: {} +finalState: + documentContents: |- + { + devShells = ; + } + selections: + - anchor: { line: 1, character: 16 } + active: { line: 1, character: 16 } diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeCallee.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeCallee.yml new file mode 100644 index 0000000000..2eca997028 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeCallee.yml @@ -0,0 +1,29 @@ +languageId: nix +command: + version: 6 + spokenForm: change callee + action: + name: clearAndSetSelection + target: + type: primitive + modifiers: + - type: containingScope + scopeType: { type: functionCallee } + usePrePhraseSnapshot: true +initialState: + documentContents: | + { + x = map (x: y: x + x) [ 1 2 3 ]; + } + selections: + - anchor: { line: 1, character: 14 } + active: { line: 1, character: 14 } + marks: {} +finalState: + documentContents: | + { + x = (x: y: x + x) [ 1 2 3 ]; + } + selections: + - anchor: { line: 1, character: 6 } + active: { line: 1, character: 6 } diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeComment.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeComment.yml new file mode 100644 index 0000000000..dbbce401be --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeComment.yml @@ -0,0 +1,25 @@ +languageId: nix +command: + version: 6 + spokenForm: change comment + action: + name: clearAndSetSelection + target: + type: primitive + modifiers: + - type: containingScope + scopeType: { type: comment } + usePrePhraseSnapshot: true +initialState: + documentContents: | + # Single-line comment + selections: + - anchor: { line: 0, character: 21 } + active: { line: 0, character: 21 } + marks: {} +finalState: + documentContents: |+ + + selections: + - anchor: { line: 0, character: 0 } + active: { line: 0, character: 0 } diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeComment2.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeComment2.yml new file mode 100644 index 0000000000..0ed589ec9b --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeComment2.yml @@ -0,0 +1,27 @@ +languageId: nix +command: + version: 6 + spokenForm: change comment + action: + name: clearAndSetSelection + target: + type: primitive + modifiers: + - type: containingScope + scopeType: { type: comment } + usePrePhraseSnapshot: true +initialState: + documentContents: | + /* + Multi-line comment + */ + selections: + - anchor: { line: 2, character: 0 } + active: { line: 2, character: 0 } + marks: {} +finalState: + documentContents: |+ + + selections: + - anchor: { line: 0, character: 0 } + active: { line: 0, character: 0 } diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeComment3.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeComment3.yml new file mode 100644 index 0000000000..7d2b5be8a3 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeComment3.yml @@ -0,0 +1,31 @@ +languageId: nix +command: + version: 6 + spokenForm: change comment + action: + name: clearAndSetSelection + target: + type: primitive + modifiers: + - type: containingScope + scopeType: { type: comment } + usePrePhraseSnapshot: true +initialState: + documentContents: | + { + a = b; # Inline comment (test) + b = c; # Inline comment 2 + } + selections: + - anchor: { line: 2, character: 13 } + active: { line: 2, character: 13 } + marks: {} +finalState: + documentContents: | + { + a = b; # Inline comment (test) + b = c; + } + selections: + - anchor: { line: 2, character: 9 } + active: { line: 2, character: 9 } diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeCondition.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeCondition.yml new file mode 100644 index 0000000000..ec236c8bbb --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeCondition.yml @@ -0,0 +1,35 @@ +languageId: nix +command: + version: 6 + spokenForm: change condition + action: + name: clearAndSetSelection + target: + type: primitive + modifiers: + - type: containingScope + scopeType: { type: condition } + usePrePhraseSnapshot: true +initialState: + documentContents: | + { + key = + if a > b + then b + else c; + } + selections: + - anchor: { line: 3, character: 9 } + active: { line: 3, character: 9 } + marks: {} +finalState: + documentContents: | + { + key = + if + then b + else c; + } + selections: + - anchor: { line: 2, character: 7 } + active: { line: 2, character: 7 } diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeCondition2.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeCondition2.yml new file mode 100644 index 0000000000..3a66a10983 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeCondition2.yml @@ -0,0 +1,29 @@ +languageId: nix +command: + version: 6 + spokenForm: change condition + action: + name: clearAndSetSelection + target: + type: primitive + modifiers: + - type: containingScope + scopeType: { type: condition } + usePrePhraseSnapshot: true +initialState: + documentContents: | + { + key = assert a > b; "foo"; + } + selections: + - anchor: { line: 1, character: 11 } + active: { line: 1, character: 11 } + marks: {} +finalState: + documentContents: | + { + key = assert ; "foo"; + } + selections: + - anchor: { line: 1, character: 15 } + active: { line: 1, character: 15 } diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeCondition3.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeCondition3.yml new file mode 100644 index 0000000000..d4c5a31f51 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeCondition3.yml @@ -0,0 +1,31 @@ +languageId: nix +command: + version: 6 + spokenForm: change condition + action: + name: clearAndSetSelection + target: + type: primitive + modifiers: + - type: containingScope + scopeType: { type: condition } + usePrePhraseSnapshot: true +initialState: + documentContents: |- + { a ? false, b ? false , c ? null }: + assert a -> c != null; + assert b -> c != null; + {foo = a;} + selections: + - anchor: { line: 1, character: 13 } + active: { line: 1, character: 13 } + marks: {} +finalState: + documentContents: |- + { a ? false, b ? false , c ? null }: + assert ; + assert b -> c != null; + {foo = a;} + selections: + - anchor: { line: 1, character: 11 } + active: { line: 1, character: 11 } diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeCondition4.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeCondition4.yml new file mode 100644 index 0000000000..7fa2b87bed --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeCondition4.yml @@ -0,0 +1,31 @@ +languageId: nix +command: + version: 6 + spokenForm: change condition + action: + name: clearAndSetSelection + target: + type: primitive + modifiers: + - type: containingScope + scopeType: { type: condition } + usePrePhraseSnapshot: true +initialState: + documentContents: |- + { a ? false, b ? false , c ? null }: + assert a -> c != null; + assert b -> c != null; + {foo = a;} + selections: + - anchor: { line: 3, character: 9 } + active: { line: 3, character: 9 } + marks: {} +finalState: + documentContents: |- + { a ? false, b ? false , c ? null }: + assert a -> c != null; + assert ; + {foo = a;} + selections: + - anchor: { line: 2, character: 11 } + active: { line: 2, character: 11 } diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeEveryIfState.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeEveryIfState.yml new file mode 100644 index 0000000000..5b53c43839 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeEveryIfState.yml @@ -0,0 +1,37 @@ +languageId: nix +command: + version: 6 + spokenForm: change every if state + action: + name: clearAndSetSelection + target: + type: primitive + modifiers: + - type: everyScope + scopeType: { type: ifStatement } + usePrePhraseSnapshot: true +initialState: + documentContents: | + { + key = if a then b else c; + key = + if a + then b + else c; + } + selections: + - anchor: { line: 5, character: 11 } + active: { line: 5, character: 11 } + marks: {} +finalState: + documentContents: | + { + key = ; + key = + ; + } + selections: + - anchor: { line: 1, character: 8 } + active: { line: 1, character: 8 } + - anchor: { line: 3, character: 4 } + active: { line: 3, character: 4 } diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeEveryItem.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeEveryItem.yml new file mode 100644 index 0000000000..3954444201 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeEveryItem.yml @@ -0,0 +1,34 @@ +languageId: nix +command: + version: 6 + spokenForm: change every item + action: + name: clearAndSetSelection + target: + type: primitive + modifiers: + - type: everyScope + scopeType: { type: collectionItem } + usePrePhraseSnapshot: true +initialState: + documentContents: |+ + foo = [ "a" a/b/c "b" ]; + + selections: + - anchor: { line: 0, character: 9 } + active: { line: 0, character: 9 } + marks: {} +finalState: + documentContents: |+ + foo = [ ]; + + selections: + - anchor: { line: 0, character: 8 } + active: { line: 0, character: 8 } + - anchor: { line: 0, character: 9 } + active: { line: 0, character: 9 } + - anchor: { line: 0, character: 10 } + active: { line: 0, character: 10 } +ide: + messages: + - { type: error, id: BaseTreeSitterScopeHandler.allow-multiple } diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeEveryMap.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeEveryMap.yml new file mode 100644 index 0000000000..c38a981c75 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeEveryMap.yml @@ -0,0 +1,56 @@ +languageId: nix +command: + version: 6 + spokenForm: change every map + action: + name: clearAndSetSelection + target: + type: primitive + modifiers: + - type: everyScope + scopeType: { type: map } + usePrePhraseSnapshot: true +initialState: + documentContents: | + { + a = { a = b; c = d; }; + a = { + a = b; + c = d; + }; + + a = { + a = { + b = 1; }; + + c = { d = [ "1" 2 ] }; + }; + + a = rec { + a = b; + b = a + 1; + }; + } + selections: + - anchor: { line: 13, character: 0 } + active: { line: 13, character: 0 } + marks: {} +finalState: + documentContents: | + { + a = ; + a = ; + + a = ; + + a = ; + } + selections: + - anchor: { line: 1, character: 8 } + active: { line: 1, character: 8 } + - anchor: { line: 2, character: 8 } + active: { line: 2, character: 8 } + - anchor: { line: 4, character: 8 } + active: { line: 4, character: 8 } + - anchor: { line: 6, character: 8 } + active: { line: 6, character: 8 } diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeEveryMap2.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeEveryMap2.yml new file mode 100644 index 0000000000..ffcf9f8b7f --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeEveryMap2.yml @@ -0,0 +1,62 @@ +languageId: nix +command: + version: 6 + spokenForm: change every map + action: + name: clearAndSetSelection + target: + type: primitive + modifiers: + - type: everyScope + scopeType: { type: map } + usePrePhraseSnapshot: true +initialState: + documentContents: | + { + a = { a = b; c = d; }; + a = { + a = b; + c = d; + }; + + a = { + a = { + b = 1; }; + + c = { d = [ "1" 2 ] }; + }; + + a = rec { + a = b; + b = a + 1; + }; + } + selections: + - anchor: { line: 10, character: 0 } + active: { line: 10, character: 0 } + marks: {} +finalState: + documentContents: | + { + a = { a = b; c = d; }; + a = { + a = b; + c = d; + }; + + a = { + a = ; + + c = ; + }; + + a = rec { + a = b; + b = a + 1; + }; + } + selections: + - anchor: { line: 8, character: 12 } + active: { line: 8, character: 12 } + - anchor: { line: 10, character: 12 } + active: { line: 10, character: 12 } diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeFunkName.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeFunkName.yml new file mode 100644 index 0000000000..89c65b849d --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeFunkName.yml @@ -0,0 +1,29 @@ +languageId: nix +command: + version: 6 + spokenForm: change funk name + action: + name: clearAndSetSelection + target: + type: primitive + modifiers: + - type: containingScope + scopeType: { type: functionName } + usePrePhraseSnapshot: true +initialState: + documentContents: | + { + x = a: b: a + b; + } + selections: + - anchor: { line: 1, character: 16 } + active: { line: 1, character: 16 } + marks: {} +finalState: + documentContents: | + { + = a: b: a + b; + } + selections: + - anchor: { line: 1, character: 2 } + active: { line: 1, character: 2 } diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeIfState.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeIfState.yml new file mode 100644 index 0000000000..a42cbbd38f --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeIfState.yml @@ -0,0 +1,29 @@ +languageId: nix +command: + version: 6 + spokenForm: change if state + action: + name: clearAndSetSelection + target: + type: primitive + modifiers: + - type: containingScope + scopeType: { type: ifStatement } + usePrePhraseSnapshot: true +initialState: + documentContents: | + { + key = if a then b else c; + } + selections: + - anchor: { line: 1, character: 24 } + active: { line: 1, character: 24 } + marks: {} +finalState: + documentContents: | + { + key = ; + } + selections: + - anchor: { line: 1, character: 8 } + active: { line: 1, character: 8 } diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeInsideFunk.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeInsideFunk.yml new file mode 100644 index 0000000000..761054fc81 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeInsideFunk.yml @@ -0,0 +1,30 @@ +languageId: nix +command: + version: 6 + spokenForm: change inside funk + action: + name: clearAndSetSelection + target: + type: primitive + modifiers: + - { type: interiorOnly } + - type: containingScope + scopeType: { type: namedFunction } + usePrePhraseSnapshot: true +initialState: + documentContents: | + { + x = a: b: a + b; + } + selections: + - anchor: { line: 1, character: 16 } + active: { line: 1, character: 16 } + marks: {} +finalState: + documentContents: | + { + x = ; + } + selections: + - anchor: { line: 1, character: 6 } + active: { line: 1, character: 6 } diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeInsideLambda.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeInsideLambda.yml new file mode 100644 index 0000000000..f7ff318bb6 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeInsideLambda.yml @@ -0,0 +1,30 @@ +languageId: nix +command: + version: 6 + spokenForm: change inside lambda + action: + name: clearAndSetSelection + target: + type: primitive + modifiers: + - { type: interiorOnly } + - type: containingScope + scopeType: { type: anonymousFunction } + usePrePhraseSnapshot: true +initialState: + documentContents: |- + { + x = a: b: a + b; + } + selections: + - anchor: { line: 1, character: 9 } + active: { line: 1, character: 9 } + marks: {} +finalState: + documentContents: |- + { + x = a: b: ; + } + selections: + - anchor: { line: 1, character: 12 } + active: { line: 1, character: 12 } diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeInsideList.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeInsideList.yml new file mode 100644 index 0000000000..e244bfe1a1 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeInsideList.yml @@ -0,0 +1,24 @@ +languageId: nix +command: + version: 6 + spokenForm: change inside list + action: + name: clearAndSetSelection + target: + type: primitive + modifiers: + - { type: interiorOnly } + - type: containingScope + scopeType: { type: list } + usePrePhraseSnapshot: true +initialState: + documentContents: '{ d = [ "1" 2 ]; }' + selections: + - anchor: { line: 0, character: 10 } + active: { line: 0, character: 10 } + marks: {} +finalState: + documentContents: "{ d = [ ]; }" + selections: + - anchor: { line: 0, character: 8 } + active: { line: 0, character: 8 } diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeItem.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeItem.yml new file mode 100644 index 0000000000..d99c7625c8 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeItem.yml @@ -0,0 +1,29 @@ +languageId: nix +command: + version: 6 + spokenForm: change item + action: + name: clearAndSetSelection + target: + type: primitive + modifiers: + - type: containingScope + scopeType: { type: collectionItem } + usePrePhraseSnapshot: true +initialState: + documentContents: | + { + foo = [ "a" a/b/c "b" ]; + } + selections: + - anchor: { line: 1, character: 17 } + active: { line: 1, character: 17 } + marks: {} +finalState: + documentContents: | + { + foo = [ "a" "b" ]; + } + selections: + - anchor: { line: 1, character: 14 } + active: { line: 1, character: 14 } diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeItem2.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeItem2.yml new file mode 100644 index 0000000000..2824b94622 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeItem2.yml @@ -0,0 +1,35 @@ +languageId: nix +command: + version: 6 + spokenForm: change item + action: + name: clearAndSetSelection + target: + type: primitive + modifiers: + - type: containingScope + scopeType: { type: collectionItem } + usePrePhraseSnapshot: true +initialState: + documentContents: | + { + bar = [ A + B + C # foo + ]; + } + selections: + - anchor: { line: 2, character: 10 } + active: { line: 2, character: 10 } + marks: {} +finalState: + documentContents: | + { + bar = [ A + + C # foo + ]; + } + selections: + - anchor: { line: 2, character: 10 } + active: { line: 2, character: 10 } diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeKey.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeKey.yml new file mode 100644 index 0000000000..b1002acb83 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeKey.yml @@ -0,0 +1,29 @@ +languageId: nix +command: + version: 6 + spokenForm: change key + action: + name: clearAndSetSelection + target: + type: primitive + modifiers: + - type: containingScope + scopeType: { type: collectionKey } + usePrePhraseSnapshot: true +initialState: + documentContents: | + { + foo = { x = 1; y = 2; }; + } + selections: + - anchor: { line: 1, character: 14 } + active: { line: 1, character: 14 } + marks: {} +finalState: + documentContents: | + { + foo = { = 1; y = 2; }; + } + selections: + - anchor: { line: 1, character: 10 } + active: { line: 1, character: 10 } diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeKeyPlex.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeKeyPlex.yml new file mode 100644 index 0000000000..422d25d675 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeKeyPlex.yml @@ -0,0 +1,33 @@ +languageId: nix +command: + version: 6 + spokenForm: change key plex + action: + name: clearAndSetSelection + target: + type: primitive + mark: { type: decoratedSymbol, symbolColor: default, character: x } + modifiers: + - type: containingScope + scopeType: { type: collectionKey } + usePrePhraseSnapshot: true +initialState: + documentContents: | + { + foo = { x = 1; y = 2; }; + } + selections: + - anchor: { line: 1, character: 12 } + active: { line: 1, character: 12 } + marks: + default.x: + start: { line: 1, character: 10 } + end: { line: 1, character: 11 } +finalState: + documentContents: | + { + foo = { = 1; y = 2; }; + } + selections: + - anchor: { line: 1, character: 10 } + active: { line: 1, character: 10 } diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeList.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeList.yml new file mode 100644 index 0000000000..e72bc2c433 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeList.yml @@ -0,0 +1,29 @@ +languageId: nix +command: + version: 6 + spokenForm: change list + action: + name: clearAndSetSelection + target: + type: primitive + modifiers: + - type: containingScope + scopeType: { type: list } + usePrePhraseSnapshot: true +initialState: + documentContents: | + { + foo = [ "a" a/b/c "b" ]; + } + selections: + - anchor: { line: 1, character: 23 } + active: { line: 1, character: 23 } + marks: {} +finalState: + documentContents: | + { + foo = ; + } + selections: + - anchor: { line: 1, character: 8 } + active: { line: 1, character: 8 } diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeListGreenAir.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeListGreenAir.yml new file mode 100644 index 0000000000..dc58c1c6fb --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeListGreenAir.yml @@ -0,0 +1,36 @@ +languageId: nix +command: + version: 6 + spokenForm: change list green air + action: + name: clearAndSetSelection + target: + type: primitive + mark: { type: decoratedSymbol, symbolColor: green, character: a } + modifiers: + - type: containingScope + scopeType: { type: list } + usePrePhraseSnapshot: true +initialState: + documentContents: | + { + bar = [ A + B + C # foo + ]; + } + selections: + - anchor: { line: 0, character: 1 } + active: { line: 0, character: 1 } + marks: + green.a: + start: { line: 1, character: 10 } + end: { line: 1, character: 11 } +finalState: + documentContents: | + { + bar = ; + } + selections: + - anchor: { line: 1, character: 8 } + active: { line: 1, character: 8 } diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeMap.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeMap.yml new file mode 100644 index 0000000000..0c059d1c3f --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeMap.yml @@ -0,0 +1,37 @@ +languageId: nix +command: + version: 6 + spokenForm: change map + action: + name: clearAndSetSelection + target: + type: primitive + modifiers: + - type: containingScope + scopeType: { type: map } + usePrePhraseSnapshot: true +initialState: + documentContents: | + { + a = { a = b; c = d; }; + a = { + a = b; + c = d; + }; + } + selections: + - anchor: { line: 1, character: 12 } + active: { line: 1, character: 12 } + marks: {} +finalState: + documentContents: | + { + a = ; + a = { + a = b; + c = d; + }; + } + selections: + - anchor: { line: 1, character: 8 } + active: { line: 1, character: 8 } diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeMap2.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeMap2.yml new file mode 100644 index 0000000000..f7517b2711 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeMap2.yml @@ -0,0 +1,34 @@ +languageId: nix +command: + version: 6 + spokenForm: change map + action: + name: clearAndSetSelection + target: + type: primitive + modifiers: + - type: containingScope + scopeType: { type: map } + usePrePhraseSnapshot: true +initialState: + documentContents: | + { + a = { a = b; c = d; }; + a = { + a = b; + c = d; + }; + } + selections: + - anchor: { line: 3, character: 12 } + active: { line: 3, character: 12 } + marks: {} +finalState: + documentContents: | + { + a = { a = b; c = d; }; + a = ; + } + selections: + - anchor: { line: 2, character: 8 } + active: { line: 2, character: 8 } diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeMap3.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeMap3.yml new file mode 100644 index 0000000000..5c51e136a7 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeMap3.yml @@ -0,0 +1,31 @@ +languageId: nix +command: + version: 6 + spokenForm: change map + action: + name: clearAndSetSelection + target: + type: primitive + modifiers: + - type: containingScope + scopeType: { type: map } + usePrePhraseSnapshot: true +initialState: + documentContents: | + { + a = { a = b; c = d; }; + a = { + a = b; + c = d; + }; + } + selections: + - anchor: { line: 6, character: 0 } + active: { line: 6, character: 0 } + marks: {} +finalState: + documentContents: |+ + + selections: + - anchor: { line: 0, character: 0 } + active: { line: 0, character: 0 } diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeMap4.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeMap4.yml new file mode 100644 index 0000000000..c7f7bef354 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeMap4.yml @@ -0,0 +1,32 @@ +languageId: nix +command: + version: 6 + spokenForm: change map + action: + name: clearAndSetSelection + target: + type: primitive + modifiers: + - type: containingScope + scopeType: { type: map } + usePrePhraseSnapshot: true +initialState: + documentContents: | + { + a = rec { + a = b; + b = a + 1; + }; + } + selections: + - anchor: { line: 2, character: 5 } + active: { line: 2, character: 5 } + marks: {} +finalState: + documentContents: | + { + a = ; + } + selections: + - anchor: { line: 1, character: 8 } + active: { line: 1, character: 8 } diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeName.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeName.yml new file mode 100644 index 0000000000..3b5d465cd9 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeName.yml @@ -0,0 +1,43 @@ +languageId: nix +command: + version: 6 + spokenForm: change name + action: + name: clearAndSetSelection + target: + type: primitive + modifiers: + - type: containingScope + scopeType: { type: name } + usePrePhraseSnapshot: true +initialState: + documentContents: | + { + foo = let + a = b; + c = d; + in + { + output = b; + }; + + } + selections: + - anchor: { line: 1, character: 11 } + active: { line: 1, character: 11 } + marks: {} +finalState: + documentContents: | + { + = let + a = b; + c = d; + in + { + output = b; + }; + + } + selections: + - anchor: { line: 1, character: 2 } + active: { line: 1, character: 2 } diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeName2.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeName2.yml new file mode 100644 index 0000000000..654c92b3c7 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeName2.yml @@ -0,0 +1,43 @@ +languageId: nix +command: + version: 6 + spokenForm: change name + action: + name: clearAndSetSelection + target: + type: primitive + modifiers: + - type: containingScope + scopeType: { type: name } + usePrePhraseSnapshot: true +initialState: + documentContents: | + { + foo = let + a = b; + c = d; + in + { + output = b; + }; + + } + selections: + - anchor: { line: 2, character: 10 } + active: { line: 2, character: 10 } + marks: {} +finalState: + documentContents: | + { + foo = let + = b; + c = d; + in + { + output = b; + }; + + } + selections: + - anchor: { line: 2, character: 4 } + active: { line: 2, character: 4 } diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeRound.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeRound.yml new file mode 100644 index 0000000000..f59b1831af --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeRound.yml @@ -0,0 +1,29 @@ +languageId: nix +command: + version: 6 + spokenForm: change round + action: + name: clearAndSetSelection + target: + type: primitive + modifiers: + - type: containingScope + scopeType: { type: surroundingPair, delimiter: parentheses } + usePrePhraseSnapshot: true +initialState: + documentContents: | + { + foo = 1; # Test (round) + } + selections: + - anchor: { line: 1, character: 23 } + active: { line: 1, character: 23 } + marks: {} +finalState: + documentContents: | + { + foo = 1; # Test + } + selections: + - anchor: { line: 1, character: 18 } + active: { line: 1, character: 18 } diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeRound2.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeRound2.yml new file mode 100644 index 0000000000..5dfdd92c9a --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeRound2.yml @@ -0,0 +1,29 @@ +languageId: nix +command: + version: 6 + spokenForm: change round + action: + name: clearAndSetSelection + target: + type: primitive + modifiers: + - type: containingScope + scopeType: { type: surroundingPair, delimiter: parentheses } + usePrePhraseSnapshot: true +initialState: + documentContents: | + { + b = ''two single (quote) string''; + } + selections: + - anchor: { line: 1, character: 22 } + active: { line: 1, character: 22 } + marks: {} +finalState: + documentContents: | + { + b = ''two single string''; + } + selections: + - anchor: { line: 1, character: 19 } + active: { line: 1, character: 19 } diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeState.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeState.yml new file mode 100644 index 0000000000..699cd3ad72 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeState.yml @@ -0,0 +1,29 @@ +languageId: nix +command: + version: 6 + spokenForm: change state + action: + name: clearAndSetSelection + target: + type: primitive + modifiers: + - type: containingScope + scopeType: { type: statement } + usePrePhraseSnapshot: true +initialState: + documentContents: | + { config, lib, pkgs, ... }: + with lib; + { foo = libthing; } + selections: + - anchor: { line: 1, character: 4 } + active: { line: 1, character: 4 } + marks: {} +finalState: + documentContents: | + { config, lib, pkgs, ... }: + + { foo = libthing; } + selections: + - anchor: { line: 1, character: 0 } + active: { line: 1, character: 0 } diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeState2.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeState2.yml new file mode 100644 index 0000000000..7985542b63 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeState2.yml @@ -0,0 +1,31 @@ +languageId: nix +command: + version: 6 + spokenForm: change state + action: + name: clearAndSetSelection + target: + type: primitive + modifiers: + - type: containingScope + scopeType: { type: statement } + usePrePhraseSnapshot: true +initialState: + documentContents: |- + { a ? false, b ? false , c ? null }: + assert a -> c != null; + assert b -> c != null; + {foo = a;} + selections: + - anchor: { line: 1, character: 9 } + active: { line: 1, character: 9 } + marks: {} +finalState: + documentContents: |- + { a ? false, b ? false , c ? null }: + + assert b -> c != null; + {foo = a;} + selections: + - anchor: { line: 1, character: 4 } + active: { line: 1, character: 4 } diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeState3.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeState3.yml new file mode 100644 index 0000000000..252b7a6aa2 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeState3.yml @@ -0,0 +1,21 @@ +languageId: nix +command: + version: 6 + spokenForm: change state + action: + name: clearAndSetSelection + target: + type: primitive + modifiers: + - type: containingScope + scopeType: { type: statement } + usePrePhraseSnapshot: true +initialState: + documentContents: |- + { a ? false, b ? false , c ? null }: + {foo = assert b != false; a;} + selections: + - anchor: { line: 1, character: 19 } + active: { line: 1, character: 19 } + marks: {} +thrownError: { name: NoContainingScopeError } diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeString.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeString.yml new file mode 100644 index 0000000000..6618232fa1 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeString.yml @@ -0,0 +1,29 @@ +languageId: nix +command: + version: 6 + spokenForm: change string + action: + name: clearAndSetSelection + target: + type: primitive + modifiers: + - type: containingScope + scopeType: { type: surroundingPair, delimiter: string } + usePrePhraseSnapshot: true +initialState: + documentContents: | + { + a = "double quoted string"; + } + selections: + - anchor: { line: 1, character: 25 } + active: { line: 1, character: 25 } + marks: {} +finalState: + documentContents: | + { + a = ; + } + selections: + - anchor: { line: 1, character: 6 } + active: { line: 1, character: 6 } diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeString2.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeString2.yml new file mode 100644 index 0000000000..e46e50d4d1 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeString2.yml @@ -0,0 +1,29 @@ +languageId: nix +command: + version: 6 + spokenForm: change string + action: + name: clearAndSetSelection + target: + type: primitive + modifiers: + - type: containingScope + scopeType: { type: surroundingPair, delimiter: string } + usePrePhraseSnapshot: true +initialState: + documentContents: | + { + b = ''two single (quote) string''; + } + selections: + - anchor: { line: 1, character: 16 } + active: { line: 1, character: 16 } + marks: {} +finalState: + documentContents: | + { + b = ; + } + selections: + - anchor: { line: 1, character: 6 } + active: { line: 1, character: 6 } diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeString3.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeString3.yml new file mode 100644 index 0000000000..d77a3530b3 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeString3.yml @@ -0,0 +1,31 @@ +languageId: nix +command: + version: 6 + spokenForm: change string + action: + name: clearAndSetSelection + target: + type: primitive + modifiers: + - type: containingScope + scopeType: { type: surroundingPair, delimiter: string } + usePrePhraseSnapshot: true +initialState: + documentContents: | + { + c = '' + multi-line + quote string''; + } + selections: + - anchor: { line: 3, character: 4 } + active: { line: 3, character: 4 } + marks: {} +finalState: + documentContents: | + { + c = ; + } + selections: + - anchor: { line: 1, character: 6 } + active: { line: 1, character: 6 } diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeValue.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeValue.yml new file mode 100644 index 0000000000..442671bd42 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeValue.yml @@ -0,0 +1,37 @@ +languageId: nix +command: + version: 6 + spokenForm: change value + action: + name: clearAndSetSelection + target: + type: primitive + modifiers: + - type: containingScope + scopeType: { type: value } + usePrePhraseSnapshot: true +initialState: + documentContents: | + { + foo = let + a = b; + c = d; + in + { + output = b; + }; + + } + selections: + - anchor: { line: 1, character: 7 } + active: { line: 1, character: 7 } + marks: {} +finalState: + documentContents: | + { + foo = ; + + } + selections: + - anchor: { line: 1, character: 8 } + active: { line: 1, character: 8 } diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeValue2.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeValue2.yml new file mode 100644 index 0000000000..f124b2cfd1 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeValue2.yml @@ -0,0 +1,43 @@ +languageId: nix +command: + version: 6 + spokenForm: change value + action: + name: clearAndSetSelection + target: + type: primitive + modifiers: + - type: containingScope + scopeType: { type: value } + usePrePhraseSnapshot: true +initialState: + documentContents: | + { + foo = let + a = b; + c = d; + in + { + output = b; + }; + + } + selections: + - anchor: { line: 2, character: 4 } + active: { line: 2, character: 4 } + marks: {} +finalState: + documentContents: | + { + foo = let + a = ; + c = d; + in + { + output = b; + }; + + } + selections: + - anchor: { line: 2, character: 8 } + active: { line: 2, character: 8 } diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeValue3.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeValue3.yml new file mode 100644 index 0000000000..459baf7855 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeValue3.yml @@ -0,0 +1,37 @@ +languageId: nix +command: + version: 6 + spokenForm: change value + action: + name: clearAndSetSelection + target: + type: primitive + modifiers: + - type: containingScope + scopeType: { type: value } + usePrePhraseSnapshot: true +initialState: + documentContents: | + { + foo = let + a = b; + c = d; + in + { + output = b; + }; + + } + selections: + - anchor: { line: 5, character: 5 } + active: { line: 5, character: 5 } + marks: {} +finalState: + documentContents: | + { + foo = ; + + } + selections: + - anchor: { line: 1, character: 8 } + active: { line: 1, character: 8 } diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeValue4.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeValue4.yml new file mode 100644 index 0000000000..3b32ab9205 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/changeValue4.yml @@ -0,0 +1,43 @@ +languageId: nix +command: + version: 6 + spokenForm: change value + action: + name: clearAndSetSelection + target: + type: primitive + modifiers: + - type: containingScope + scopeType: { type: value } + usePrePhraseSnapshot: true +initialState: + documentContents: | + { + foo = let + a = b; + c = d; + in + { + output = b; + }; + + } + selections: + - anchor: { line: 6, character: 13 } + active: { line: 6, character: 13 } + marks: {} +finalState: + documentContents: | + { + foo = let + a = b; + c = d; + in + { + output = ; + }; + + } + selections: + - anchor: { line: 6, character: 15 } + active: { line: 6, character: 15 } diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/chuckArg.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/chuckArg.yml new file mode 100644 index 0000000000..f2ec633b6d --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/chuckArg.yml @@ -0,0 +1,29 @@ +languageId: nix +command: + version: 6 + spokenForm: chuck arg + action: + name: remove + target: + type: primitive + modifiers: + - type: containingScope + scopeType: { type: argumentOrParameter } + usePrePhraseSnapshot: true +initialState: + documentContents: | + { + d = "Interpolated ${value1} string ${value2}"; + } + selections: + - anchor: { line: 1, character: 26 } + active: { line: 1, character: 26 } + marks: {} +finalState: + documentContents: | + { + d = "Interpolated string ${value2}"; + } + selections: + - anchor: { line: 1, character: 20 } + active: { line: 1, character: 20 } diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/chuckInsideMap.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/chuckInsideMap.yml new file mode 100644 index 0000000000..64a10e11f7 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/chuckInsideMap.yml @@ -0,0 +1,32 @@ +languageId: nix +command: + version: 6 + spokenForm: chuck inside map + action: + name: remove + target: + type: primitive + modifiers: + - { type: interiorOnly } + - type: containingScope + scopeType: { type: map } + usePrePhraseSnapshot: true +initialState: + documentContents: | + { + foo = if a + then b + else c; + } + selections: + - anchor: { line: 3, character: 9 } + active: { line: 3, character: 9 } + marks: {} +finalState: + documentContents: | + { + + } + selections: + - anchor: { line: 1, character: 2 } + active: { line: 1, character: 2 } diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/chuckKey.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/chuckKey.yml new file mode 100644 index 0000000000..14aeb31640 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/chuckKey.yml @@ -0,0 +1,29 @@ +languageId: nix +command: + version: 6 + spokenForm: chuck key + action: + name: remove + target: + type: primitive + modifiers: + - type: containingScope + scopeType: { type: collectionKey } + usePrePhraseSnapshot: true +initialState: + documentContents: | + { + d = "Interpolated ${value1} string ${value2}"; + } + selections: + - anchor: { line: 1, character: 6 } + active: { line: 1, character: 6 } + marks: {} +finalState: + documentContents: | + { + "Interpolated ${value1} string ${value2}"; + } + selections: + - anchor: { line: 1, character: 2 } + active: { line: 1, character: 2 } diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/chuckValue.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/chuckValue.yml new file mode 100644 index 0000000000..8916e8198b --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/chuckValue.yml @@ -0,0 +1,37 @@ +languageId: nix +command: + version: 6 + spokenForm: chuck value + action: + name: remove + target: + type: primitive + modifiers: + - type: containingScope + scopeType: { type: value } + usePrePhraseSnapshot: true +initialState: + documentContents: | + { + foo = let + a = b; + c = d; + in + { + output = b; + }; + + } + selections: + - anchor: { line: 1, character: 7 } + active: { line: 1, character: 7 } + marks: {} +finalState: + documentContents: | + { + foo; + + } + selections: + - anchor: { line: 1, character: 5 } + active: { line: 1, character: 5 } diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/chuckValue2.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/chuckValue2.yml new file mode 100644 index 0000000000..6a07d078b4 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/nix/chuckValue2.yml @@ -0,0 +1,43 @@ +languageId: nix +command: + version: 6 + spokenForm: chuck value + action: + name: remove + target: + type: primitive + modifiers: + - type: containingScope + scopeType: { type: value } + usePrePhraseSnapshot: true +initialState: + documentContents: | + { + foo = let + a = b; + c = d; + in + { + output = b; + }; + + } + selections: + - anchor: { line: 2, character: 4 } + active: { line: 2, character: 4 } + marks: {} +finalState: + documentContents: | + { + foo = let + a; + c = d; + in + { + output = b; + }; + + } + selections: + - anchor: { line: 2, character: 4 } + active: { line: 2, character: 4 } diff --git a/queries/nix.scm b/queries/nix.scm new file mode 100644 index 0000000000..e7ce720616 --- /dev/null +++ b/queries/nix.scm @@ -0,0 +1,372 @@ +;; +;; Statements +;; + +(let_expression + (binding_set + (_) @statement @_.domain + ) + "in" @statement.iteration.end.startOf +) + +(source_code) @comment.iteration + +;; Any foo = anywhere is a statement +;; [ +;; (inherit) +;; (binding) +;; ] @statement +(binding_set) @map.iteration @list.iteration @ifStatement.iteration + +;; This matches assert statements as stand-alone statements. This +;; is because it's common to have a series of assert statements in a file, which +;; would otherwise all match as a single statement. See the playground/nix/asserts.nix +;; file for an example. +( + (assert_expression + "assert" @statement.start @statement.domain.start + condition: (_) + ";" @statement.end + body: (_) @statement.domain.end.startOf + ) @dummy + (#not-parent-type? @dummy binding) +) + +;; FIXME: Branch only makes sense probably for single line assert, but may not keep it. +;; also don't know how to match on single line only +(assert_expression + condition: (_) @condition + ;; body: (_) @branch +) @_.domain + +;; Match with when it's part of an expression like: +;; with lib; +;; let ... in ...; +( + (with_expression + "with" @statement.start + . + environment: (_) + ";" @statement.end + ) @dummy + (#not-parent-type? @dummy binding) +) + +;; FIXME: Need something like above for inherit, but only if it is on a single line. + +;;!! let +;;!! a = 1; +;;! <****** +;;!! b = 2; +;;! *****> +;;!! in a + b +(let_expression + "let" + . + (_) @statement.iteration @value.iteration @name.iteration +) + +;; +;; Conditionals +;; + +;;!! key = if a then b else c; +;;! ^^^^^^^^^^^^^^^^^^ +(if_expression) @ifStatement @branch.iteration @condition.iteration +;;!! key = if a then b else c; +;;! ^^^^^^^^^^^ +;;! xxxxxxxxxxxx +(if_expression + "if" @branch.start + condition: (_) + "then" + consequence: (_) @branch.end @branch.interior +) +;;!! key = if a then b else c; +;;! ^^^^^^ +;;! xxxxxxx +(if_expression + "else" @branch.start + alternative: (_) @branch.end @branch.interior +) + +;;!! key = if a > 10 then b else c; +;;! ^^^^^^ +(if_expression + condition: (_) @condition +) @_.domain + +;; +;; Lists and maps +;; + +;;!! foo = [ a b c ]; +;;! ^ +;;! xx +(list_expression + element: (_) @collectionItem +) @_.iteration @_.domain + +;;!! foo = [ a b c ]; +;;! ^^^^^^^^^ +(list_expression + "[" @list.interior.start.endOf + "]" @list.interior.end.startOf +) @list + +;;!! foo = { x = 1; y = 2; }; +;;! ^^^^^^^^^^^^^^^^^ +[ + (attrset_expression + (_) @map.interior + ) + (rec_attrset_expression + (_) @map.interior + ) +] @map @value.iteration @name.iteration + +;;!! foo = { x = 1; }; +;;! ^^^^^^ +(attrset_expression + (binding_set + binding: (_) @collectionItem + ) +) @_.iteration + +;;!! foo = rec { x = 1; }; +;;! ^^^^^^ +(rec_attrset_expression + (binding_set + binding: (_) @collectionItem + ) +) @_.iteration + +;;!! foo = { x = 1; y = 2; }; +;;! ^ +;;! xxxx +;;! ----- +(binding + attrpath: (_) @collectionKey @_.trailing.start.endOf + expression: (_) @_.trailing.end.startOf +) @_.domain + +;; +;; Strings +;; + +;; Comment +;;!! # foo +;;! ^^^^^ +;; Inside comment: +;;!! # foo +;;! ^^^ +(comment) @comment @textFragment + +;; FIXME: This works for inside comment on #, but breaks multi-line /* */ +;; Not sure how to match different interiors depending on contents. Almost +;; need a #regex predicate? Can't use shrink-to-match in [] without errors +;; [ +;; ( +;; (comment) @comment.interior +;; (#shrink-to-match! @comment.interior "# ?(?.*)$") +;; ) +;; ( +;; (comment) @comment.interior +;; ;; This would need to be a multi-line match, which I'm not sure shrink-to-match can do +;; ;; (#shrink-to-match! @comment.interior "/\*(?.*)\*/$") +;; ) +;; ] @comment + +[ + (string_expression) + (indented_string_expression) +] @string +(string_fragment) @textFragment + +;;!! d = "foo ${bar} baz" +;;! ^^^^^^ +;;! <**************> +(string_expression + (interpolation) @argumentOrParameter +) @_.iteration + +;; +;; Functions +;; + +;; Note for this part of the function, we identify is as lambda only +;;!! x = a: b: a + b; +;;! ^^^^^^^^ Func1 due to currying +;;! ^^^^^^^^^^^ Func2 due to currying +(function_expression + . + [ + ( + ;; Match foo@{ a, b }: + (identifier)? @argumentOrParameter.start + . + "@" + . + (formals) @argumentOrParameter.end + ) + ( + ;; Match{ a, b }@foo: + (formals) @argumentOrParameter.start + . + "@" + . + (identifier) @argumentOrParameter.end + ) + ;; Match { a, b }: + ( + (formals) @argumentOrParameter + . + ":" + ) + ;; Match a: + ( + (identifier) @argumentOrParameter + . + ":" + ) + ] + . + body: (_) @anonymousFunction.interior +) @anonymousFunction @argumentOrParameter.iteration + +;; We define the named function as the full assignment of the lambda +;; This means funk name becomes the variable holding the lambda +(binding + (_) @functionName + "=" + expression: (function_expression) @namedFunction.interior +) @namedFunction @functionName.domain + +;; This is gross, but not sure how to do fuzzy matching against an unknown number of +;; nested child nodes. Possiblyl should be a new predicate. Arbitrarily stopping at +;; 5 args for now, as that ought to be enough arguments for anyone +;; Args: +;;!! mkHost a b c d e +;;! ^ +;;! xx +;;! <*********> +;;! Callee: +;;!! mkHost a b c d e +;;! ^^^^^^ +;;! xxxxxxx +;;! ---------------- +(apply_expression + [ + (apply_expression + function: (variable_expression + name: (identifier) @functionCallee + ) + ) + (apply_expression + [ + (apply_expression + function: (variable_expression + name: (identifier) @functionCallee + ) + ) + (apply_expression + [ + (apply_expression + function: (variable_expression + name: (identifier) @functionCallee + ) + ) + (apply_expression + (apply_expression + function: (variable_expression + name: (identifier) @functionCallee + ) + ) + ) + ] + ) + ] + ) + ] +) @functionCall @_.domain + +;; Similar to above, but sometimes the function calls are in select_expression +(apply_expression + [ + (select_expression + expression: (variable_expression + name: (identifier) + ) + ) @functionCallee + (apply_expression + [ + (select_expression + expression: (variable_expression + name: (identifier) + ) + ) @functionCallee + (apply_expression + [ + (select_expression + expression: (variable_expression + name: (identifier) + ) + ) @functionCallee + (apply_expression + (select_expression + expression: (variable_expression + name: (identifier) + ) + ) @functionCallee + ) + ] + ) + ] + ) + ] +) @functionCall @_.domain + +;; Args: +;;!! mkHost a +;;! ^ +;;! x +;;! -------- +;;! Callee: +;;!! mkHost a +;;! ^^^^^^ +;;! xxxxxx +;;! -------- +(apply_expression + function: (variable_expression + name: (identifier) @functionCallee + ) + argument: (_) @argumentOrParameter +) @functionCall @_.domain + +(apply_expression + argument: (_) @argumentOrParameter +) + +;; +;; Names and Values +;; + +;;!! a = 25; +;;! ^^ +;;! xxxxx +;;! ------- +(binding + (_) @_.leading.start.endOf + . + expression: (_) @value @_.leading.end.startOf +) @_.domain + +;;!! a = 25; +;;! ^ +;;! xxxx +;;! ------- +(binding + (_) @name @_.leading.end.startOf @_.trailing.start.endOf + . + expression: (_) @_.trailing.end.startOf +) @_.domain