mirror of https://github.com/helix-editor/helix
Compare commits
27 Commits
6171242f18
...
2bbd823dde
Author | SHA1 | Date |
---|---|---|
|
2bbd823dde | |
|
837627dd8a | |
|
1246549afd | |
|
ada8004ea5 | |
|
6576e92333 | |
|
26c230cea0 | |
|
0d21faf712 | |
|
931b8d9a31 | |
|
c4672ed902 | |
|
7694517d0f | |
|
395f4bf877 | |
|
056e2ffbb2 | |
|
82401d87b7 | |
|
6fbe9fe0bf | |
|
7537b0c25b | |
|
7add058abc | |
|
a60dc2d085 | |
|
a9a1e69f09 | |
|
c43074abdb | |
|
64390df159 | |
|
78bfdb680f | |
|
b3831c032e | |
|
6c19d2c1c4 | |
|
30b592fed9 | |
|
2b76e839ad | |
|
897569fa64 | |
|
2491522c87 |
|
@ -67,6 +67,16 @@ impl Display for TextObject {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn find_word_boundaries(slice: RopeSlice, pos: usize, is_long: bool) -> (usize, usize) {
|
||||||
|
let word_start = find_word_boundary(slice, pos, Direction::Backward, is_long);
|
||||||
|
let word_end = match slice.get_char(pos).map(categorize_char) {
|
||||||
|
None | Some(CharCategory::Whitespace | CharCategory::Eol) => pos,
|
||||||
|
_ => find_word_boundary(slice, pos + 1, Direction::Forward, is_long),
|
||||||
|
};
|
||||||
|
|
||||||
|
(word_start, word_end)
|
||||||
|
}
|
||||||
|
|
||||||
// count doesn't do anything yet
|
// count doesn't do anything yet
|
||||||
pub fn textobject_word(
|
pub fn textobject_word(
|
||||||
slice: RopeSlice,
|
slice: RopeSlice,
|
||||||
|
@ -77,11 +87,7 @@ pub fn textobject_word(
|
||||||
) -> Range {
|
) -> Range {
|
||||||
let pos = range.cursor(slice);
|
let pos = range.cursor(slice);
|
||||||
|
|
||||||
let word_start = find_word_boundary(slice, pos, Direction::Backward, long);
|
let (word_start, word_end) = find_word_boundaries(slice, pos, long);
|
||||||
let word_end = match slice.get_char(pos).map(categorize_char) {
|
|
||||||
None | Some(CharCategory::Whitespace | CharCategory::Eol) => pos,
|
|
||||||
_ => find_word_boundary(slice, pos + 1, Direction::Forward, long),
|
|
||||||
};
|
|
||||||
|
|
||||||
// Special case.
|
// Special case.
|
||||||
if word_start == word_end {
|
if word_start == word_end {
|
||||||
|
|
|
@ -19,6 +19,7 @@ use helix_core::{
|
||||||
movement::Direction,
|
movement::Direction,
|
||||||
syntax::{self, OverlayHighlights},
|
syntax::{self, OverlayHighlights},
|
||||||
text_annotations::TextAnnotations,
|
text_annotations::TextAnnotations,
|
||||||
|
textobject::find_word_boundaries,
|
||||||
unicode::width::UnicodeWidthStr,
|
unicode::width::UnicodeWidthStr,
|
||||||
visual_offset_from_block, Change, Position, Range, Selection, Transaction,
|
visual_offset_from_block, Change, Position, Range, Selection, Transaction,
|
||||||
};
|
};
|
||||||
|
@ -27,7 +28,7 @@ use helix_view::{
|
||||||
document::{Mode, SCRATCH_BUFFER_NAME},
|
document::{Mode, SCRATCH_BUFFER_NAME},
|
||||||
editor::{CompleteAction, CursorShapeConfig},
|
editor::{CompleteAction, CursorShapeConfig},
|
||||||
graphics::{Color, CursorKind, Modifier, Rect, Style},
|
graphics::{Color, CursorKind, Modifier, Rect, Style},
|
||||||
input::{KeyEvent, MouseButton, MouseEvent, MouseEventKind},
|
input::{KeyEvent, MouseButton, MouseClick, MouseEvent, MouseEventKind},
|
||||||
keyboard::{KeyCode, KeyModifiers},
|
keyboard::{KeyCode, KeyModifiers},
|
||||||
Document, Editor, Theme, View,
|
Document, Editor, Theme, View,
|
||||||
};
|
};
|
||||||
|
@ -1128,22 +1129,42 @@ impl EditorView {
|
||||||
if let Some((pos, view_id)) = pos_and_view(editor, row, column, true) {
|
if let Some((pos, view_id)) = pos_and_view(editor, row, column, true) {
|
||||||
let prev_view_id = view!(editor).id;
|
let prev_view_id = view!(editor).id;
|
||||||
let doc = doc_mut!(editor, &view!(editor, view_id).doc);
|
let doc = doc_mut!(editor, &view!(editor, view_id).doc);
|
||||||
|
let text = doc.text().slice(..);
|
||||||
|
|
||||||
if modifiers == KeyModifiers::ALT {
|
let selection = match editor.mouse_clicks.register_click(pos, view_id) {
|
||||||
let selection = doc.selection(view_id).clone();
|
MouseClick::Single => {
|
||||||
doc.set_selection(view_id, selection.push(Range::point(pos)));
|
if modifiers == KeyModifiers::ALT {
|
||||||
} else if editor.mode == Mode::Select {
|
let selection = doc.selection(view_id).clone();
|
||||||
// Discards non-primary selections for consistent UX with normal mode
|
selection.push(Range::point(pos))
|
||||||
let primary = doc.selection(view_id).primary().put_cursor(
|
} else if editor.mode == Mode::Select {
|
||||||
doc.text().slice(..),
|
// Discards non-primary selections for consistent UX with normal mode
|
||||||
pos,
|
let primary = doc.selection(view_id).primary().put_cursor(
|
||||||
true,
|
doc.text().slice(..),
|
||||||
);
|
pos,
|
||||||
editor.mouse_down_range = Some(primary);
|
true,
|
||||||
doc.set_selection(view_id, Selection::single(primary.anchor, primary.head));
|
);
|
||||||
} else {
|
editor.mouse_down_range = Some(primary);
|
||||||
doc.set_selection(view_id, Selection::point(pos));
|
|
||||||
}
|
Selection::single(primary.anchor, primary.head)
|
||||||
|
} else {
|
||||||
|
Selection::point(pos)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MouseClick::Double => {
|
||||||
|
let (word_start, word_end) = find_word_boundaries(text, pos, false);
|
||||||
|
|
||||||
|
Selection::single(word_start, word_end)
|
||||||
|
}
|
||||||
|
MouseClick::Triple => {
|
||||||
|
let current_line = text.char_to_line(pos);
|
||||||
|
let line_start = text.line_to_char(current_line);
|
||||||
|
let line_end = text.line_to_char(current_line + 1);
|
||||||
|
|
||||||
|
Selection::single(line_start, line_end)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
doc.set_selection(view_id, selection);
|
||||||
|
|
||||||
if view_id != prev_view_id {
|
if view_id != prev_view_id {
|
||||||
self.clear_completion(editor);
|
self.clear_completion(editor);
|
||||||
|
|
|
@ -8,7 +8,7 @@ use crate::{
|
||||||
graphics::{CursorKind, Rect},
|
graphics::{CursorKind, Rect},
|
||||||
handlers::Handlers,
|
handlers::Handlers,
|
||||||
info::Info,
|
info::Info,
|
||||||
input::KeyEvent,
|
input::{KeyEvent, MouseClicks},
|
||||||
register::Registers,
|
register::Registers,
|
||||||
theme::{self, Theme},
|
theme::{self, Theme},
|
||||||
tree::{self, Tree},
|
tree::{self, Tree},
|
||||||
|
@ -1133,6 +1133,8 @@ pub struct Editor {
|
||||||
|
|
||||||
pub mouse_down_range: Option<Range>,
|
pub mouse_down_range: Option<Range>,
|
||||||
pub cursor_cache: CursorCache,
|
pub cursor_cache: CursorCache,
|
||||||
|
|
||||||
|
pub mouse_clicks: MouseClicks,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type Motion = Box<dyn Fn(&mut Editor)>;
|
pub type Motion = Box<dyn Fn(&mut Editor)>;
|
||||||
|
@ -1255,6 +1257,7 @@ impl Editor {
|
||||||
handlers,
|
handlers,
|
||||||
mouse_down_range: None,
|
mouse_down_range: None,
|
||||||
cursor_cache: CursorCache::default(),
|
cursor_cache: CursorCache::default(),
|
||||||
|
mouse_clicks: MouseClicks::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1437,7 +1440,11 @@ impl Editor {
|
||||||
log::error!("failed to apply workspace edit: {err:?}")
|
log::error!("failed to apply workspace edit: {err:?}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fs::rename(old_path, &new_path)?;
|
|
||||||
|
if old_path.exists() {
|
||||||
|
fs::rename(old_path, &new_path)?;
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(doc) = self.document_by_path(old_path) {
|
if let Some(doc) = self.document_by_path(old_path) {
|
||||||
self.set_doc_path(doc.id(), &new_path);
|
self.set_doc_path(doc.id(), &new_path);
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ use serde::de::{self, Deserialize, Deserializer};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
pub use crate::keyboard::{KeyCode, KeyModifiers, MediaKeyCode, ModifierKeyCode};
|
pub use crate::keyboard::{KeyCode, KeyModifiers, MediaKeyCode, ModifierKeyCode};
|
||||||
|
use crate::ViewId;
|
||||||
|
|
||||||
#[derive(Debug, PartialOrd, PartialEq, Eq, Clone, Hash)]
|
#[derive(Debug, PartialOrd, PartialEq, Eq, Clone, Hash)]
|
||||||
pub enum Event {
|
pub enum Event {
|
||||||
|
@ -59,6 +60,82 @@ pub enum MouseButton {
|
||||||
/// Middle mouse button.
|
/// Middle mouse button.
|
||||||
Middle,
|
Middle,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Tracks the character positions and views where we last saw a mouse click
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct MouseClicks {
|
||||||
|
/// The last 2 clicks on specific characters in the editor:
|
||||||
|
/// (character index clicked, view id)
|
||||||
|
// We store the view id to ensure that if we click on
|
||||||
|
// the 3rd character in view #1 and 3rd character in view #2,
|
||||||
|
// it won't register as a double click.
|
||||||
|
clicks: [Option<(usize, ViewId)>; 2],
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
|
pub enum MouseClick {
|
||||||
|
/// A click where the pressed character is different to the character previously pressed
|
||||||
|
Single,
|
||||||
|
/// A click where the same character was pressed 2 times in a row
|
||||||
|
Double,
|
||||||
|
/// A click where the same character pressed 3 times in a row
|
||||||
|
Triple,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A fixed-size queue of length 2, storing the most recently clicked characters
|
||||||
|
/// as well as the views for which they were clicked.
|
||||||
|
impl MouseClicks {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
clicks: [None, None],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Add a click to the beginning of the queue, discarding the last click
|
||||||
|
fn insert(&mut self, click: usize, view_id: ViewId) {
|
||||||
|
self.clicks[1] = self.clicks[0];
|
||||||
|
self.clicks[0] = Some((click, view_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Registers a click for a certain character index, and returns the type of this click
|
||||||
|
pub fn register_click(&mut self, click: usize, view_id: ViewId) -> MouseClick {
|
||||||
|
let click_type = if self.is_triple_click(click, view_id) {
|
||||||
|
// Clicking 4th time on the same character should be the same as clicking for the 1st time
|
||||||
|
// So we reset the state
|
||||||
|
self.clicks = [None, None];
|
||||||
|
|
||||||
|
return MouseClick::Triple;
|
||||||
|
} else if self.is_double_click(click, view_id) {
|
||||||
|
MouseClick::Double
|
||||||
|
} else {
|
||||||
|
MouseClick::Single
|
||||||
|
};
|
||||||
|
|
||||||
|
self.insert(click, view_id);
|
||||||
|
|
||||||
|
click_type
|
||||||
|
}
|
||||||
|
|
||||||
|
/// If we click this character, would that be a triple click?
|
||||||
|
fn is_triple_click(&mut self, click: usize, view_id: ViewId) -> bool {
|
||||||
|
Some((click, view_id)) == self.clicks[0] && Some((click, view_id)) == self.clicks[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
/// If we click this character, would that be a double click?
|
||||||
|
fn is_double_click(&mut self, click: usize, view_id: ViewId) -> bool {
|
||||||
|
Some((click, view_id)) == self.clicks[0]
|
||||||
|
&& self.clicks[1].map_or(true, |(prev_click, prev_view_id)| {
|
||||||
|
!(click == prev_click && prev_view_id == view_id)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for MouseClicks {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Represents a key event.
|
/// Represents a key event.
|
||||||
// We use a newtype here because we want to customize Deserialize and Display.
|
// We use a newtype here because we want to customize Deserialize and Display.
|
||||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash)]
|
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash)]
|
||||||
|
@ -961,4 +1038,52 @@ mod test {
|
||||||
assert!(parse_macro("abc>123").is_err());
|
assert!(parse_macro("abc>123").is_err());
|
||||||
assert!(parse_macro("wd<foo>").is_err());
|
assert!(parse_macro("wd<foo>").is_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn clicking_4th_time_resets_mouse_clicks() {
|
||||||
|
let mut mouse_clicks = MouseClicks::new();
|
||||||
|
let view = ViewId::default();
|
||||||
|
|
||||||
|
assert_eq!(mouse_clicks.register_click(4, view), MouseClick::Single);
|
||||||
|
assert_eq!(mouse_clicks.register_click(4, view), MouseClick::Double);
|
||||||
|
assert_eq!(mouse_clicks.register_click(4, view), MouseClick::Triple);
|
||||||
|
|
||||||
|
assert_eq!(mouse_clicks.register_click(4, view), MouseClick::Single);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn clicking_different_characters_resets_mouse_clicks() {
|
||||||
|
let mut mouse_clicks = MouseClicks::new();
|
||||||
|
let view = ViewId::default();
|
||||||
|
|
||||||
|
assert_eq!(mouse_clicks.register_click(4, view), MouseClick::Single);
|
||||||
|
assert_eq!(mouse_clicks.register_click(4, view), MouseClick::Double);
|
||||||
|
|
||||||
|
assert_eq!(mouse_clicks.register_click(8, view), MouseClick::Single);
|
||||||
|
|
||||||
|
assert_eq!(mouse_clicks.register_click(1, view), MouseClick::Single);
|
||||||
|
assert_eq!(mouse_clicks.register_click(1, view), MouseClick::Double);
|
||||||
|
assert_eq!(mouse_clicks.register_click(1, view), MouseClick::Triple);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn switching_views_resets_mouse_clicks() {
|
||||||
|
let mut mouse_clicks = MouseClicks::new();
|
||||||
|
let mut view_ids = slotmap::HopSlotMap::with_key();
|
||||||
|
let view1 = view_ids.insert(());
|
||||||
|
let view2 = view_ids.insert(());
|
||||||
|
|
||||||
|
assert_eq!(mouse_clicks.register_click(4, view1), MouseClick::Single);
|
||||||
|
|
||||||
|
assert_eq!(mouse_clicks.register_click(4, view2), MouseClick::Single);
|
||||||
|
|
||||||
|
assert_eq!(mouse_clicks.register_click(4, view1), MouseClick::Single);
|
||||||
|
|
||||||
|
assert_eq!(mouse_clicks.register_click(4, view2), MouseClick::Single);
|
||||||
|
assert_eq!(mouse_clicks.register_click(4, view2), MouseClick::Double);
|
||||||
|
|
||||||
|
assert_eq!(mouse_clicks.register_click(4, view1), MouseClick::Single);
|
||||||
|
assert_eq!(mouse_clicks.register_click(4, view1), MouseClick::Double);
|
||||||
|
assert_eq!(mouse_clicks.register_click(4, view1), MouseClick::Triple);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -937,7 +937,7 @@ indent = { tab-width = 2, unit = " " }
|
||||||
|
|
||||||
[[grammar]]
|
[[grammar]]
|
||||||
name = "html"
|
name = "html"
|
||||||
source = { git = "https://github.com/tree-sitter/tree-sitter-html", rev = "29f53d8f4f2335e61bf6418ab8958dac3282077a" }
|
source = { git = "https://github.com/tree-sitter/tree-sitter-html", rev = "cbb91a0ff3621245e890d1c50cc811bffb77a26b" }
|
||||||
|
|
||||||
[[language]]
|
[[language]]
|
||||||
name = "python"
|
name = "python"
|
||||||
|
|
|
@ -1,3 +1,48 @@
|
||||||
; inherits: html
|
(tag_name) @tag
|
||||||
|
(erroneous_end_tag_name) @error
|
||||||
|
(doctype) @constant
|
||||||
|
(attribute_name) @attribute
|
||||||
|
(comment) @comment
|
||||||
|
|
||||||
|
((attribute
|
||||||
|
(attribute_name) @attribute
|
||||||
|
(quoted_attribute_value (attribute_value) @markup.link.url))
|
||||||
|
(#any-of? @attribute "href" "src"))
|
||||||
|
|
||||||
|
((element
|
||||||
|
(start_tag
|
||||||
|
(tag_name) @tag)
|
||||||
|
(text) @markup.link.label)
|
||||||
|
(#eq? @tag "a"))
|
||||||
|
|
||||||
|
(attribute [(attribute_value) (quoted_attribute_value)] @string)
|
||||||
|
|
||||||
|
((element
|
||||||
|
(start_tag
|
||||||
|
(tag_name) @tag)
|
||||||
|
(text) @markup.bold)
|
||||||
|
(#any-of? @tag "strong" "b"))
|
||||||
|
|
||||||
|
((element
|
||||||
|
(start_tag
|
||||||
|
(tag_name) @tag)
|
||||||
|
(text) @markup.italic)
|
||||||
|
(#any-of? @tag "em" "i"))
|
||||||
|
|
||||||
|
((element
|
||||||
|
(start_tag
|
||||||
|
(tag_name) @tag)
|
||||||
|
(text) @markup.strikethrough)
|
||||||
|
(#any-of? @tag "s" "del"))
|
||||||
|
|
||||||
|
[
|
||||||
|
"<"
|
||||||
|
">"
|
||||||
|
"</"
|
||||||
|
"/>"
|
||||||
|
"<!"
|
||||||
|
] @punctuation.bracket
|
||||||
|
|
||||||
|
"=" @punctuation.delimiter
|
||||||
|
|
||||||
["---"] @punctuation.delimiter
|
["---"] @punctuation.delimiter
|
||||||
|
|
|
@ -12,8 +12,6 @@
|
||||||
(namespace_definition name: (namespace_identifier) @namespace)
|
(namespace_definition name: (namespace_identifier) @namespace)
|
||||||
(namespace_identifier) @namespace
|
(namespace_identifier) @namespace
|
||||||
|
|
||||||
(qualified_identifier name: (identifier) @type.enum.variant)
|
|
||||||
|
|
||||||
(auto) @type
|
(auto) @type
|
||||||
"decltype" @type
|
"decltype" @type
|
||||||
|
|
||||||
|
@ -21,12 +19,29 @@
|
||||||
(reference_declarator ["&" "&&"] @type.builtin)
|
(reference_declarator ["&" "&&"] @type.builtin)
|
||||||
(abstract_reference_declarator ["&" "&&"] @type.builtin)
|
(abstract_reference_declarator ["&" "&&"] @type.builtin)
|
||||||
|
|
||||||
|
; -------
|
||||||
; Functions
|
; Functions
|
||||||
|
; -------
|
||||||
|
; Support up to 4 levels of nesting of qualifiers
|
||||||
|
; i.e. a::b::c::d::func();
|
||||||
(call_expression
|
(call_expression
|
||||||
function: (qualified_identifier
|
function: (qualified_identifier
|
||||||
name: (identifier) @function))
|
name: (identifier) @function))
|
||||||
|
(call_expression
|
||||||
|
function: (qualified_identifier
|
||||||
|
name: (qualified_identifier
|
||||||
|
name: (identifier) @function)))
|
||||||
|
(call_expression
|
||||||
|
function: (qualified_identifier
|
||||||
|
name: (qualified_identifier
|
||||||
|
name: (qualified_identifier
|
||||||
|
name: (identifier) @function))))
|
||||||
|
(call_expression
|
||||||
|
function: (qualified_identifier
|
||||||
|
name: (qualified_identifier
|
||||||
|
name: (qualified_identifier
|
||||||
|
name: (qualified_identifier
|
||||||
|
name: (identifier) @function)))))
|
||||||
|
|
||||||
(template_function
|
(template_function
|
||||||
name: (identifier) @function)
|
name: (identifier) @function)
|
||||||
|
@ -34,26 +49,42 @@
|
||||||
(template_method
|
(template_method
|
||||||
name: (field_identifier) @function)
|
name: (field_identifier) @function)
|
||||||
|
|
||||||
; Support up to 3 levels of nesting of qualifiers
|
; Support up to 4 levels of nesting of qualifiers
|
||||||
; i.e. a::b::c::func();
|
; i.e. a::b::c::d::func();
|
||||||
(function_declarator
|
(function_declarator
|
||||||
declarator: (qualified_identifier
|
declarator: (qualified_identifier
|
||||||
name: (identifier) @function))
|
name: (identifier) @function))
|
||||||
|
|
||||||
(function_declarator
|
(function_declarator
|
||||||
declarator: (qualified_identifier
|
declarator: (qualified_identifier
|
||||||
name: (qualified_identifier
|
name: (qualified_identifier
|
||||||
name: (identifier) @function)))
|
name: (identifier) @function)))
|
||||||
|
|
||||||
(function_declarator
|
(function_declarator
|
||||||
declarator: (qualified_identifier
|
declarator: (qualified_identifier
|
||||||
name: (qualified_identifier
|
name: (qualified_identifier
|
||||||
name: (qualified_identifier
|
name: (qualified_identifier
|
||||||
name: (identifier) @function))))
|
name: (identifier) @function))))
|
||||||
|
(function_declarator
|
||||||
|
declarator: (qualified_identifier
|
||||||
|
name: (qualified_identifier
|
||||||
|
name: (qualified_identifier
|
||||||
|
name: (qualified_identifier
|
||||||
|
name: (identifier) @function)))))
|
||||||
|
|
||||||
(function_declarator
|
(function_declarator
|
||||||
declarator: (field_identifier) @function)
|
declarator: (field_identifier) @function)
|
||||||
|
|
||||||
|
; Constructors
|
||||||
|
|
||||||
|
(class_specifier
|
||||||
|
(type_identifier) @type
|
||||||
|
(field_declaration_list
|
||||||
|
(function_definition
|
||||||
|
(function_declarator
|
||||||
|
(identifier) @constructor)))
|
||||||
|
(#eq? @type @constructor))
|
||||||
|
(destructor_name "~" @constructor
|
||||||
|
(identifier) @constructor)
|
||||||
|
|
||||||
; Parameters
|
; Parameters
|
||||||
|
|
||||||
(parameter_declaration
|
(parameter_declaration
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
(erroneous_end_tag_name) @error
|
(erroneous_end_tag_name) @error
|
||||||
(doctype) @constant
|
(doctype) @constant
|
||||||
(attribute_name) @attribute
|
(attribute_name) @attribute
|
||||||
|
(entity) @string.special.symbol
|
||||||
(comment) @comment
|
(comment) @comment
|
||||||
|
|
||||||
((attribute
|
((attribute
|
||||||
|
|
Loading…
Reference in New Issue