diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2a1950df..ef47a277 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -103,6 +103,14 @@ jobs: command: clippy args: --all-targets -- -D warnings + - name: Run cargo doc + uses: actions-rs/cargo@v1 + with: + command: doc + args: --no-deps --workspace --document-private-items + env: + RUSTDOCFLAGS: -D warnings + docs: name: Docs runs-on: ubuntu-latest diff --git a/.github/workflows/cachix.yml b/.github/workflows/cachix.yml index 113f7fa1..2d37b36a 100644 --- a/.github/workflows/cachix.yml +++ b/.github/workflows/cachix.yml @@ -23,4 +23,4 @@ jobs: authToken: ${{ secrets.CACHIX_AUTH_TOKEN }} - name: Build nix flake - run: nix build + run: nix build -L diff --git a/flake.lock b/flake.lock index 4f0841a7..f28ec884 100644 --- a/flake.lock +++ b/flake.lock @@ -3,11 +3,11 @@ "crane": { "flake": false, "locked": { - "lastModified": 1654444508, - "narHash": "sha256-4OBvQ4V7jyt7afs6iKUvRzJ1u/9eYnKzVQbeQdiamuY=", + "lastModified": 1661875961, + "narHash": "sha256-f1h/2c6Teeu1ofAHWzrS8TwBPcnN+EEu+z1sRVmMQTk=", "owner": "ipetkov", "repo": "crane", - "rev": "db5482bf225acc3160899124a1df5a617cfa27b5", + "rev": "d9f394e4e20e97c2a60c3ad82c2b6ef99be19e24", "type": "github" }, "original": { @@ -19,11 +19,11 @@ "devshell": { "flake": false, "locked": { - "lastModified": 1655976588, - "narHash": "sha256-VreHyH6ITkf/1EX/8h15UqhddJnUleb0HgbC3gMkAEQ=", + "lastModified": 1660811669, + "narHash": "sha256-V6lmsaLNFz41myppL0yxglta92ijkSvpZ+XVygAh+bU=", "owner": "numtide", "repo": "devshell", - "rev": "899ca4629020592a13a46783587f6e674179d1db", + "rev": "c2feacb46ee69949124c835419861143c4016fb5", "type": "github" }, "original": { @@ -35,49 +35,45 @@ "dream2nix": { "inputs": { "alejandra": [ - "nixCargoIntegration", + "nci", "nixpkgs" ], "crane": "crane", "devshell": [ - "nixCargoIntegration", + "nci", "devshell" ], "flake-utils-pre-commit": [ - "nixCargoIntegration", + "nci", "nixpkgs" ], "gomod2nix": [ - "nixCargoIntegration", + "nci", "nixpkgs" ], "mach-nix": [ - "nixCargoIntegration", + "nci", "nixpkgs" ], "nixpkgs": [ - "nixCargoIntegration", - "nixpkgs" - ], - "node2nix": [ - "nixCargoIntegration", + "nci", "nixpkgs" ], "poetry2nix": [ - "nixCargoIntegration", + "nci", "nixpkgs" ], "pre-commit-hooks": [ - "nixCargoIntegration", + "nci", "nixpkgs" ] }, "locked": { - "lastModified": 1655975833, - "narHash": "sha256-g8sdfuglIZ24oWVbntVzniNTJW+Z3n9DNL9w9Tt+UCE=", + "lastModified": 1662176993, + "narHash": "sha256-Sy7DsGAveDUFBb6YDsUSYZd/AcXfP/MOMIwMt/NgY84=", "owner": "nix-community", "repo": "dream2nix", - "rev": "4e75e665ec3a1cddae5266bed0dd72fce0b74a23", + "rev": "809bc5940214744eb29778a9a0b03f161979c1b2", "type": "github" }, "original": { @@ -88,11 +84,11 @@ }, "flake-utils": { "locked": { - "lastModified": 1637014545, - "narHash": "sha256-26IZAc5yzlD9FlDT54io1oqG/bBoyka+FJk5guaX4x4=", + "lastModified": 1656928814, + "narHash": "sha256-RIFfgBuKz6Hp89yRr7+NR5tzIAbn52h8vT6vXkYjZoM=", "owner": "numtide", "repo": "flake-utils", - "rev": "bba5dcc8e0b20ab664967ad83d24d64cb64ec4f4", + "rev": "7e2a3b3dfd9af950a856d66b0a7d01e3c18aa249", "type": "github" }, "original": { @@ -101,7 +97,7 @@ "type": "github" } }, - "nixCargoIntegration": { + "nci": { "inputs": { "devshell": "devshell", "dream2nix": "dream2nix", @@ -113,11 +109,11 @@ ] }, "locked": { - "lastModified": 1656453541, - "narHash": "sha256-ZCPVnS6zJOZJvIlwU3rKR8MBVm6A3F4/0mA7G1lQ3D0=", + "lastModified": 1662177071, + "narHash": "sha256-x6XF//RdZlw81tFAYM1TkjY+iQIpyMCWZ46r9o4wVQY=", "owner": "yusdacra", "repo": "nix-cargo-integration", - "rev": "9eb74345b30cd2e536d9dac9d4435d3c475605c7", + "rev": "65270dea87bb82fc02102a15221677eea237680e", "type": "github" }, "original": { @@ -128,11 +124,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1655624069, - "narHash": "sha256-7g1zwTdp35GMTERnSzZMWJ7PG3QdDE8VOX3WsnOkAtM=", + "lastModified": 1662019588, + "narHash": "sha256-oPEjHKGGVbBXqwwL+UjsveJzghWiWV0n9ogo1X6l4cw=", "owner": "nixos", "repo": "nixpkgs", - "rev": "0d68d7c857fe301d49cdcd56130e0beea4ecd5aa", + "rev": "2da64a81275b68fdad38af669afeda43d401e94b", "type": "github" }, "original": { @@ -144,7 +140,7 @@ }, "root": { "inputs": { - "nixCargoIntegration": "nixCargoIntegration", + "nci": "nci", "nixpkgs": "nixpkgs", "rust-overlay": "rust-overlay" } @@ -157,11 +153,11 @@ ] }, "locked": { - "lastModified": 1655779671, - "narHash": "sha256-6feeiGa6fb7ZPVHR71uswkmN1701TAJpwYQA8QffmRk=", + "lastModified": 1662087605, + "narHash": "sha256-Gpf2gp2JenKGf+TylX/YJpttY2bzsnvAMLdLaxoZRyU=", "owner": "oxalica", "repo": "rust-overlay", - "rev": "8159585609a772b041cce6019d5c21d240709244", + "rev": "60c2cfaa8b90ed8cebd18b214fac8682dcf222dd", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index 7b6f0685..abcb2cb2 100644 --- a/flake.nix +++ b/flake.nix @@ -7,128 +7,169 @@ url = "github:oxalica/rust-overlay"; inputs.nixpkgs.follows = "nixpkgs"; }; - nixCargoIntegration = { + nci = { url = "github:yusdacra/nix-cargo-integration"; inputs.nixpkgs.follows = "nixpkgs"; inputs.rust-overlay.follows = "rust-overlay"; }; }; - outputs = inputs @ { + outputs = { + self, nixpkgs, - nixCargoIntegration, + nci, ... }: let - outputs = config: - nixCargoIntegration.lib.makeOutputs { - root = ./.; - renameOutputs = {"helix-term" = "helix";}; - # Set default app to hx (binary is from helix-term release build) - # Set default package to helix-term release build - defaultOutputs = { - app = "hx"; - package = "helix"; - }; - overrides = { - cCompiler = common: - with common.pkgs; - if stdenv.isLinux - then gcc - else clang; - crateOverrides = common: _: { - helix-term = prev: let - inherit (common) pkgs; - mkRootPath = rel: - builtins.path { - path = "${common.root}/${rel}"; - name = rel; - }; - grammars = pkgs.callPackage ./grammars.nix config; - runtimeDir = pkgs.runCommandNoCC "helix-runtime" {} '' - mkdir -p $out - ln -s ${mkRootPath "runtime"}/* $out - rm -r $out/grammars - ln -s ${grammars} $out/grammars - ''; - overridedAttrs = { - # disable fetching and building of tree-sitter grammars in the helix-term build.rs - HELIX_DISABLE_AUTO_GRAMMAR_BUILD = "1"; - # link languages and theme toml files since helix-term expects them (for tests) - preConfigure = - pkgs.lib.concatMapStringsSep - "\n" - (path: "ln -sf ${mkRootPath path} ..") - ["languages.toml" "theme.toml" "base16_theme.toml"]; - buildInputs = (prev.buildInputs or []) ++ [common.cCompiler.cc.lib]; - nativeBuildInputs = [pkgs.makeWrapper]; + lib = nixpkgs.lib; + mkRootPath = rel: + builtins.path { + path = "${toString ./.}/${rel}"; + name = rel; + }; + outputs = nci.lib.makeOutputs { + root = ./.; + renameOutputs = {"helix-term" = "helix";}; + # Set default app to hx (binary is from helix-term release build) + # Set default package to helix-term release build + defaultOutputs = { + app = "hx"; + package = "helix"; + }; + overrides = { + cCompiler = common: + with common.pkgs; + if stdenv.isLinux + then gcc + else clang; + crateOverrides = common: _: { + helix-term = prev: { + src = builtins.path { + name = "helix-source"; + path = toString ./.; + # filter out unneeded stuff that cause rebuilds + filter = path: type: + lib.all + (n: builtins.baseNameOf path != n) + [ + ".envrc" + ".ignore" + ".github" + "runtime" + "screenshot.png" + "book" + "contrib" + "docs" + "README.md" + "shell.nix" + "default.nix" + "grammars.nix" + "flake.nix" + "flake.lock" + ]; + }; - postFixup = '' - if [ -f "$out/bin/hx" ]; then - wrapProgram "$out/bin/hx" ''${makeWrapperArgs[@]} --set HELIX_RUNTIME "${runtimeDir}" - fi - ''; - }; - in - overridedAttrs - // ( - pkgs.lib.optionalAttrs - (config ? makeWrapperArgs) - {inherit (config) makeWrapperArgs;} - ); - }; - shell = common: prev: { - packages = - prev.packages - ++ ( - with common.pkgs; - [lld_13 lldb cargo-flamegraph rust-analyzer] ++ - (lib.optional (stdenv.isx86_64 && stdenv.isLinux) cargo-tarpaulin) - ); - env = - prev.env - ++ [ - { - name = "HELIX_RUNTIME"; - eval = "$PWD/runtime"; - } - { - name = "RUST_BACKTRACE"; - value = "1"; - } - { - name = "RUSTFLAGS"; - value = - if common.pkgs.stdenv.isLinux - then "-C link-arg=-fuse-ld=lld -C target-cpu=native -Clink-arg=-Wl,--no-rosegment" - else ""; - } - ]; + # disable fetching and building of tree-sitter grammars in the helix-term build.rs + HELIX_DISABLE_AUTO_GRAMMAR_BUILD = "1"; + + buildInputs = (prev.buildInputs or []) ++ [common.cCompiler.cc.lib]; + + # link languages and theme toml files since helix-term expects them (for tests) + preConfigure = '' + ${prev.preConfigure or ""} + ${ + lib.concatMapStringsSep + "\n" + (path: "ln -sf ${mkRootPath path} ..") + ["languages.toml" "theme.toml" "base16_theme.toml"] + } + ''; + + meta.mainProgram = "hx"; }; }; + shell = common: prev: { + packages = + prev.packages + ++ ( + with common.pkgs; + [lld_13 lldb cargo-flamegraph rust-analyzer] + ++ (lib.optional (stdenv.isx86_64 && stdenv.isLinux) cargo-tarpaulin) + ); + env = + prev.env + ++ [ + { + name = "HELIX_RUNTIME"; + eval = "$PWD/runtime"; + } + { + name = "RUST_BACKTRACE"; + value = "1"; + } + { + name = "RUSTFLAGS"; + value = + if common.pkgs.stdenv.isLinux + then "-C link-arg=-fuse-ld=lld -C target-cpu=native -Clink-arg=-Wl,--no-rosegment" + else ""; + } + ]; + }; }; - defaultOutputs = outputs {}; - makeOverridableHelix = system: old: - old - // { - override = args: - makeOverridableHelix - system - (outputs args).packages.${system}.helix; - }; + }; + makeOverridableHelix = system: old: config: let + pkgs = nixpkgs.legacyPackages.${system}; + grammars = pkgs.callPackage ./grammars.nix config; + runtimeDir = pkgs.runCommand "helix-runtime" {} '' + mkdir -p $out + ln -s ${mkRootPath "runtime"}/* $out + rm -r $out/grammars + ln -s ${grammars} $out/grammars + ''; + helix-wrapped = + pkgs.runCommand "${old.name}-wrapped" + { + inherit (old) pname version meta; + + nativeBuildInputs = [pkgs.makeWrapper]; + makeWrapperArgs = config.makeWrapperArgs or []; + } + '' + mkdir -p $out + cp -r --no-preserve=mode,ownership ${old}/* $out/ + chmod +x $out/bin/* + wrapProgram "$out/bin/hx" ''${makeWrapperArgs[@]} --set HELIX_RUNTIME "${runtimeDir}" + ''; + in + helix-wrapped + // {override = makeOverridableHelix system old;}; in - defaultOutputs + outputs // { + apps = + lib.mapAttrs + ( + system: apps: rec { + default = hx; + hx = { + type = "app"; + program = lib.getExe self.${system}.packages.helix; + }; + } + ) + outputs.apps; packages = - nixpkgs.lib.mapAttrs + lib.mapAttrs ( - system: packages: - packages - // rec { - default = helix; - helix = makeOverridableHelix system packages.helix; - } + system: packages: rec { + default = helix; + helix = makeOverridableHelix system helix-unwrapped {}; + helix-debug = makeOverridableHelix system helix-unwrapped-debug {}; + helix-unwrapped = packages.helix; + helix-unwrapped-debug = packages.helix-debug; + } ) - defaultOutputs.packages; + outputs.packages; }; nixConfig = { diff --git a/helix-core/src/indent.rs b/helix-core/src/indent.rs index 137b8822..ad079c25 100644 --- a/helix-core/src/indent.rs +++ b/helix-core/src/indent.rs @@ -230,14 +230,14 @@ fn get_first_in_line(mut node: Node, byte_pos: usize, new_line: bool) -> Vec 0 && added.outdent == 0 { @@ -433,7 +433,7 @@ fn query_indents( /// after pos were moved to a new line. /// /// The indentation is determined by traversing all the tree-sitter nodes containing the position. -/// Each of these nodes produces some [AddedIndent] for: +/// Each of these nodes produces some [Indentation] for: /// /// - The line of the (beginning of the) node. This is defined by the scope `all` if this is the first node on its line. /// - The line after the node. This is defined by: @@ -441,9 +441,9 @@ fn query_indents( /// - The scope `all` if this node is not the first node on its line. /// Intuitively, `all` applies to everything contained in this node while `tail` applies to everything except for the first line of the node. /// The indents from different nodes for the same line are then combined. -/// The [IndentResult] is simply the sum of the [AddedIndent] for all lines. +/// The result [Indentation] is simply the sum of the [Indentation] for all lines. /// -/// Specifying which line exactly an [AddedIndent] applies to is important because indents on the same line combine differently than indents on different lines: +/// Specifying which line exactly an [Indentation] applies to is important because indents on the same line combine differently than indents on different lines: /// ```ignore /// some_function(|| { /// // Both the function parameters as well as the contained block should be indented. diff --git a/helix-lsp/src/lib.rs b/helix-lsp/src/lib.rs index f3a4f755..9365c8b3 100644 --- a/helix-lsp/src/lib.rs +++ b/helix-lsp/src/lib.rs @@ -12,7 +12,7 @@ use futures_util::stream::select_all::SelectAll; use helix_core::syntax::LanguageConfiguration; use std::{ - collections::HashMap, + collections::{hash_map::Entry, HashMap}, sync::{ atomic::{AtomicUsize, Ordering}, Arc, @@ -326,14 +326,52 @@ impl Registry { None => return Err(Error::LspNotDefined), }; - if let Some((_, client)) = self.inner.get(&language_config.scope) { - Ok(client.clone()) - } else { - let id = self.counter.fetch_add(1, Ordering::Relaxed); - let client = self.initialize_client(language_config, config, id)?; // initialize a new client - self.inner - .insert(language_config.scope.clone(), (id, client.clone())); - Ok(client) + match self.inner.entry(language_config.scope.clone()) { + Entry::Occupied(entry) => Ok(entry.get().1.clone()), + Entry::Vacant(entry) => { + // initialize a new client + let id = self.counter.fetch_add(1, Ordering::Relaxed); + let (client, incoming, initialize_notify) = Client::start( + &config.command, + &config.args, + language_config.config.clone(), + &language_config.roots, + id, + config.timeout, + )?; + self.incoming.push(UnboundedReceiverStream::new(incoming)); + let client = Arc::new(client); + + // Initialize the client asynchronously + let _client = client.clone(); + tokio::spawn(async move { + use futures_util::TryFutureExt; + let value = _client + .capabilities + .get_or_try_init(|| { + _client + .initialize() + .map_ok(|response| response.capabilities) + }) + .await; + + if let Err(e) = value { + log::error!("failed to initialize language server: {}", e); + return; + } + + // next up, notify + _client + .notify::(lsp::InitializedParams {}) + .await + .unwrap(); + + initialize_notify.notify_one(); + }); + + entry.insert((id, client.clone())); + Ok(client) + } } } pub fn restart(&mut self, language_config: &LanguageConfiguration) -> Result> { diff --git a/helix-term/src/application.rs b/helix-term/src/application.rs index 9e79e7c9..9653b373 100644 --- a/helix-term/src/application.rs +++ b/helix-term/src/application.rs @@ -195,7 +195,7 @@ impl Application { // `--vsplit` or `--hsplit` are used, the file which is // opened last is focused on. let view_id = editor.tree.focus; - let doc = editor.document_mut(doc_id).unwrap(); + let doc = doc_mut!(editor, &doc_id); let pos = Selection::point(pos_at_coords(doc.text().slice(..), pos, true)); doc.set_selection(view_id, pos); } @@ -505,8 +505,13 @@ impl Application { let language_id = doc.language_id().map(ToOwned::to_owned).unwrap_or_default(); + let url = match doc.url() { + Some(url) => url, + None => continue, // skip documents with no path + }; + tokio::spawn(language_server.text_document_did_open( - doc.url().unwrap(), + url, doc.version(), doc.text(), language_id, diff --git a/helix-term/src/ui/editor.rs b/helix-term/src/ui/editor.rs index c3efa5cf..2e58824e 100644 --- a/helix-term/src/ui/editor.rs +++ b/helix-term/src/ui/editor.rs @@ -1063,7 +1063,7 @@ impl EditorView { let editor = &mut cxt.editor; if let Some((pos, view_id)) = pos_and_view(editor, row, column) { - let doc = editor.document_mut(editor.tree.get(view_id).doc).unwrap(); + let doc = doc_mut!(editor, &view!(editor, view_id).doc); if modifiers == KeyModifiers::ALT { let selection = doc.selection(view_id).clone(); @@ -1192,7 +1192,7 @@ impl EditorView { } if let Some((pos, view_id)) = pos_and_view(editor, row, column) { - let doc = editor.document_mut(editor.tree.get(view_id).doc).unwrap(); + let doc = doc_mut!(editor, &view!(editor, view_id).doc); doc.set_selection(view_id, Selection::point(pos)); cxt.editor.focus(view_id); commands::MappableCommand::paste_primary_clipboard_before.execute(cxt); @@ -1327,8 +1327,8 @@ impl Component for EditorView { if cx.editor.tree.contains(focus) { let config = cx.editor.config(); let mode = cx.editor.mode(); - let view = cx.editor.tree.get_mut(focus); - let doc = cx.editor.documents.get_mut(&view.doc).unwrap(); + let view = view_mut!(cx.editor, focus); + let doc = doc_mut!(cx.editor, &view.doc); view.ensure_cursor_in_view(doc, config.scrolloff); diff --git a/helix-term/src/ui/prompt.rs b/helix-term/src/ui/prompt.rs index 24fc8233..d66e32be 100644 --- a/helix-term/src/ui/prompt.rs +++ b/helix-term/src/ui/prompt.rs @@ -101,7 +101,7 @@ impl Prompt { } /// Compute the cursor position after applying movement - /// Taken from: https://github.com/wez/wezterm/blob/e0b62d07ca9bf8ce69a61e30a3c20e7abc48ce7e/termwiz/src/lineedit/mod.rs#L516-L611 + /// Taken from: fn eval_movement(&self, movement: Movement) -> usize { match movement { Movement::BackwardChar(rep) => { diff --git a/helix-view/src/document.rs b/helix-view/src/document.rs index 3c406f8b..3f8dc4e6 100644 --- a/helix-view/src/document.rs +++ b/helix-view/src/document.rs @@ -407,7 +407,11 @@ impl Document { // We can't use anyhow::Result here since the output of the future has to be // clonable to be used as shared future. So use a custom error type. pub fn format(&self) -> Option>> { - if let Some(formatter) = self.language_config().and_then(|c| c.formatter.clone()) { + if let Some(formatter) = self + .language_config() + .and_then(|c| c.formatter.clone()) + .filter(|formatter| which::which(&formatter.command).is_ok()) + { use std::process::Stdio; let text = self.text().clone(); let mut process = tokio::process::Command::new(&formatter.command); diff --git a/helix-view/src/editor.rs b/helix-view/src/editor.rs index 567c7113..6bb8276d 100644 --- a/helix-view/src/editor.rs +++ b/helix-view/src/editor.rs @@ -973,7 +973,7 @@ impl Editor { view.doc = doc_id; view.offset = Position::default(); - let doc = self.documents.get_mut(&doc_id).unwrap(); + let doc = doc_mut!(self, &doc_id); doc.ensure_view_init(view.id); // TODO: reuse align_view @@ -1044,7 +1044,7 @@ impl Editor { } Action::Load => { let view_id = view!(self).id; - let doc = self.documents.get_mut(&id).unwrap(); + let doc = doc_mut!(self, &id); doc.ensure_view_init(view_id); return; } @@ -1065,7 +1065,7 @@ impl Editor { }, ); // initialize selection for view - let doc = self.documents.get_mut(&id).unwrap(); + let doc = doc_mut!(self, &id); doc.ensure_view_init(view_id); } } @@ -1119,9 +1119,9 @@ impl Editor { } pub fn close(&mut self, id: ViewId) { - let view = self.tree.get(self.tree.focus); + let (_view, doc) = current!(self); // remove selection - self.documents.get_mut(&view.doc).unwrap().remove_view(id); + doc.remove_view(id); self.tree.remove(id); self._refresh(); } @@ -1195,7 +1195,7 @@ impl Editor { .unwrap_or_else(|| self.new_document(Document::default())); let view = View::new(doc_id, self.config().gutters.clone()); let view_id = self.tree.insert(view); - let doc = self.documents.get_mut(&doc_id).unwrap(); + let doc = doc_mut!(self, &doc_id); doc.ensure_view_init(view_id); } diff --git a/helix-view/src/macros.rs b/helix-view/src/macros.rs index 04f8df94..53ab4346 100644 --- a/helix-view/src/macros.rs +++ b/helix-view/src/macros.rs @@ -14,7 +14,7 @@ macro_rules! current { ($editor:expr) => {{ let view = $crate::view_mut!($editor); let id = view.doc; - let doc = $editor.documents.get_mut(&id).unwrap(); + let doc = $crate::doc_mut!($editor, &id); (view, doc) }}; } @@ -32,6 +32,9 @@ macro_rules! current_ref { /// Returns `&mut Document` #[macro_export] macro_rules! doc_mut { + ($editor:expr, $id:expr) => {{ + $editor.documents.get_mut($id).unwrap() + }}; ($editor:expr) => {{ $crate::current!($editor).1 }}; @@ -41,6 +44,9 @@ macro_rules! doc_mut { /// Returns `&mut View` #[macro_export] macro_rules! view_mut { + ($editor:expr, $id:expr) => {{ + $editor.tree.get_mut($id) + }}; ($editor:expr) => {{ $editor.tree.get_mut($editor.tree.focus) }}; @@ -50,6 +56,9 @@ macro_rules! view_mut { /// Returns `&View` #[macro_export] macro_rules! view { + ($editor:expr, $id:expr) => {{ + $editor.tree.get($id) + }}; ($editor:expr) => {{ $editor.tree.get($editor.tree.focus) }}; @@ -57,6 +66,9 @@ macro_rules! view { #[macro_export] macro_rules! doc { + ($editor:expr, $id:expr) => {{ + $editor.documents[$id] + }}; ($editor:expr) => {{ $crate::current_ref!($editor).1 }}; diff --git a/helix-view/src/tree.rs b/helix-view/src/tree.rs index 72f6af57..a1977764 100644 --- a/helix-view/src/tree.rs +++ b/helix-view/src/tree.rs @@ -270,18 +270,18 @@ impl Tree { }) } - /// Get reference to a [`view`] by index. + /// Get reference to a [View] by index. /// # Panics /// - /// Panics if `index` is not in self.nodes, or if the node's content is not [`Content::View`] . This can be checked with [`contains`] + /// Panics if `index` is not in self.nodes, or if the node's content is not [Content::View]. This can be checked with [Self::contains]. pub fn get(&self, index: ViewId) -> &View { self.try_get(index).unwrap() } - /// Try to get reference to a [`view`] by index. Returns `None` if node content is not a [`Content::View`] + /// Try to get reference to a [View] by index. Returns `None` if node content is not a [Content::View] /// # Panics /// - /// Panics if `index` is not in self.nodes. This can be checked with [`Self::contains`] + /// Panics if `index` is not in self.nodes. This can be checked with [Self::contains] pub fn try_get(&self, index: ViewId) -> Option<&View> { match &self.nodes[index] { Node { @@ -292,10 +292,10 @@ impl Tree { } } - /// Get a mutable reference to a [`view`] by index. + /// Get a mutable reference to a [View] by index. /// # Panics /// - /// Panics if `index` is not in self.nodes, or if the node's content is not [`Content::View`] . This can be checked with [`Self::contains`] + /// Panics if `index` is not in self.nodes, or if the node's content is not [Content::View]. This can be checked with [Self::contains]. pub fn get_mut(&mut self, index: ViewId) -> &mut View { match &mut self.nodes[index] { Node { @@ -306,7 +306,7 @@ impl Tree { } } - /// Check if tree contains a [`Node`] with a given index. + /// Check if tree contains a [Node] with a given index. pub fn contains(&self, index: ViewId) -> bool { self.nodes.contains_key(index) } diff --git a/languages.toml b/languages.toml index 05608b81..06921534 100644 --- a/languages.toml +++ b/languages.toml @@ -735,10 +735,9 @@ language-server = { command = "zls" } indent = { tab-width = 4, unit = " " } formatter = { command = "zig" , args = ["fmt", "--stdin"] } - [[grammar]] name = "zig" -source = { git = "https://github.com/maxxnino/tree-sitter-zig", rev = "93331b8bd8b4ebee2b575490b2758f16ad4e9f30" } +source = { git = "https://github.com/maxxnino/tree-sitter-zig", rev = "8d3224c3bd0890fe08358886ebf54fca2ed448a6" } [[language]] name = "prolog" diff --git a/runtime/queries/rust/injections.scm b/runtime/queries/rust/injections.scm index 77c70805..704d8494 100644 --- a/runtime/queries/rust/injections.scm +++ b/runtime/queries/rust/injections.scm @@ -24,3 +24,30 @@ name: (identifier) @_new (#eq? @_new "new")) arguments: (arguments (raw_string_literal) @injection.content) (#set! injection.language "regex")) + +; Highlight SQL in `sqlx::query!()` +(macro_invocation + macro: (scoped_identifier + path: (identifier) @_sqlx (#eq? @_sqlx "sqlx") + name: (identifier) @_query (#eq? @_query "query")) + (token_tree + ; Only the first argument is SQL + . + [(string_literal) (raw_string_literal)] @injection.content + ) + (#set! injection.language "sql")) + +; Highlight SQL in `sqlx::query_as!()` +(macro_invocation + macro: (scoped_identifier + path: (identifier) @_sqlx (#eq? @_sqlx "sqlx") + name: (identifier) @_query_as (#eq? @_query_as "query_as")) + (token_tree + ; Only the second argument is SQL + . + ; Allow anything as the first argument in case the user has lower case type + ; names for some reason + (_) + [(string_literal) (raw_string_literal)] @injection.content + ) + (#set! injection.language "sql")) diff --git a/runtime/queries/zig/highlights.scm b/runtime/queries/zig/highlights.scm index 62c99acc..e2e79518 100644 --- a/runtime/queries/zig/highlights.scm +++ b/runtime/queries/zig/highlights.scm @@ -1,20 +1,11 @@ [ (container_doc_comment) (doc_comment) - (line_comment) -] @comment +] @comment.documentation [ - variable: (IDENTIFIER) - variable_type_function: (IDENTIFIER) -] @variable - -parameter: (IDENTIFIER) @variable.parameter - -[ - field_member: (IDENTIFIER) - field_access: (IDENTIFIER) -] @variable.other.member + (line_comment) +] @comment.line ;; assume TitleCase is a type ( @@ -25,6 +16,7 @@ parameter: (IDENTIFIER) @variable.parameter ] @type (#match? @type "^[A-Z]([a-z]+[A-Za-z0-9]*)*$") ) + ;; assume camelCase is a function ( [ @@ -44,29 +36,33 @@ parameter: (IDENTIFIER) @variable.parameter (#match? @constant "^[A-Z][A-Z_0-9]+$") ) -[ - function_call: (IDENTIFIER) - function: (IDENTIFIER) -] @function - -exception: "!" @function.macro - +;; _ ( (IDENTIFIER) @variable.builtin (#eq? @variable.builtin "_") ) +;; C Pointers [*c]T (PtrTypeStart "c" @variable.builtin) -( - (ContainerDeclType - [ - (ErrorUnionExpr) - "enum" - ] - ) - (ContainerField (IDENTIFIER) @constant) -) +[ + variable: (IDENTIFIER) + variable_type_function: (IDENTIFIER) +] @variable + +parameter: (IDENTIFIER) @variable.parameter + +[ + field_member: (IDENTIFIER) + field_access: (IDENTIFIER) +] @variable.other.member + +[ + function_call: (IDENTIFIER) + function: (IDENTIFIER) +] @function + +exception: "!" @keyword.control.exception field_constant: (IDENTIFIER) @constant @@ -89,8 +85,6 @@ field_constant: (IDENTIFIER) @constant (FormatSequence) @string.special [ - "allowzero" - "volatile" "anytype" "anyframe" (BuildinTypeExpr) @@ -125,44 +119,53 @@ field_constant: (IDENTIFIER) @constant "or" "and" "orelse" -] @operator +] @keyword.operator [ "struct" "enum" "union" - "error" "packed" "opaque" -] @keyword + "export" + "extern" + "linksection" +] @keyword.storage.type + +[ + "const" + "var" + "threadlocal" + "allowzero" + "volatile" + "align" +] @keyword.storage.modifier [ "try" "error" "catch" -] @function.macro +] @keyword.control.exception -; VarDecl [ - "threadlocal" "fn" ] @keyword.function [ - "const" - "var" "test" +] @keyword + +[ "pub" "usingnamespace" -] @keyword +] @keyword.control.import [ "return" "break" "continue" -] @keyword.control +] @keyword.control.return -; Macro [ "defer" "errdefer" @@ -171,11 +174,8 @@ field_constant: (IDENTIFIER) @constant "await" "suspend" "resume" - "export" - "extern" ] @function.macro -; PrecProc [ "comptime" "inline" @@ -185,11 +185,6 @@ field_constant: (IDENTIFIER) @constant "noalias" ] @keyword.directive -[ - "linksection" - "align" -] @function.builtin - [ (CompareOp) (BitwiseOp) @@ -230,5 +225,4 @@ field_constant: (IDENTIFIER) @constant (PtrIndexPayload "|") ] @punctuation.bracket -; Error -(ERROR) @keyword +(ERROR) @keyword.control.exception diff --git a/runtime/themes/boo_berry.toml b/runtime/themes/boo_berry.toml index e413319a..2f6f5127 100644 --- a/runtime/themes/boo_berry.toml +++ b/runtime/themes/boo_berry.toml @@ -30,13 +30,16 @@ "ui.background" = { bg = "berry" } "ui.cursor" = { fg = "berry", bg = "lilac" } "ui.cursor.match" = { fg = "berry", bg = "berry_desaturated" } -"ui.cursor.select" = { fg = "berry", bg = "mint" } +"ui.cursor.select" = { fg = "berry", bg = "violet" } "ui.cursor.insert" = { fg = "berry", bg = "mint" } "ui.linenr" = { fg = "berry_desaturated" } "ui.linenr.selected" = { fg = "lilac" } "ui.cursorline" = { fg = "lilac", bg = "berry_dim" } "ui.statusline" = { fg = "lilac", bg = "berry_saturated" } "ui.statusline.inactive" = { fg = "berry_desaturated", bg = "berry_saturated" } +"ui.statusline.normal" = { fg = "berry_saturated", bg = "lilac" } +"ui.statusline.insert" = { fg = "berry_saturated", bg = "mint" } +"ui.statusline.select" = { fg = "berry_saturated", bg = "violet" } "ui.popup" = { fg = "lilac", bg = "berry_saturated" } "ui.window" = { fg = "berry_desaturated", bg = "berry" } "ui.help" = { fg = "lilac", bg = "berry_saturated" } @@ -46,7 +49,8 @@ "ui.menu.selected" = { fg = "mint", bg = "berry_saturated" } "ui.selection" = { bg = "berry_saturated" } "ui.virtual.whitespace" = { fg = "berry_desaturated" } -"ui.virtual.ruler" = { bg ="berry_dim" } +"ui.virtual.ruler" = { bg = "berry_dim" } +"ui.virtual.indent-guide" = { fg = "berry_fade" } "diff.plus" = { fg = "mint" } "diff.delta" = { fg = "gold" } @@ -66,6 +70,7 @@ [palette] berry = "#3A2A4D" +berry_fade = "#5A3D6E" berry_dim = "#47345E" berry_saturated = "#2B1C3D" berry_desaturated = "#886C9C" diff --git a/runtime/tutor.txt b/runtime/tutor.txt index fe7b15d2..4a6c4425 100644 --- a/runtime/tutor.txt +++ b/runtime/tutor.txt @@ -670,8 +670,8 @@ _________________________________________________________________ 3. Try using A-. with f and t, to select multiple sentences for instance. - This is some text for you to repeat things. You can repeat - insertions like changing words, or repeat selections like f/t. + --> This is some text for you to repeat things. You can repeat + insertions like changing words, or repeat selections like f/t. @@ -911,7 +911,7 @@ lines. 1. Move the cursor to the line below marked -->. 2. Select the first "bat" and type * to set it to search. 3. Type v to enter select mode. - 4. Type n to select the othe "bat". + 4. Type n to select the other "bat". 5. Use c or r to change the "bat"s to "cat". --> Everybody wants to be a bat,