Merge branch 'master' of https://github.com/helix-editor/helix into tree_explore

pull/9/head
wongjiahau 1 year ago
commit 8ef95ee56a

@ -37,7 +37,7 @@ jobs:
uses: actions/checkout@v3
- name: Install stable toolchain
uses: dtolnay/rust-toolchain@1.63
uses: dtolnay/rust-toolchain@1.65
- uses: Swatinem/rust-cache@v2
@ -66,7 +66,7 @@ jobs:
uses: actions/checkout@v3
- name: Install stable toolchain
uses: dtolnay/rust-toolchain@1.63
uses: dtolnay/rust-toolchain@1.65
with:
components: rustfmt, clippy
@ -91,7 +91,7 @@ jobs:
uses: actions/checkout@v3
- name: Install stable toolchain
uses: dtolnay/rust-toolchain@1.63
uses: dtolnay/rust-toolchain@1.65
- uses: Swatinem/rust-cache@v2

@ -14,7 +14,7 @@ jobs:
uses: actions/checkout@v3
- name: Install nix
uses: cachix/install-nix-action@v19
uses: cachix/install-nix-action@v20
- name: Authenticate with Cachix
uses: cachix/cachix-action@v12

789
Cargo.lock generated

File diff suppressed because it is too large Load Diff

@ -98,6 +98,7 @@ The following statusline elements can be configured:
| `spinner` | A progress spinner indicating LSP activity |
| `file-name` | The path/name of the opened file |
| `file-base-name` | The basename of the opened file |
| `file-modification-indicator` | The indicator to show whether the file is modified (a `[+]` appears when there are unsaved changes) |
| `file-encoding` | The encoding of the opened file if it differs from UTF-8 |
| `file-line-ending` | The file line endings (CRLF or LF) |
| `total-line-numbers` | The total line numbers of the opened file |

@ -104,6 +104,7 @@
| prisma | ✓ | | | `prisma-language-server` |
| prolog | | | | `swipl` |
| protobuf | ✓ | | ✓ | |
| prql | ✓ | | | |
| purescript | ✓ | | | `purescript-language-server` |
| python | ✓ | ✓ | ✓ | `pylsp` |
| qml | ✓ | | ✓ | `qmlls` |
@ -113,6 +114,7 @@
| rescript | ✓ | ✓ | | `rescript-language-server` |
| rmarkdown | ✓ | | ✓ | `R` |
| ron | ✓ | | ✓ | |
| rst | ✓ | | | |
| ruby | ✓ | ✓ | ✓ | `solargraph` |
| rust | ✓ | ✓ | ✓ | `rust-analyzer` |
| sage | ✓ | ✓ | | |

@ -10,7 +10,7 @@ repository = "https://github.com/helix-editor/helix"
homepage = "https://helix-editor.com"
include = ["src/**/*", "README.md"]
default-run = "hx"
rust-version = "1.57"
rust-version = "1.65"
[features]
default = ["git"]

@ -345,12 +345,12 @@ impl Application {
tokio::select! {
biased;
Some(event) = input_stream.next() => {
self.handle_terminal_events(event).await;
}
Some(signal) = self.signals.next() => {
self.handle_signals(signal).await;
}
Some(event) = input_stream.next() => {
self.handle_terminal_events(event).await;
}
Some(callback) = self.jobs.futures.next() => {
self.jobs.handle_callback(&mut self.editor, &mut self.compositor, callback);
self.render().await;
@ -638,6 +638,11 @@ impl Application {
self.compositor
.handle_event(&Event::Resize(width, height), &mut cx)
}
// Ignore keyboard release events.
CrosstermEvent::Key(crossterm::event::KeyEvent {
kind: crossterm::event::KeyEventKind::Release,
..
}) => false,
event => self.compositor.handle_event(&event.into(), &mut cx),
};

@ -2988,7 +2988,6 @@ fn goto_first_diag(cx: &mut Context) {
None => return,
};
doc.set_selection(view.id, selection);
align_view(doc, view, Align::Center);
}
fn goto_last_diag(cx: &mut Context) {
@ -2998,7 +2997,6 @@ fn goto_last_diag(cx: &mut Context) {
None => return,
};
doc.set_selection(view.id, selection);
align_view(doc, view, Align::Center);
}
fn goto_next_diag(cx: &mut Context) {
@ -3020,7 +3018,6 @@ fn goto_next_diag(cx: &mut Context) {
None => return,
};
doc.set_selection(view.id, selection);
align_view(doc, view, Align::Center);
}
fn goto_prev_diag(cx: &mut Context) {
@ -3045,7 +3042,6 @@ fn goto_prev_diag(cx: &mut Context) {
None => return,
};
doc.set_selection(view.id, selection);
align_view(doc, view, Align::Center);
}
fn goto_first_change(cx: &mut Context) {
@ -3108,10 +3104,7 @@ fn goto_next_change_impl(cx: &mut Context, direction: Direction) {
.prev_hunk(cursor_line)
.map(|idx| idx.saturating_sub(count)),
};
// TODO refactor with let..else once MSRV reaches 1.65
let hunk_idx = if let Some(hunk_idx) = hunk_idx {
hunk_idx
} else {
let Some(hunk_idx) = hunk_idx else {
return range;
};
let hunk = hunks.nth_hunk(hunk_idx);

@ -202,10 +202,7 @@ pub fn render_text<'t>(
// formattter.line_pos returns to line index of the next grapheme
// so it must be called before formatter.next
let doc_line = formatter.line_pos();
// TODO refactor with let .. else once MSRV reaches 1.65
let (grapheme, mut pos) = if let Some(it) = formatter.next() {
it
} else {
let Some((grapheme, mut pos)) = formatter.next() else {
let mut last_pos = formatter.visual_pos();
if last_pos.row >= row_off {
last_pos.col -= 1;
@ -226,7 +223,6 @@ pub fn render_text<'t>(
// skip any graphemes on visual lines before the block start
if pos.row < row_off {
if char_pos >= style_span.1 {
// TODO refactor using let..else once MSRV reaches 1.65
style_span = if let Some(style_span) = styles.next() {
style_span
} else {
@ -266,12 +262,7 @@ pub fn render_text<'t>(
// aquire the correct grapheme style
if char_pos >= style_span.1 {
// TODO refactor using let..else once MSRV reaches 1.65
style_span = if let Some(style_span) = styles.next() {
style_span
} else {
(Style::default(), usize::MAX)
}
style_span = styles.next().unwrap_or((Style::default(), usize::MAX));
}
char_pos += grapheme.doc_chars();
@ -322,7 +313,7 @@ pub struct TextRenderer<'a> {
pub nbsp: String,
pub space: String,
pub tab: String,
pub tab_width: u16,
pub indent_width: u16,
pub starting_indent: usize,
pub draw_indent_guides: bool,
pub col_offset: usize,
@ -370,16 +361,19 @@ impl<'a> TextRenderer<'a> {
let text_style = theme.get("ui.text");
let indent_width = doc.indent_style.indent_width(tab_width) as u16;
TextRenderer {
surface,
indent_guide_char: editor_config.indent_guides.character.into(),
newline,
nbsp,
space,
tab_width: tab_width as u16,
tab,
whitespace_style: theme.get("ui.virtual.whitespace"),
starting_indent: (col_offset / tab_width)
indent_width,
starting_indent: col_offset / indent_width as usize
+ (col_offset % indent_width as usize != 0) as usize
+ editor_config.indent_guides.skip_levels as usize,
indent_guide_style: text_style.patch(
theme
@ -461,14 +455,14 @@ impl<'a> TextRenderer<'a> {
// Don't draw indent guides outside of view
let end_indent = min(
indent_level,
// Add tab_width - 1 to round up, since the first visible
// Add indent_width - 1 to round up, since the first visible
// indent might be a bit after offset.col
self.col_offset + self.viewport.width as usize + (self.tab_width - 1) as usize,
) / self.tab_width as usize;
self.col_offset + self.viewport.width as usize + (self.indent_width as usize - 1),
) / self.indent_width as usize;
for i in self.starting_indent..end_indent {
let x =
(self.viewport.x as usize + (i * self.tab_width as usize) - self.col_offset) as u16;
let x = (self.viewport.x as usize + (i * self.indent_width as usize) - self.col_offset)
as u16;
let y = self.viewport.y + row;
debug_assert!(self.surface.in_bounds(x, y));
self.surface

@ -342,13 +342,10 @@ impl Component for Markdown {
fn required_size(&mut self, viewport: (u16, u16)) -> Option<(u16, u16)> {
let padding = 2;
if padding >= viewport.1 || padding >= viewport.0 {
return None;
}
let contents = self.parse(None);
// TODO: account for tab width
let max_text_width = (viewport.0 - padding).min(120);
let max_text_width = (viewport.0.saturating_sub(padding)).min(120);
let (width, height) = crate::ui::text::required_size(&contents, max_text_width);
Some((width + padding, height + padding))

@ -58,7 +58,7 @@ pub fn required_size(text: &tui::text::Text, max_text_width: u16) -> (u16, u16)
let content_width = content.width() as u16;
if content_width > max_text_width {
text_width = max_text_width;
height += content_width / max_text_width;
height += content_width.checked_div(max_text_width).unwrap_or(0);
} else if content_width > text_width {
text_width = content_width;
}

@ -16,13 +16,13 @@ helix-core = { version = "0.6", path = "../helix-core" }
tokio = { version = "1", features = ["rt", "rt-multi-thread", "time", "sync", "parking_lot", "macros"] }
parking_lot = "0.12"
git-repository = { version = "0.32", default-features = false , optional = true }
gix = { version = "0.39.0", default-features = false , optional = true }
imara-diff = "0.1.5"
log = "0.4"
[features]
git = ["git-repository"]
git = ["gix"]
[dev-dependencies]
tempfile = "3.4"

@ -1,9 +1,8 @@
use std::path::Path;
use git::objs::tree::EntryMode;
use git::sec::trust::DefaultForLevel;
use git::{Commit, ObjectId, Repository, ThreadSafeRepository};
use git_repository as git;
use gix::objs::tree::EntryMode;
use gix::sec::trust::DefaultForLevel;
use gix::{Commit, ObjectId, Repository, ThreadSafeRepository};
use crate::DiffProvider;
@ -15,13 +14,13 @@ pub struct Git;
impl Git {
fn open_repo(path: &Path, ceiling_dir: Option<&Path>) -> Option<ThreadSafeRepository> {
// custom open options
let mut git_open_opts_map = git::sec::trust::Mapping::<git::open::Options>::default();
let mut git_open_opts_map = gix::sec::trust::Mapping::<gix::open::Options>::default();
// On windows various configuration options are bundled as part of the installations
// This path depends on the install location of git and therefore requires some overhead to lookup
// This is basically only used on windows and has some overhead hence it's disabled on other platforms.
// `gitoxide` doesn't use this as default
let config = git::permissions::Config {
let config = gix::permissions::Config {
system: true,
git: true,
user: true,
@ -30,16 +29,16 @@ impl Git {
git_binary: cfg!(windows),
};
// change options for config permissions without touching anything else
git_open_opts_map.reduced = git_open_opts_map.reduced.permissions(git::Permissions {
git_open_opts_map.reduced = git_open_opts_map.reduced.permissions(gix::Permissions {
config,
..git::Permissions::default_for_level(git::sec::Trust::Reduced)
..gix::Permissions::default_for_level(gix::sec::Trust::Reduced)
});
git_open_opts_map.full = git_open_opts_map.full.permissions(git::Permissions {
git_open_opts_map.full = git_open_opts_map.full.permissions(gix::Permissions {
config,
..git::Permissions::default_for_level(git::sec::Trust::Full)
..gix::Permissions::default_for_level(gix::sec::Trust::Full)
});
let mut open_options = git::discover::upwards::Options::default();
let mut open_options = gix::discover::upwards::Options::default();
if let Some(ceiling_dir) = ceiling_dir {
open_options.ceiling_dirs = vec![ceiling_dir.to_owned()];
}

@ -237,8 +237,8 @@ impl Rect {
Rect {
x: x1,
y: y1,
width: x2 - x1,
height: y2 - y1,
width: x2.saturating_sub(x1),
height: y2.saturating_sub(y1),
}
}

@ -242,7 +242,7 @@ impl View {
at_top = true;
true
}
Some((visual_pos, _)) if visual_pos.row >= vertical_viewport_end - scrolloff => {
Some((visual_pos, _)) if visual_pos.row + scrolloff + 1 >= vertical_viewport_end => {
if CENTERING && visual_pos.row >= vertical_viewport_end {
// cursor out of view
return None;
@ -257,7 +257,7 @@ impl View {
let v_off = if at_top {
scrolloff as isize
} else {
viewport.height as isize - scrolloff as isize
viewport.height as isize - scrolloff as isize - 1
};
(offset.anchor, offset.vertical_offset) =
char_idx_at_visual_offset(doc_text, cursor, -v_off, 0, &text_fmt, &annotations);

@ -1190,7 +1190,7 @@ source = { git = "https://github.com/shunsambongi/tree-sitter-gitignore", rev =
name = "graphql"
scope = "source.graphql"
injection-regex = "graphql"
file-types = ["gql", "graphql"]
file-types = ["gql", "graphql", "graphqls"]
roots = []
indent = { tab-width = 2, unit = " " }
@ -1463,7 +1463,7 @@ indent = { tab-width = 4, unit = "\t" }
[[grammar]]
name = "gdscript"
source = { git = "https://github.com/PrestonKnopp/tree-sitter-gdscript", rev = "a56a6fcec3fb63ec3324bf9373aae7298861eb30" }
source = { git = "https://github.com/PrestonKnopp/tree-sitter-gdscript", rev = "a4b57cc3bcbfc24550e858159647e9238e7ad1ac" }
[[language]]
name = "godot-resource"
@ -2208,6 +2208,19 @@ indent = { tab-width = 2, unit = " " }
name = "yuck"
source = { git = "https://github.com/Philipp-M/tree-sitter-yuck", rev = "9e97da5773f82123a8c8cccf8f7e795d140ed7d1" }
[[language]]
name = "prql"
scope = "source.prql"
injection-regex = "prql"
file-types = ["prql"]
roots = []
comment-token = "#"
indent = { tab-width = 4, unit = " " }
[[grammar]]
name = "prql"
source = { git = "https://github.com/PRQL/tree-sitter-prql", rev = "3f27cac466f030ee7d985d91eba5470e01dd21ea" }
[[language]]
name = "po"
scope = "source.po"
@ -2231,3 +2244,14 @@ indent = { tab-width = 8, unit = " " }
[[grammar]]
name = "nasm"
source = { git = "https://github.com/naclsn/tree-sitter-nasm", rev = "a0db15db6fcfb1bf2cc8702500e55e558825c48b" }
[[language]]
name = "rst"
scope = "source.rst"
comment-token = ".."
file-types = ["rst"]
roots = []
[[grammar]]
name = "rst"
source = { git = "https://github.com/stsewd/tree-sitter-rst", rev = "25e6328872ac3a764ba8b926aea12719741103f1" }

@ -5,17 +5,33 @@
":" @punctuation.delimiter
; Hint level tags
((tag (name) @hint)
(#match? @hint "^(HINT|MARK)$"))
("text" @hint
(#match? @hint "^(HINT|MARK)$"))
; Info level tags
((tag (name) @info)
(#match? @info "^(INFO|NOTE|TODO)$"))
("text" @info
(#match? @info "^(INFO|NOTE|TODO)$"))
; Warning level tags
((tag (name) @warning)
(#match? @warning "^(TODO|HACK|WARNING)$"))
(#match? @warning "^(HACK|WARN|WARNING)$"))
("text" @warning
(#match? @warning "^(TODO|HACK|WARNING)$"))
(#match? @warning "^(HACK|WARN|WARNING)$"))
; Error level tags
((tag (name) @error)
(match? @error "^(FIXME|XXX|BUG)$"))
(match? @error "^(BUG|FIXME|ISSUE|XXX)$"))
("text" @error
(match? @error "^(FIXME|XXX|BUG)$"))
(match? @error "^(BUG|FIXME|ISSUE|XXX)$"))
(tag
(name) @ui.text

@ -1,7 +1,8 @@
; Identifier naming conventions
((identifier) @constant
(#match? @constant "^[A-Z][A-Z_]*$"))
(
(identifier) @constant
(#match? @constant "^[A-Z][A-Z\\d_]+$"))
; class
(class_name_statement (name) @type)
@ -11,32 +12,35 @@
; Function calls
(attribute_call (identifier) @function)
(base_call (identifier) @function)
(call (identifier) @function)
; Function definitions
(function_definition (name) @function)
(constructor_definition "_init" @function)
;; Literals
(integer) @constant.numeric.integer
(float) @constant.numeric.float
(comment) @comment
(string) @string
(escape_sequence) @constant.character.escape
(identifier) @variable
(type) @type
(expression_statement (array (identifier) @type))
(binary_operator (identifier) @type)
;; Literals
(variable_statement (identifier) @variable)
(get_node) @label
(const_statement (name) @constant)
(integer) @constant.numeric.integer
(float) @constant.numeric.float
(escape_sequence) @constant.character.escape
[
(true)
(false)
(null)
] @constant.builtin
] @constant.builtin.boolean
(null) @constant.builtin
[
"+"
@ -62,37 +66,67 @@
"~"
"<<"
">>"
"and"
"or"
"not"
] @operator
(annotation (identifier) @keyword.storage.modifier)
[
(static_keyword)
(remote_keyword)
(tool_statement)
"var"
"func"
"setget"
"in"
"is"
"as"
"if"
"else"
"elif"
] @keyword.control.conditional
[
"while"
"for"
] @keyword.control.repeat
[
"return"
"pass"
"break"
"continue"
"pass"
] @keyword.control.return
[
"func"
] @keyword.control.function
[
"export"
] @keyword.control.import
[
"in"
"is"
"as"
"match"
"and"
"or"
"not"
] @keyword.operator
[
"var"
"class"
"class_name"
"enum"
] @keyword.storage.type
[
(remote_keyword)
(static_keyword)
"const"
"signal"
"@"
] @keyword.storage.modifier
[
"setget"
"onready"
"export"
"extends"
"const"
"set"
"get"
] @keyword

@ -12,6 +12,7 @@
(dictionary (_))
(array (_))
(setget)
] @indent
[
@ -25,7 +26,6 @@
(class_definition)
] @extend
[
(return_statement)
(break_statement)

@ -1,2 +1,18 @@
((comment) @injection.content
(#set! injection.language "comment"))
; ((section) @injection.content
; (#set! injection.language "comment"))
((section
(attribute
(identifier) @_type
(string) @_is_shader)
(property
(path) @_is_code
(string) @injection.content))
(#match? @_type "type")
(#match? @_is_shader "Shader")
(#eq? @_is_code "code")
(#set! injection.language "glsl")
)

@ -0,0 +1,136 @@
[
(keyword_from)
(keyword_filter)
(keyword_derive)
(keyword_group)
(keyword_aggregate)
(keyword_sort)
(keyword_take)
(keyword_window)
(keyword_join)
(keyword_select)
(keyword_switch)
(keyword_append)
(keyword_remove)
(keyword_intersect)
(keyword_rolling)
(keyword_rows)
(keyword_expanding)
(keyword_let)
(keyword_prql)
(keyword_from_text)
] @keyword
(literal) @string
(assignment
alias: (field) @variable.other.member)
alias: (identifier) @variable.other.member
(f_string) @string.special
(s_string) @string.special
(comment) @comment
(keyword_func) @keyword.function
(function_call
(identifier) @function)
[
"+"
"-"
"*"
"/"
"="
"=="
"<"
"<="
"!="
">="
">"
"->"
(bang)
] @operator
[
"("
")"
"["
"]"
] @punctuation.bracket
[
","
"."
(pipe)
] @punctuation.delimiter
(literal
(integer) @constant.numeric.integer)
(integer) @constant.numeric.integer
(literal
(decimal_number) @constant.numeric.float)
(decimal_number) @constant.numeric.float
[
(keyword_min)
(keyword_max)
(keyword_count)
(keyword_count_distinct)
(keyword_average)
(keyword_avg)
(keyword_sum)
(keyword_stddev)
(keyword_count)
] @function
[
(keyword_side)
(keyword_version)
(keyword_target)
(keyword_null)
(keyword_format)
] @attribute
(target) @function.builtin
[
(date)
(time)
(timestamp)
] @string.special
[
(keyword_left)
(keyword_inner)
(keyword_right)
(keyword_full)
(keyword_csv)
(keyword_json)
] @function.method
[
(keyword_true)
(keyword_false)
] @constant.builtin.boolean
[
(keyword_and)
(keyword_or)
] @keyword.operator
(function_definition
(keyword_func)
name: (identifier) @function)
(parameter
(identifier) @variable.parameter)
(variable
(keyword_let)
name: (identifier) @constant)

@ -0,0 +1,8 @@
((s_string) @injection.content
(#set! injection.language "sql"))
(from_text
(keyword_from_text)
(keyword_json)
(literal) @injection.content
(#set! injection.language "json"))

@ -0,0 +1,38 @@
(comment) @comment
[
(title)
] @markup.heading.1
[
"adornment"
] @markup.heading.marker
[
(target)
(reference)
] @markup.link.url
[
"bullet"
] @markup.list.unnumbered
(strong) @markup.bold
(emphasis) @markup.italic
(literal) @markup.raw.inline
(list_item
(term) @markup.bold
(classifier)? @markup.italic)
(directive
[".." (type) "::"] @function
)
(field
[":" (field_name) ":"] @variable.other.member
)
(interpreted_text) @markup.raw.inline
(interpreted_text (role)) @keyword

@ -7,6 +7,7 @@
"ui.text.focus" = { fg = "selection_background", modifiers = ["bold"]}
"ui.selection" = {bg="selection_background", fg="selection_foreground"}
"ui.cursorline" = {bg="cursorline_background"}
"ui.highlight" = {bg="cursorline_background"}
"ui.statusline" = {bg="paper_bar_bg", fg="regular0"}
"ui.statusline.select" = {bg="background", fg="bright7"}
"ui.statusline.normal" = {bg="background", fg="bright3"}

@ -6,6 +6,7 @@
"ui.text" = "foreground"
"ui.text.focus" = { fg = "selection_background", modifiers = ["bold"]}
"ui.selection" = {bg="selection_background", fg="selection_foreground"}
"ui.highlight" = {bg="cursorline_background"}
"ui.cursorline" = {bg="cursorline_background"}
"ui.statusline" = {bg="paper_bar_bg", fg="regular0"}
"ui.statusline.select" = {bg="background", fg="bright7"}

@ -1,3 +1,3 @@
[toolchain]
channel = "1.63.0"
channel = "1.65.0"
components = ["rustfmt", "rust-src"]

Loading…
Cancel
Save