aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitmodules4
-rw-r--r--README.md8
-rw-r--r--book/book.toml3
-rw-r--r--book/src/install.md9
-rw-r--r--book/src/keymap.md2
-rw-r--r--helix-core/src/movement.rs20
-rw-r--r--helix-core/src/search.rs4
-rw-r--r--helix-syntax/build.rs5
m---------helix-syntax/languages/tree-sitter-elixir0
-rw-r--r--helix-syntax/src/lib.rs1
-rw-r--r--helix-term/src/commands.rs11
-rw-r--r--helix-term/src/keymap.rs2
-rw-r--r--helix-term/src/main.rs34
-rw-r--r--languages.toml9
-rw-r--r--runtime/queries/elixir/highlights.scm146
-rw-r--r--shell.nix6
16 files changed, 227 insertions, 37 deletions
diff --git a/.gitmodules b/.gitmodules
index f4d6456c..a90766d4 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -82,3 +82,7 @@
path = helix-syntax/languages/tree-sitter-toml
url = https://github.com/ikatyang/tree-sitter-toml
shallow = true
+[submodule "helix-syntax/languages/tree-sitter-elixir"]
+ path = helix-syntax/languages/tree-sitter-elixir
+ url = https://github.com/IceDragon200/tree-sitter-elixir
+ shallow = true
diff --git a/README.md b/README.md
index 608bb1c0..d867b007 100644
--- a/README.md
+++ b/README.md
@@ -42,6 +42,14 @@ Now copy the `runtime/` directory somewhere. Helix will by default look for the
runtime inside the same folder as the executable, but that can be overriden via
the `HELIX_RUNTIME` environment variable.
+> NOTE: You should set this to <path to repository>/runtime in development (if
+> running via cargo).
+
+## Arch Linux
+There are two packages available from AUR:
+ - `helix-bin`: contains prebuilt binary from GitHub releases
+ - `helix-git`: builds the master branch of this repository
+
# Contributing
Contributors are very welcome! **No contribution is too small and all contributions are valued.**
diff --git a/book/book.toml b/book/book.toml
index f397aef0..e6d3eee3 100644
--- a/book/book.toml
+++ b/book/book.toml
@@ -4,3 +4,6 @@ language = "en"
multilingual = false
src = "src"
theme = "colibri"
+
+[output.html]
+cname = "docs.helix-editor.com"
diff --git a/book/src/install.md b/book/src/install.md
index ac9f1daa..4e3cfc3f 100644
--- a/book/src/install.md
+++ b/book/src/install.md
@@ -6,10 +6,7 @@ We provide pre-built binaries on the [GitHub Releases page](https://github.com/h
TODO: brew tap
-```
-$ brew tap helix-editor/helix
-$ brew install helix
-```
+Please use a pre-built binary release for the time being.
## Linux
@@ -21,7 +18,9 @@ shell for working on Helix.
### Arch Linux
-A binary package is available on AUR as [helix-bin](https://aur.archlinux.org/packages/helix-bin/).
+Binary packages are available on AUR:
+- [helix-bin](https://aur.archlinux.org/packages/helix-bin/) contains the pre-built release
+- [helix-git](https://aur.archlinux.org/packages/helix-git/) builds the master branch
## Build from source
diff --git a/book/src/keymap.md b/book/src/keymap.md
index 9c8c23d6..43e623a2 100644
--- a/book/src/keymap.md
+++ b/book/src/keymap.md
@@ -118,7 +118,7 @@ Jumps to various locations.
|-----|-----------|
| g | Go to the start of the file |
| e | Go to the end of the file |
-| e | Go to definition |
+| d | Go to definition |
| t | Go to type definition |
| r | Go to references |
| i | Go to implementation |
diff --git a/helix-core/src/movement.rs b/helix-core/src/movement.rs
index ba2e92b9..387b59b1 100644
--- a/helix-core/src/movement.rs
+++ b/helix-core/src/movement.rs
@@ -45,7 +45,7 @@ pub fn move_vertically(
let new_line = match dir {
Direction::Backward => row.saturating_sub(count),
- Direction::Forward => std::cmp::min(row.saturating_add(count), text.len_lines() - 1),
+ Direction::Forward => std::cmp::min(row.saturating_add(count), text.len_lines() - 2),
};
// convert to 0-indexed, subtract another 1 because len_chars() counts \n
@@ -76,8 +76,9 @@ pub fn move_next_word_start(slice: RopeSlice, mut begin: usize, count: usize) ->
begin += 1;
}
- // return if not skip while?
- skip_over_next(slice, &mut begin, |ch| ch == '\n');
+ if !skip_over_next(slice, &mut begin, |ch| ch == '\n') {
+ return None;
+ };
ch = slice.char(begin);
end = begin + 1;
@@ -134,7 +135,7 @@ pub fn move_next_word_end(slice: RopeSlice, mut begin: usize, count: usize) -> O
let mut end = begin;
for _ in 0..count {
- if begin + 1 == slice.len_chars() {
+ if begin + 2 >= slice.len_chars() {
return None;
}
@@ -145,8 +146,9 @@ pub fn move_next_word_end(slice: RopeSlice, mut begin: usize, count: usize) -> O
begin += 1;
}
- // return if not skip while?
- skip_over_next(slice, &mut begin, |ch| ch == '\n');
+ if !skip_over_next(slice, &mut begin, |ch| ch == '\n') {
+ return None;
+ };
end = begin;
@@ -199,18 +201,20 @@ fn categorize(ch: char) -> Category {
}
#[inline]
-pub fn skip_over_next<F>(slice: RopeSlice, pos: &mut usize, fun: F)
+/// Returns true if there are more characters left after the new position.
+pub fn skip_over_next<F>(slice: RopeSlice, pos: &mut usize, fun: F) -> bool
where
F: Fn(char) -> bool,
{
let mut chars = slice.chars_at(*pos);
- for ch in chars {
+ while let Some(ch) = chars.next() {
if !fun(ch) {
break;
}
*pos += 1;
}
+ chars.next().is_some()
}
#[inline]
diff --git a/helix-core/src/search.rs b/helix-core/src/search.rs
index af754ab7..55f7bf1d 100644
--- a/helix-core/src/search.rs
+++ b/helix-core/src/search.rs
@@ -7,6 +7,10 @@ pub fn find_nth_next(
n: usize,
inclusive: bool,
) -> Option<usize> {
+ if pos >= text.len_chars() {
+ return None;
+ }
+
// start searching right after pos
let mut chars = text.chars_at(pos + 1);
diff --git a/helix-syntax/build.rs b/helix-syntax/build.rs
index 70d71f92..447fa9c3 100644
--- a/helix-syntax/build.rs
+++ b/helix-syntax/build.rs
@@ -107,7 +107,10 @@ fn build_dir(dir: &str, language: &str) {
}
fn main() {
- let ignore = vec!["tree-sitter-typescript".to_string()];
+ let ignore = vec![
+ "tree-sitter-typescript".to_string(),
+ ".DS_Store".to_string(),
+ ];
let dirs = collect_tree_sitter_dirs(&ignore);
let mut n_jobs = 0;
diff --git a/helix-syntax/languages/tree-sitter-elixir b/helix-syntax/languages/tree-sitter-elixir
new file mode 160000
+Subproject 295e62a43b92cea909cfabe57e8818d177f4857
diff --git a/helix-syntax/src/lib.rs b/helix-syntax/src/lib.rs
index 79c1c1f5..bb0b2ec6 100644
--- a/helix-syntax/src/lib.rs
+++ b/helix-syntax/src/lib.rs
@@ -72,6 +72,7 @@ mk_langs!(
(CSharp, tree_sitter_c_sharp),
(Cpp, tree_sitter_cpp),
(Css, tree_sitter_css),
+ (Elixir, tree_sitter_elixir),
(Go, tree_sitter_go),
// (Haskell, tree_sitter_haskell),
(Html, tree_sitter_html),
diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs
index 3dba9333..7b30168a 100644
--- a/helix-term/src/commands.rs
+++ b/helix-term/src/commands.rs
@@ -473,10 +473,10 @@ fn scroll(cx: &mut Context, offset: usize, direction: Direction) {
let last_line = view.last_line(doc);
// clamp into viewport
- let line = cursor.row.clamp(
- view.first_line + scrolloff,
- last_line.saturating_sub(scrolloff),
- );
+ let line = cursor
+ .row
+ .min(view.first_line + scrolloff)
+ .max(last_line.saturating_sub(scrolloff));
let text = doc.text().slice(..);
let pos = pos_at_coords(text, Position::new(line, cursor.col)); // this func will properly truncate to line end
@@ -1031,6 +1031,9 @@ pub fn command_mode(cx: &mut Context) {
}
let parts = input.split_ascii_whitespace().collect::<Vec<&str>>();
+ if parts.is_empty() {
+ return;
+ }
if let Some(cmd) = cmd::COMMANDS.get(parts[0]) {
(cmd.fun)(editor, &parts[1..], event);
diff --git a/helix-term/src/keymap.rs b/helix-term/src/keymap.rs
index 044d97eb..fc7bb86e 100644
--- a/helix-term/src/keymap.rs
+++ b/helix-term/src/keymap.rs
@@ -240,10 +240,12 @@ pub fn default() -> Keymaps {
code: KeyCode::PageUp,
modifiers: KeyModifiers::NONE
} => commands::page_up,
+ ctrl!('b') => commands::page_up,
KeyEvent {
code: KeyCode::PageDown,
modifiers: KeyModifiers::NONE
} => commands::page_down,
+ ctrl!('f') => commands::page_down,
ctrl!('u') => commands::half_page_up,
ctrl!('d') => commands::half_page_down,
diff --git a/helix-term/src/main.rs b/helix-term/src/main.rs
index ac060bbe..3a0f4d20 100644
--- a/helix-term/src/main.rs
+++ b/helix-term/src/main.rs
@@ -8,11 +8,13 @@ mod ui;
use application::Application;
+use helix_core::config_dir;
+
use std::path::PathBuf;
-use anyhow::Error;
+use anyhow::{Context, Result};
-fn setup_logging(verbosity: u64) -> Result<(), fern::InitError> {
+fn setup_logging(verbosity: u64) -> Result<()> {
let mut base_config = fern::Dispatch::new();
// Let's say we depend on something which whose "info" level messages are too
@@ -27,8 +29,6 @@ fn setup_logging(verbosity: u64) -> Result<(), fern::InitError> {
_3_or_more => base_config.level(log::LevelFilter::Trace),
};
- let home = dirs_next::home_dir().expect("can't find the home directory");
-
// Separate file config so we can include year, month and day in file logs
let file_config = fern::Dispatch::new()
.format(|out, message, record| {
@@ -40,7 +40,7 @@ fn setup_logging(verbosity: u64) -> Result<(), fern::InitError> {
message
))
})
- .chain(fern::log_file(home.join("helix.log"))?);
+ .chain(fern::log_file(config_dir().join("helix.log"))?);
base_config.chain(file_config).apply()?;
@@ -51,7 +51,7 @@ pub struct Args {
files: Vec<PathBuf>,
}
-fn main() {
+fn main() -> Result<()> {
let help = format!(
"\
{} {}
@@ -89,14 +89,19 @@ FLAGS:
verbosity = 1;
}
- setup_logging(verbosity).expect("failed to initialize logging.");
+ let conf_dir = config_dir();
+
+ if !conf_dir.exists() {
+ std::fs::create_dir(&conf_dir);
+ }
+
+ setup_logging(verbosity).context("failed to initialize logging")?;
let args = Args {
files: pargs.finish().into_iter().map(|arg| arg.into()).collect(),
};
// initialize language registry
- use helix_core::config_dir;
use helix_core::syntax::{Loader, LOADER};
// load $HOME/.config/helix/languages.toml, fallback to default config
@@ -105,17 +110,16 @@ FLAGS:
.as_deref()
.unwrap_or(include_bytes!("../../languages.toml"));
- LOADER.get_or_init(|| {
- let config = toml::from_slice(toml).expect("Could not parse languages.toml");
- Loader::new(config)
- });
+ let config = toml::from_slice(toml).context("Could not parse languages.toml")?;
+ LOADER.get_or_init(|| Loader::new(config));
- let runtime = tokio::runtime::Runtime::new().unwrap();
+ let runtime = tokio::runtime::Runtime::new().context("unable to start tokio runtime")?;
// TODO: use the thread local executor to spawn the application task separately from the work pool
+ let mut app = Application::new(args).context("unable to create new appliction")?;
runtime.block_on(async move {
- let mut app = Application::new(args).unwrap();
-
app.run().await;
});
+
+ Ok(())
}
diff --git a/languages.toml b/languages.toml
index 87f03d06..6b80763f 100644
--- a/languages.toml
+++ b/languages.toml
@@ -18,6 +18,15 @@ roots = []
indent = { tab-width = 2, unit = " " }
[[language]]
+name = "elixir"
+scope = "source.elixir"
+injection-regex = "elixir"
+file-types = ["ex", "exs"]
+roots = []
+
+indent = { tab-width = 2, unit = " " }
+
+[[language]]
name = "json"
scope = "source.json"
injection-regex = "json"
diff --git a/runtime/queries/elixir/highlights.scm b/runtime/queries/elixir/highlights.scm
new file mode 100644
index 00000000..b9ec0210
--- /dev/null
+++ b/runtime/queries/elixir/highlights.scm
@@ -0,0 +1,146 @@
+["when" "and" "or" "not in" "not" "in" "fn" "do" "end" "catch" "rescue" "after" "else"] @keyword
+
+[(true) (false) (nil)] @constant.builtin
+
+(keyword
+ [(keyword_literal)
+ ":"] @tag)
+
+(keyword
+ (keyword_string
+ [(string_start)
+ (string_content)
+ (string_end)] @tag))
+
+[(atom_literal)
+ (atom_start)
+ (atom_content)
+ (atom_end)] @tag
+
+(comment) @comment
+
+(escape_sequence) @escape
+
+(call function: (function_identifier) @keyword
+ (#match? @keyword "^(defmodule|defexception|defp|def|with|case|cond|raise|import|require|use|defmacrop|defmacro|defguardp|defguard|defdelegate|defstruct|alias|defimpl|defprotocol|defoverridable|receive|if|for|try|throw|unless|reraise|super|quote|unquote|unquote_splicing)$"))
+
+(call function: (function_identifier) @keyword
+ [(call
+ function: (function_identifier) @function
+ (arguments
+ [(identifier) @variable.parameter
+ (_ (identifier) @variable.parameter)
+ (_ (_ (identifier) @variable.parameter))
+ (_ (_ (_ (identifier) @variable.parameter)))
+ (_ (_ (_ (_ (identifier) @variable.parameter))))
+ (_ (_ (_ (_ (_ (identifier) @variable.parameter)))))]))
+ (binary_op
+ left:
+ (call
+ function: (function_identifier) @function
+ (arguments
+ [(identifier) @variable.parameter
+ (_ (identifier) @variable.parameter)
+ (_ (_ (identifier) @variable.parameter))
+ (_ (_ (_ (identifier) @variable.parameter)))
+ (_ (_ (_ (_ (identifier) @variable.parameter))))
+ (_ (_ (_ (_ (_ (identifier) @variable.parameter)))))]))
+ operator: "when")
+ (binary_op
+ left: (identifier) @variable.parameter
+ operator: _ @function
+ right: (identifier) @variable.parameter)]
+ (#match? @keyword "^(defp|def|defmacrop|defmacro|defguardp|defguard|defdelegate)$")
+ (#match? @variable.parameter "^[^_]"))
+
+(call (function_identifier) @keyword
+ [(call
+ function: (function_identifier) @function)
+ (identifier) @function
+ (binary_op
+ left:
+ [(call
+ function: (function_identifier) @function)
+ (identifier) @function]
+ operator: "when")]
+ (#match? @keyword "^(defp|def|defmacrop|defmacro|defguardp|defguard|defdelegate)$"))
+
+(anonymous_function
+ (stab_expression
+ left: (bare_arguments
+ [(identifier) @variable.parameter
+ (_ (identifier) @variable.parameter)
+ (_ (_ (identifier) @variable.parameter))
+ (_ (_ (_ (identifier) @variable.parameter)))
+ (_ (_ (_ (_ (identifier) @variable.parameter))))
+ (_ (_ (_ (_ (_ (identifier) @variable.parameter)))))]))
+ (#match? @variable.parameter "^[^_]"))
+
+(unary_op
+ operator: "@"
+ (call (identifier) @attribute
+ (heredoc
+ [(heredoc_start)
+ (heredoc_content)
+ (heredoc_end)] @doc))
+ (#match? @attribute "^(doc|moduledoc)$"))
+
+(module) @type
+
+(unary_op
+ operator: "@" @attribute
+ [(call
+ function: (function_identifier) @attribute)
+ (identifier) @attribute])
+
+(unary_op
+ operator: _ @operator)
+
+(binary_op
+ operator: _ @operator)
+
+(heredoc
+ [(heredoc_start)
+ (heredoc_content)
+ (heredoc_end)] @string)
+
+(string
+ [(string_start)
+ (string_content)
+ (string_end)] @string)
+
+(sigil_start) @string.special
+(sigil_content) @string
+(sigil_end) @string.special
+
+(interpolation
+ "#{" @punctuation.special
+ "}" @punctuation.special)
+
+[
+ ","
+ "->"
+ "."
+] @punctuation.delimiter
+
+[
+ "("
+ ")"
+ "["
+ "]"
+ "{"
+ "}"
+ "<<"
+ ">>"
+] @punctuation.bracket
+
+[(identifier) @function.special
+ (#match? @function.special "^__.+__$")]
+
+[(remote_identifier) @function.special
+ (#match? @function.special "^__.+__$")]
+
+[(identifier) @comment
+ (#match? @comment "^_")]
+
+(ERROR) @warning
diff --git a/shell.nix b/shell.nix
index b6274581..180e8957 100644
--- a/shell.nix
+++ b/shell.nix
@@ -12,7 +12,7 @@ pkgs.mkShell {
# https://github.com/rust-lang/rust/issues/55979
LD_LIBRARY_PATH="${stdenv.cc.cc.lib}/lib64:$LD_LIBRARY_PATH";
- # HELIX_RUNTIME=./runtime;
- HELIX_RUNTIME="/home/speed/src/helix/runtime";
+ shellHook = ''
+ export HELIX_RUNTIME=$PWD/runtime
+ '';
}
-