mirror of https://github.com/helix-editor/helix
Compare commits
8 Commits
1a028d12c5
...
2649df1be7
Author | SHA1 | Date |
---|---|---|
|
2649df1be7 | |
|
395a71bf53 | |
|
1e4bf6704a | |
|
ef56d34f60 | |
|
0fa6b1408b | |
|
7d17fd7ba3 | |
|
5af123a4d9 | |
|
395371db51 |
|
@ -177,7 +177,14 @@ impl Compositor {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render(&mut self, area: Rect, surface: &mut Surface, cx: &mut Context) {
|
pub fn render(&mut self, area: Rect, surface: &mut Surface, cx: &mut Context) {
|
||||||
|
// Check if there are prompt layers active and update EditorView
|
||||||
|
let has_prompt = self.has_component("helix_term::ui::prompt::Prompt");
|
||||||
|
|
||||||
for layer in &mut self.layers {
|
for layer in &mut self.layers {
|
||||||
|
// Update prompt state for EditorView
|
||||||
|
if let Some(editor_view) = layer.as_any_mut().downcast_mut::<crate::ui::EditorView>() {
|
||||||
|
editor_view.prompt_active = has_prompt;
|
||||||
|
}
|
||||||
layer.render(area, surface, cx);
|
layer.render(area, surface, cx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,6 +44,8 @@ pub struct EditorView {
|
||||||
spinners: ProgressSpinners,
|
spinners: ProgressSpinners,
|
||||||
/// Tracks if the terminal window is focused by reaction to terminal focus events
|
/// Tracks if the terminal window is focused by reaction to terminal focus events
|
||||||
terminal_focused: bool,
|
terminal_focused: bool,
|
||||||
|
/// Tracks if there are prompt layers active (updated by compositor)
|
||||||
|
pub prompt_active: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
@ -67,6 +69,7 @@ impl EditorView {
|
||||||
completion: None,
|
completion: None,
|
||||||
spinners: ProgressSpinners::default(),
|
spinners: ProgressSpinners::default(),
|
||||||
terminal_focused: true,
|
terminal_focused: true,
|
||||||
|
prompt_active: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,7 +136,7 @@ impl EditorView {
|
||||||
if let Some(tabstops) = Self::tabstop_highlights(doc, theme) {
|
if let Some(tabstops) = Self::tabstop_highlights(doc, theme) {
|
||||||
overlays.push(tabstops);
|
overlays.push(tabstops);
|
||||||
}
|
}
|
||||||
overlays.push(Self::doc_selection_highlights(
|
overlays.push(self.doc_selection_highlights(
|
||||||
editor.mode(),
|
editor.mode(),
|
||||||
doc,
|
doc,
|
||||||
view,
|
view,
|
||||||
|
@ -427,7 +430,8 @@ impl EditorView {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get highlight spans for selections in a document view.
|
/// Get highlight spans for selections in a document view.
|
||||||
pub fn doc_selection_highlights(
|
fn doc_selection_highlights(
|
||||||
|
&self,
|
||||||
mode: Mode,
|
mode: Mode,
|
||||||
doc: &Document,
|
doc: &Document,
|
||||||
view: &View,
|
view: &View,
|
||||||
|
@ -481,12 +485,9 @@ impl EditorView {
|
||||||
|
|
||||||
// Special-case: cursor at end of the rope.
|
// Special-case: cursor at end of the rope.
|
||||||
if range.head == range.anchor && range.head == text.len_chars() {
|
if range.head == range.anchor && range.head == text.len_chars() {
|
||||||
if !selection_is_primary || (cursor_is_block && is_terminal_focused) {
|
if !selection_is_primary || !is_terminal_focused || self.prompt_active {
|
||||||
// Bar and underline cursors are drawn by the terminal
|
// Primary cursor is drawn by the terminal when focused and no prompt is active
|
||||||
// BUG: If the editor area loses focus while having a bar or
|
// Secondary cursors, unfocused primary cursor, and editor cursor when prompt is active are drawn manually
|
||||||
// underline cursor (eg. when a regex prompt has focus) then
|
|
||||||
// the primary cursor will be invisible. This doesn't happen
|
|
||||||
// with block cursors since we manually draw *all* cursors.
|
|
||||||
spans.push((cursor_scope, range.head..range.head + 1));
|
spans.push((cursor_scope, range.head..range.head + 1));
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
|
@ -504,17 +505,17 @@ impl EditorView {
|
||||||
cursor_start
|
cursor_start
|
||||||
};
|
};
|
||||||
spans.push((selection_scope, range.anchor..selection_end));
|
spans.push((selection_scope, range.anchor..selection_end));
|
||||||
// add block cursors
|
// add cursors
|
||||||
// skip primary cursor if terminal is unfocused - crossterm cursor is used in that case
|
// skip primary cursor if terminal is focused and no prompt is active - terminal cursor is used in that case
|
||||||
if !selection_is_primary || (cursor_is_block && is_terminal_focused) {
|
if !selection_is_primary || !is_terminal_focused || self.prompt_active {
|
||||||
spans.push((cursor_scope, cursor_start..range.head));
|
spans.push((cursor_scope, cursor_start..range.head));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Reverse case.
|
// Reverse case.
|
||||||
let cursor_end = next_grapheme_boundary(text, range.head);
|
let cursor_end = next_grapheme_boundary(text, range.head);
|
||||||
// add block cursors
|
// add cursors
|
||||||
// skip primary cursor if terminal is unfocused - crossterm cursor is used in that case
|
// skip primary cursor if terminal is focused and no prompt is active - terminal cursor is used in that case
|
||||||
if !selection_is_primary || (cursor_is_block && is_terminal_focused) {
|
if !selection_is_primary || !is_terminal_focused || self.prompt_active {
|
||||||
spans.push((cursor_scope, range.head..cursor_end));
|
spans.push((cursor_scope, range.head..cursor_end));
|
||||||
}
|
}
|
||||||
// non block cursors look like they exclude the cursor
|
// non block cursors look like they exclude the cursor
|
||||||
|
@ -1591,17 +1592,12 @@ impl Component for EditorView {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cursor(&self, _area: Rect, editor: &Editor) -> (Option<Position>, CursorKind) {
|
fn cursor(&self, _area: Rect, editor: &Editor) -> (Option<Position>, CursorKind) {
|
||||||
match editor.cursor() {
|
let (pos, kind) = editor.cursor();
|
||||||
// all block cursors are drawn manually
|
if self.terminal_focused {
|
||||||
(pos, CursorKind::Block) => {
|
(pos, kind)
|
||||||
if self.terminal_focused {
|
} else {
|
||||||
(pos, CursorKind::Hidden)
|
// use underline cursor when terminal loses focus for visibility
|
||||||
} else {
|
(pos, CursorKind::Underline)
|
||||||
// use crossterm cursor when terminal loses focus
|
|
||||||
(pos, CursorKind::Underline)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cursor => cursor,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -746,7 +746,7 @@ async fn test_hardlink_write() -> anyhow::Result<()> {
|
||||||
async fn edit_file_with_content(file_content: &[u8]) -> anyhow::Result<()> {
|
async fn edit_file_with_content(file_content: &[u8]) -> anyhow::Result<()> {
|
||||||
let mut file = tempfile::NamedTempFile::new()?;
|
let mut file = tempfile::NamedTempFile::new()?;
|
||||||
|
|
||||||
file.as_file_mut().write_all(&file_content)?;
|
file.as_file_mut().write_all(file_content)?;
|
||||||
|
|
||||||
helpers::test_key_sequence(
|
helpers::test_key_sequence(
|
||||||
&mut helpers::AppBuilder::new()
|
&mut helpers::AppBuilder::new()
|
||||||
|
|
|
@ -61,6 +61,7 @@ pub struct TestCase {
|
||||||
pub out_text: String,
|
pub out_text: String,
|
||||||
pub out_selection: Selection,
|
pub out_selection: Selection,
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
pub line_feed_handling: LineFeedHandling,
|
pub line_feed_handling: LineFeedHandling,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -425,7 +426,7 @@ pub fn reload_file(file: &mut NamedTempFile) -> anyhow::Result<()> {
|
||||||
let f = std::fs::OpenOptions::new()
|
let f = std::fs::OpenOptions::new()
|
||||||
.write(true)
|
.write(true)
|
||||||
.read(true)
|
.read(true)
|
||||||
.open(&path)?;
|
.open(path)?;
|
||||||
*file.as_file_mut() = f;
|
*file.as_file_mut() = f;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -1022,6 +1022,7 @@ shebangs = []
|
||||||
comment-token = "#"
|
comment-token = "#"
|
||||||
language-servers = [ "nil", "nixd" ]
|
language-servers = [ "nil", "nixd" ]
|
||||||
indent = { tab-width = 2, unit = " " }
|
indent = { tab-width = 2, unit = " " }
|
||||||
|
formatter = { command = "nixfmt" }
|
||||||
|
|
||||||
[[grammar]]
|
[[grammar]]
|
||||||
name = "nix"
|
name = "nix"
|
||||||
|
@ -4243,10 +4244,11 @@ comment-token = "#"
|
||||||
block-comment-tokens = ["#-", "-#"]
|
block-comment-tokens = ["#-", "-#"]
|
||||||
indent = { tab-width = 2, unit = " " }
|
indent = { tab-width = 2, unit = " " }
|
||||||
language-servers = ["koto-ls"]
|
language-servers = ["koto-ls"]
|
||||||
|
formatter = {command = "koto", args = ["--format"]}
|
||||||
|
|
||||||
[[grammar]]
|
[[grammar]]
|
||||||
name = "koto"
|
name = "koto"
|
||||||
source = { git = "https://github.com/koto-lang/tree-sitter-koto", rev = "b420f7922d0d74905fd0d771e5b83be9ee8a8a9a" }
|
source = { git = "https://github.com/koto-lang/tree-sitter-koto", rev = "2ffc77c14f0ac1674384ff629bfc207b9c57ed89" }
|
||||||
|
|
||||||
[[language]]
|
[[language]]
|
||||||
name = "gpr"
|
name = "gpr"
|
||||||
|
|
|
@ -5,11 +5,13 @@
|
||||||
"*"
|
"*"
|
||||||
"/"
|
"/"
|
||||||
"%"
|
"%"
|
||||||
|
"^"
|
||||||
"+="
|
"+="
|
||||||
"-="
|
"-="
|
||||||
"*="
|
"*="
|
||||||
"/="
|
"/="
|
||||||
"%="
|
"%="
|
||||||
|
"^="
|
||||||
"=="
|
"=="
|
||||||
"!="
|
"!="
|
||||||
"<"
|
"<"
|
||||||
|
@ -99,12 +101,18 @@
|
||||||
(export
|
(export
|
||||||
(identifier) @namespace)
|
(identifier) @namespace)
|
||||||
|
|
||||||
(call
|
(chain
|
||||||
function: (identifier) @function.method)
|
start: (identifier) @function)
|
||||||
|
|
||||||
(chain
|
(chain
|
||||||
lookup: (identifier) @variable.other.member)
|
lookup: (identifier) @variable.other.member)
|
||||||
|
|
||||||
|
(call
|
||||||
|
function: (identifier)) @function
|
||||||
|
|
||||||
|
(call_arg
|
||||||
|
(identifier) @variable.other.member)
|
||||||
|
|
||||||
[
|
[
|
||||||
(true)
|
(true)
|
||||||
(false)
|
(false)
|
||||||
|
@ -139,13 +147,10 @@
|
||||||
|
|
||||||
(self) @variable.builtin
|
(self) @variable.builtin
|
||||||
|
|
||||||
(variable
|
(type
|
||||||
type: (identifier) @type)
|
_ @type)
|
||||||
|
|
||||||
(arg
|
(arg
|
||||||
(_ (identifier) @variable.parameter))
|
(_ (identifier) @variable.parameter))
|
||||||
|
|
||||||
(ellipsis) @variable.parameter
|
(ellipsis) @variable.parameter
|
||||||
|
|
||||||
(function
|
|
||||||
output_type: (identifier) @type)
|
|
||||||
|
|
|
@ -11,10 +11,6 @@
|
||||||
(call_args
|
(call_args
|
||||||
((call_arg) @parameter.inside . ","? @parameter.around) @parameter.around)
|
((call_arg) @parameter.inside . ","? @parameter.around) @parameter.around)
|
||||||
|
|
||||||
(chain
|
|
||||||
call: (tuple
|
|
||||||
((element) @parameter.inside . ","? @parameter.around) @parameter.around))
|
|
||||||
|
|
||||||
(map
|
(map
|
||||||
((entry_inline) @entry.inside . ","? @entry.around) @entry.around)
|
((entry_inline) @entry.inside . ","? @entry.around) @entry.around)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue