Added SelectToken action
This commit is contained in:
parent
3e3755c0b5
commit
8bd6a70968
4 changed files with 87 additions and 18 deletions
|
|
@ -32,6 +32,7 @@ pub enum Action {
|
|||
OpenFile(PathBuf), // Open the file and switch the current pane to it
|
||||
CommandStart(&'static str), // Start a new command
|
||||
GotoLine(isize), // Go to the specified file line
|
||||
SelectToken, // Fully select the token under the cursor
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
|
@ -174,6 +175,22 @@ impl RawEvent {
|
|||
Some(Action::Move(dir, page, retain_base))
|
||||
}
|
||||
|
||||
pub fn to_select_token(&self) -> Option<Action> {
|
||||
if matches!(
|
||||
&self.0,
|
||||
TerminalEvent::Key(KeyEvent {
|
||||
code: KeyCode::Char(' '),
|
||||
modifiers: KeyModifiers::CONTROL,
|
||||
kind: KeyEventKind::Press,
|
||||
..
|
||||
})
|
||||
) {
|
||||
Some(Action::SelectToken)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_open_prompt(&self) -> Option<Action> {
|
||||
if matches!(
|
||||
&self.0,
|
||||
|
|
|
|||
|
|
@ -85,8 +85,12 @@ impl Highlighter {
|
|||
|
||||
pub fn rust() -> Self {
|
||||
Self::new_from_regex([
|
||||
(TokenKind::Doc, r"\/\/[\/!][^\n]*$"),
|
||||
(TokenKind::Comment, r"\/\/[^$]*$"),
|
||||
// Both kinds of comments match multiple lines
|
||||
(
|
||||
TokenKind::Doc,
|
||||
r"\/\/[\/!][^\n]*$(\n[[:space:]]\/\/[\/!][^\n]*$)*",
|
||||
),
|
||||
(TokenKind::Comment, r"\/\/[^$]*$(\n[[:space:]]\/\/[^$]*$)*"),
|
||||
// Multi-line comment
|
||||
(TokenKind::Comment, r"\/\*[^(\*\/)]*\*\/"),
|
||||
(
|
||||
|
|
@ -105,7 +109,7 @@ impl Highlighter {
|
|||
// Primitives
|
||||
(
|
||||
TokenKind::Type,
|
||||
r"\b[(u8)(u16)(u32)(u64)(u128)(i8)(i16)(i32)(i64)(i128)(usize)(isize)(bool)(str)(char)]\b",
|
||||
r"\b[(u8)(u16)(u32)(u64)(u128)(i8)(i16)(i32)(i64)(i128)(usize)(isize)(bool)(str)(char)(f16)(f32)(f64)(f128)]\b",
|
||||
),
|
||||
// "foo" or b"foo" or r#"foo"#
|
||||
(TokenKind::String, r#"b?r?(#*)@("[(\\")[^("~)]]*("~))"#),
|
||||
|
|
@ -132,7 +136,7 @@ impl Highlighter {
|
|||
])
|
||||
}
|
||||
|
||||
fn highlight_str(&self, mut s: &[char]) -> Vec<(Range<usize>, TokenKind)> {
|
||||
fn highlight_str(&self, mut s: &[char]) -> Vec<Token> {
|
||||
let mut tokens = Vec::new();
|
||||
let mut i = 0;
|
||||
loop {
|
||||
|
|
@ -142,7 +146,10 @@ impl Highlighter {
|
|||
.enumerate()
|
||||
.find_map(|(i, r)| Some((i, r.matches(s)?)))
|
||||
{
|
||||
tokens.push((i..i + n, self.entries[idx]));
|
||||
tokens.push(Token {
|
||||
kind: self.entries[idx],
|
||||
range: i..i + n,
|
||||
});
|
||||
n
|
||||
} else if !s.is_empty() {
|
||||
1
|
||||
|
|
@ -166,21 +173,31 @@ impl Highlighter {
|
|||
|
||||
pub struct Highlights {
|
||||
pub highlighter: Highlighter,
|
||||
tokens: Vec<(Range<usize>, TokenKind)>,
|
||||
tokens: Vec<Token>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Token {
|
||||
pub kind: TokenKind,
|
||||
pub range: Range<usize>,
|
||||
}
|
||||
|
||||
impl Highlights {
|
||||
pub fn insert(&mut self, at: usize, s: &str) {}
|
||||
|
||||
pub fn get_at(&self, pos: usize) -> Option<TokenKind> {
|
||||
pub fn get_at(&self, pos: usize) -> Option<&Token> {
|
||||
let idx = self.tokens
|
||||
.binary_search_by_key(&pos, |(r, _)| r.start)
|
||||
.binary_search_by_key(&pos, |tok| tok.range.start)
|
||||
// .ok()?
|
||||
.unwrap_or_else(|p| p.saturating_sub(1))
|
||||
// .saturating_sub(1)
|
||||
;
|
||||
let (r, tok) = self.tokens.get(idx)?;
|
||||
if r.contains(&pos) { Some(*tok) } else { None }
|
||||
let tok = self.tokens.get(idx)?;
|
||||
if tok.range.contains(&pos) {
|
||||
Some(tok)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -279,16 +296,12 @@ impl State<'_> {
|
|||
let mut times = 0;
|
||||
loop {
|
||||
let pos = self.pos;
|
||||
if times >= *at_most {
|
||||
break;
|
||||
} else if self.attempt(x).is_none() {
|
||||
break;
|
||||
if times >= *at_most || self.attempt(x).is_none() {
|
||||
break (times >= *at_least).then_some(());
|
||||
}
|
||||
assert_ne!(pos, self.pos, "{x:?}");
|
||||
times += 1;
|
||||
}
|
||||
|
||||
if times >= *at_least { Some(()) } else { None }
|
||||
}
|
||||
Regex::Delim(d, r) => {
|
||||
let old_pos = self.pos;
|
||||
|
|
|
|||
30
src/state.rs
30
src/state.rs
|
|
@ -185,6 +185,36 @@ impl Buffer {
|
|||
cursor.base = cursor.pos;
|
||||
}
|
||||
|
||||
pub fn select_token_cursor(&mut self, cursor_id: CursorId) {
|
||||
let Some(cursor) = self.cursors.get_mut(cursor_id) else {
|
||||
return;
|
||||
};
|
||||
if let Some(tok) = self
|
||||
.highlights
|
||||
.as_ref()
|
||||
// Choose the longest token that the cursor is touching
|
||||
.and_then(|hl| {
|
||||
let a = hl.get_at(cursor.pos);
|
||||
let b = hl.get_at(cursor.pos.saturating_sub(1));
|
||||
a.zip(b)
|
||||
.map(|(a, b)| {
|
||||
if a.range.end - a.range.start > b.range.end - b.range.start {
|
||||
a
|
||||
} else {
|
||||
b
|
||||
}
|
||||
})
|
||||
.or(a)
|
||||
.or(b)
|
||||
})
|
||||
{
|
||||
cursor.base = tok.range.start;
|
||||
cursor.pos = tok.range.end;
|
||||
} else {
|
||||
// TODO: Bell
|
||||
}
|
||||
}
|
||||
|
||||
pub fn move_cursor(
|
||||
&mut self,
|
||||
cursor_id: CursorId,
|
||||
|
|
|
|||
|
|
@ -55,7 +55,12 @@ impl Input {
|
|||
cursor_id: CursorId,
|
||||
event: Event,
|
||||
) -> Result<Resp, Event> {
|
||||
match event.to_action(|e| e.to_char().map(Action::Char).or_else(|| e.to_move())) {
|
||||
match event.to_action(|e| {
|
||||
e.to_char()
|
||||
.map(Action::Char)
|
||||
.or_else(|| e.to_move())
|
||||
.or_else(|| e.to_select_token())
|
||||
}) {
|
||||
Some(Action::Char(c)) => {
|
||||
if c == '\x08' {
|
||||
buffer.backspace(cursor_id);
|
||||
|
|
@ -82,6 +87,10 @@ impl Input {
|
|||
self.refocus(buffer, cursor_id);
|
||||
Ok(Resp::handled(None))
|
||||
}
|
||||
Some(Action::SelectToken) => {
|
||||
buffer.select_token_cursor(cursor_id);
|
||||
Ok(Resp::handled(None))
|
||||
}
|
||||
_ => Err(event),
|
||||
}
|
||||
}
|
||||
|
|
@ -165,7 +174,7 @@ impl Input {
|
|||
.highlights
|
||||
.as_ref()
|
||||
.and_then(|hl| hl.get_at(pos))
|
||||
.map(|tok| state.theme.token_color(tok))
|
||||
.map(|tok| state.theme.token_color(tok.kind))
|
||||
{
|
||||
(fg, c)
|
||||
} else {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue