mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-25 08:41:05 +00:00
WIP [no ci]
This commit is contained in:
parent
d59e52c39b
commit
146606e034
16 changed files with 219 additions and 66 deletions
|
|
@ -1 +1 @@
|
||||||
{"words":["Punct","KEYMAP","splitn","crossterm","YAZI","unar","peekable","ratatui","syntect","pbpaste","pbcopy","ffmpegthumbnailer","oneshot","Posix","Lsar","XADDOS","zoxide","cands","Deque","precache","imageops","IFBLK","IFCHR","IFDIR","IFIFO","IFLNK","IFMT","IFSOCK","IRGRP","IROTH","IRUSR","ISGID","ISUID","ISVTX","IWGRP","IWOTH","IWUSR","IXGRP","IXOTH","IXUSR","libc","winsize","TIOCGWINSZ","xpixel","ypixel","ioerr","appender","Catppuccin","macchiato","gitmodules","Dotfiles","bashprofile","vimrc","flac","webp","exiftool","mediainfo","ripgrep","nvim","indexmap","indexmap","unwatch","canonicalize","serde","fsevent","Ueberzug","iterm","wezterm","sixel","chafa","ueberzugpp","️ Überzug","️ Überzug","Konsole","Alacritty","Überzug","pkgs","paru","unarchiver","pdftoppm","poppler","prebuild","singlefile","jpegopt","EXIF","rustfmt","mktemp","nanos","xclip","xsel","natord","Mintty","nixos","nixpkgs","SIGTSTP","SIGCONT","SIGCONT","mlua","nonstatic","userdata","metatable","natsort","backstack","luajit","Succ","Succ","cand","fileencoding","foldmethod","lightgreen","darkgray","lightred","lightyellow","lightcyan","nushell","msvc","aarch","linemode","sxyazi"],"language":"en","version":"0.2","flagWords":[]}
|
{"words":["Punct","KEYMAP","splitn","crossterm","YAZI","unar","peekable","ratatui","syntect","pbpaste","pbcopy","ffmpegthumbnailer","oneshot","Posix","Lsar","XADDOS","zoxide","cands","Deque","precache","imageops","IFBLK","IFCHR","IFDIR","IFIFO","IFLNK","IFMT","IFSOCK","IRGRP","IROTH","IRUSR","ISGID","ISUID","ISVTX","IWGRP","IWOTH","IWUSR","IXGRP","IXOTH","IXUSR","libc","winsize","TIOCGWINSZ","xpixel","ypixel","ioerr","appender","Catppuccin","macchiato","gitmodules","Dotfiles","bashprofile","vimrc","flac","webp","exiftool","mediainfo","ripgrep","nvim","indexmap","indexmap","unwatch","canonicalize","serde","fsevent","Ueberzug","iterm","wezterm","sixel","chafa","ueberzugpp","️ Überzug","️ Überzug","Konsole","Alacritty","Überzug","pkgs","paru","unarchiver","pdftoppm","poppler","prebuild","singlefile","jpegopt","EXIF","rustfmt","mktemp","nanos","xclip","xsel","natord","Mintty","nixos","nixpkgs","SIGTSTP","SIGCONT","SIGCONT","mlua","nonstatic","userdata","metatable","natsort","backstack","luajit","Succ","Succ","cand","fileencoding","foldmethod","lightgreen","darkgray","lightred","lightyellow","lightcyan","nushell","msvc","aarch","linemode","sxyazi","rsplit"],"flagWords":[],"version":"0.2","language":"en"}
|
||||||
|
|
|
||||||
|
|
@ -244,8 +244,8 @@ keymap = [
|
||||||
{ on = [ "<C-q>" ], exec = "close", desc = "Cancel completion" },
|
{ on = [ "<C-q>" ], exec = "close", desc = "Cancel completion" },
|
||||||
{ on = [ "<Enter>" ], exec = "close --submit", desc = "Submit the completion" },
|
{ on = [ "<Enter>" ], exec = "close --submit", desc = "Submit the completion" },
|
||||||
|
|
||||||
{ on = [ "k" ], exec = "arrow -1", desc = "Move cursor up" },
|
{ on = [ "<A-k>" ], exec = "arrow -1", desc = "Move cursor up" },
|
||||||
{ on = [ "j" ], exec = "arrow 1", desc = "Move cursor down" },
|
{ on = [ "<A-j>" ], exec = "arrow 1", desc = "Move cursor down" },
|
||||||
|
|
||||||
{ on = [ "<Up>" ], exec = "arrow -1", desc = "Move cursor up" },
|
{ on = [ "<Up>" ], exec = "arrow -1", desc = "Move cursor up" },
|
||||||
{ on = [ "<Down>" ], exec = "arrow 1", desc = "Move cursor down" },
|
{ on = [ "<Down>" ], exec = "arrow 1", desc = "Move cursor down" },
|
||||||
|
|
|
||||||
|
|
@ -84,13 +84,19 @@ inactive = {}
|
||||||
|
|
||||||
# : }}}
|
# : }}}
|
||||||
|
|
||||||
|
|
||||||
# : Completion {{{
|
# : Completion {{{
|
||||||
|
|
||||||
[completion]
|
[completion]
|
||||||
border = { fg = "blue" }
|
border = { fg = "blue" }
|
||||||
active = { fg = "lightcyan" }
|
active = { bg = "darkgray" }
|
||||||
inactive = {}
|
inactive = {}
|
||||||
|
|
||||||
|
# Icons
|
||||||
|
icon_file = ""
|
||||||
|
icon_folder = ""
|
||||||
|
icon_command = ""
|
||||||
|
|
||||||
# : }}}
|
# : }}}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -86,6 +86,10 @@ pub struct Completion {
|
||||||
pub border: Style,
|
pub border: Style,
|
||||||
pub active: Style,
|
pub active: Style,
|
||||||
pub inactive: Style,
|
pub inactive: Style,
|
||||||
|
|
||||||
|
pub icon_file: String,
|
||||||
|
pub icon_folder: String,
|
||||||
|
pub icon_command: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize)]
|
#[derive(Deserialize, Serialize)]
|
||||||
|
|
|
||||||
44
yazi-core/src/completion/commands/arrow.rs
Normal file
44
yazi-core/src/completion/commands/arrow.rs
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
use yazi_config::keymap::Exec;
|
||||||
|
|
||||||
|
use crate::completion::Completion;
|
||||||
|
|
||||||
|
pub struct Opt(isize);
|
||||||
|
|
||||||
|
impl From<&Exec> for Opt {
|
||||||
|
fn from(e: &Exec) -> Self { Self(e.args.first().and_then(|s| s.parse().ok()).unwrap_or(0)) }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Completion {
|
||||||
|
fn next(&mut self, step: usize) -> bool {
|
||||||
|
let len = self.items.len();
|
||||||
|
if len == 0 {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
let old = self.cursor;
|
||||||
|
self.cursor = (self.cursor + step).min(len - 1);
|
||||||
|
|
||||||
|
let limit = self.limit();
|
||||||
|
if self.cursor >= len.min(self.offset + limit) {
|
||||||
|
self.offset = len.saturating_sub(limit).min(self.offset + self.cursor - old);
|
||||||
|
}
|
||||||
|
|
||||||
|
old != self.cursor
|
||||||
|
}
|
||||||
|
|
||||||
|
fn prev(&mut self, step: usize) -> bool {
|
||||||
|
let old = self.cursor;
|
||||||
|
self.cursor = self.cursor.saturating_sub(step);
|
||||||
|
|
||||||
|
if self.cursor < self.offset {
|
||||||
|
self.offset = self.offset.saturating_sub(old - self.cursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
old != self.cursor
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn arrow(&mut self, opt: impl Into<Opt>) -> bool {
|
||||||
|
let step = opt.into().0;
|
||||||
|
if step > 0 { self.next(step as usize) } else { self.prev(step.unsigned_abs()) }
|
||||||
|
}
|
||||||
|
}
|
||||||
32
yazi-core/src/completion/commands/close.rs
Normal file
32
yazi-core/src/completion/commands/close.rs
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
use yazi_config::keymap::{Exec, KeymapLayer};
|
||||||
|
|
||||||
|
use crate::{completion::Completion, emit};
|
||||||
|
|
||||||
|
pub struct Opt(bool);
|
||||||
|
|
||||||
|
impl From<&Exec> for Opt {
|
||||||
|
fn from(e: &Exec) -> Self { Self(e.named.contains_key("submit")) }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<bool> for Opt {
|
||||||
|
fn from(b: bool) -> Self { Self(b) }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Completion {
|
||||||
|
pub fn close(&mut self, opt: impl Into<Opt>) -> bool {
|
||||||
|
let submit = opt.into().0;
|
||||||
|
if submit {
|
||||||
|
emit!(Call(
|
||||||
|
Exec::call("complete", vec![self.items[self.cursor].to_owned()])
|
||||||
|
.with_bool("apply", true)
|
||||||
|
.with("ticket", self.ticket)
|
||||||
|
.vec(),
|
||||||
|
KeymapLayer::Input
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
self.cursor = 0;
|
||||||
|
self.visible = false;
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,2 +1,4 @@
|
||||||
|
mod arrow;
|
||||||
|
mod close;
|
||||||
mod show;
|
mod show;
|
||||||
mod trigger;
|
mod trigger;
|
||||||
|
|
|
||||||
|
|
@ -1,39 +1,20 @@
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct Completion {
|
pub struct Completion {
|
||||||
pub items: Vec<String>,
|
pub(super) items: Vec<String>,
|
||||||
pub cursor: usize,
|
pub(super) offset: usize,
|
||||||
|
pub cursor: usize,
|
||||||
|
|
||||||
pub ticket: usize,
|
pub ticket: usize,
|
||||||
pub visible: bool,
|
pub visible: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Completion {
|
impl Completion {
|
||||||
pub fn close(&mut self, submit: bool) -> bool {
|
#[inline]
|
||||||
self.cursor = 0;
|
pub fn window(&self) -> &[String] {
|
||||||
|
let end = (self.offset + self.limit()).min(self.items.len());
|
||||||
self.visible = false;
|
&self.items[self.offset..end]
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn next(&mut self, step: usize) -> bool {
|
|
||||||
let len = self.items.len();
|
|
||||||
if len == 0 {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
let old = self.cursor;
|
|
||||||
self.cursor = (self.cursor + step).min(len - 1);
|
|
||||||
|
|
||||||
old != self.cursor
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn prev(&mut self, step: usize) -> bool {
|
|
||||||
let old = self.cursor;
|
|
||||||
self.cursor = self.cursor.saturating_sub(step);
|
|
||||||
|
|
||||||
old != self.cursor
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn selected(&self) -> Option<&String> { self.items.get(self.cursor) }
|
pub fn limit(&self) -> usize { self.items.len().min(5) }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
45
yazi-core/src/input/commands/complete.rs
Normal file
45
yazi-core/src/input/commands/complete.rs
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
use yazi_config::keymap::Exec;
|
||||||
|
|
||||||
|
use crate::input::Input;
|
||||||
|
|
||||||
|
pub struct Opt<'a> {
|
||||||
|
word: &'a str,
|
||||||
|
ticket: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> From<&'a Exec> for Opt<'a> {
|
||||||
|
fn from(e: &'a Exec) -> Self {
|
||||||
|
Self {
|
||||||
|
word: e.args.first().map(|w| w.as_str()).unwrap_or_default(),
|
||||||
|
ticket: e.named.get("ticket").and_then(|v| v.parse().ok()).unwrap_or(0),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Input {
|
||||||
|
pub fn complete<'a>(&mut self, opt: impl Into<Opt<'a>>) -> bool {
|
||||||
|
let opt = opt.into();
|
||||||
|
if self.ticket != opt.ticket {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
let [before, after] = self.partition();
|
||||||
|
let new = if let Some((prefix, _)) = before.rsplit_once('/') {
|
||||||
|
format!("{prefix}/{}{after}", opt.word)
|
||||||
|
} else {
|
||||||
|
format!("{}{after}", opt.word)
|
||||||
|
};
|
||||||
|
|
||||||
|
let snap = self.snaps.current_mut();
|
||||||
|
if new == snap.value {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
let delta = new.chars().count() as isize - snap.value.chars().count() as isize;
|
||||||
|
snap.value = new;
|
||||||
|
|
||||||
|
self.move_(delta);
|
||||||
|
self.flush_value(true);
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
1
yazi-core/src/input/commands/mod.rs
Normal file
1
yazi-core/src/input/commands/mod.rs
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
mod complete;
|
||||||
|
|
@ -3,17 +3,17 @@ use std::ops::Range;
|
||||||
use crossterm::event::KeyCode;
|
use crossterm::event::KeyCode;
|
||||||
use tokio::sync::mpsc::UnboundedSender;
|
use tokio::sync::mpsc::UnboundedSender;
|
||||||
use unicode_width::UnicodeWidthStr;
|
use unicode_width::UnicodeWidthStr;
|
||||||
use yazi_config::keymap::{Exec, Key, KeymapLayer};
|
use yazi_config::keymap::Key;
|
||||||
use yazi_shared::{CharKind, InputError};
|
use yazi_shared::{CharKind, InputError};
|
||||||
|
|
||||||
use super::{mode::InputMode, op::InputOp, InputOpt, InputSnap, InputSnaps};
|
use super::{mode::InputMode, op::InputOp, InputOpt, InputSnap, InputSnaps};
|
||||||
use crate::{emit, external, Position};
|
use crate::{external, Position};
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct Input {
|
pub struct Input {
|
||||||
snaps: InputSnaps,
|
pub(super) snaps: InputSnaps,
|
||||||
pub ticket: usize,
|
pub ticket: usize,
|
||||||
pub visible: bool,
|
pub visible: bool,
|
||||||
|
|
||||||
pub title: String,
|
pub title: String,
|
||||||
pub position: Position,
|
pub position: Position,
|
||||||
|
|
@ -31,7 +31,6 @@ impl Input {
|
||||||
pub fn show(&mut self, opt: InputOpt, tx: UnboundedSender<Result<String, InputError>>) {
|
pub fn show(&mut self, opt: InputOpt, tx: UnboundedSender<Result<String, InputError>>) {
|
||||||
self.close(false);
|
self.close(false);
|
||||||
self.snaps.reset(opt.value);
|
self.snaps.reset(opt.value);
|
||||||
self.ticket = self.ticket.wrapping_add(1);
|
|
||||||
self.visible = true;
|
self.visible = true;
|
||||||
|
|
||||||
self.title = opt.title;
|
self.title = opt.title;
|
||||||
|
|
@ -52,6 +51,7 @@ impl Input {
|
||||||
_ = cb.send(if submit { Ok(value) } else { Err(InputError::Canceled(value)) });
|
_ = cb.send(if submit { Ok(value) } else { Err(InputError::Canceled(value)) });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.ticket = self.ticket.wrapping_add(1);
|
||||||
self.visible = false;
|
self.visible = false;
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
@ -213,7 +213,7 @@ impl Input {
|
||||||
}
|
}
|
||||||
|
|
||||||
self.move_(s.chars().count() as isize);
|
self.move_(s.chars().count() as isize);
|
||||||
self.flush_value();
|
self.flush_value(false);
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -226,7 +226,7 @@ impl Input {
|
||||||
}
|
}
|
||||||
|
|
||||||
self.move_(-1);
|
self.move_(-1);
|
||||||
self.flush_value();
|
self.flush_value(false);
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -320,26 +320,23 @@ impl Input {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if !matches!(old.op, InputOp::None | InputOp::Select(_)) {
|
if !matches!(old.op, InputOp::None | InputOp::Select(_)) {
|
||||||
self.snaps.tag().then(|| self.flush_value());
|
self.snaps.tag().then(|| self.flush_value(false));
|
||||||
}
|
}
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn flush_value(&mut self) {
|
pub(super) fn flush_value(&mut self, no_complete: bool) {
|
||||||
self.ticket = self.ticket.wrapping_add(1);
|
self.ticket = self.ticket.wrapping_add(1);
|
||||||
|
|
||||||
if self.realtime {
|
if self.realtime {
|
||||||
let value = self.snap().value.clone();
|
let value = self.snap().value.clone();
|
||||||
self.callback.as_ref().unwrap().send(Err(InputError::Typed(value))).ok();
|
self.callback.as_ref().unwrap().send(Err(InputError::Typed(value))).ok();
|
||||||
}
|
}
|
||||||
if self.completion {
|
|
||||||
emit!(Call(
|
if self.completion && !no_complete {
|
||||||
Exec::call("complete", vec![self.partition()[0].to_owned()])
|
let before = self.partition()[0].to_owned();
|
||||||
.with("ticket", self.ticket)
|
self.callback.as_ref().unwrap().send(Err(InputError::Completed(before, self.ticket))).ok();
|
||||||
.vec(),
|
|
||||||
KeymapLayer::Input
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
mod commands;
|
||||||
mod input;
|
mod input;
|
||||||
mod mode;
|
mod mode;
|
||||||
mod op;
|
mod op;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,9 @@
|
||||||
use std::mem;
|
use std::{mem, time::Duration};
|
||||||
|
|
||||||
use yazi_shared::Url;
|
use tokio::pin;
|
||||||
|
use tokio_stream::{wrappers::UnboundedReceiverStream, StreamExt};
|
||||||
|
use yazi_config::keymap::{Exec, KeymapLayer};
|
||||||
|
use yazi_shared::{Debounce, InputError, Url};
|
||||||
|
|
||||||
use crate::{emit, files::{File, FilesOp}, input::InputOpt, tab::Tab};
|
use crate::{emit, files::{File, FilesOp}, input::InputOpt, tab::Tab};
|
||||||
|
|
||||||
|
|
@ -59,12 +62,26 @@ impl Tab {
|
||||||
|
|
||||||
pub fn cd_interactive(&mut self, target: Url) -> bool {
|
pub fn cd_interactive(&mut self, target: Url) -> bool {
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
let mut result = emit!(Input(
|
let rx = emit!(Input(
|
||||||
InputOpt::top("Change directory:").with_value(target.to_string_lossy()).with_completion()
|
InputOpt::top("Change directory:").with_value(target.to_string_lossy()).with_completion()
|
||||||
));
|
));
|
||||||
|
|
||||||
if let Some(Ok(s)) = result.recv().await {
|
let rx = Debounce::new(UnboundedReceiverStream::new(rx), Duration::from_millis(50));
|
||||||
emit!(Cd(Url::from(s.trim())));
|
pin!(rx);
|
||||||
|
|
||||||
|
while let Some(result) = rx.next().await {
|
||||||
|
match result {
|
||||||
|
Ok(s) => {
|
||||||
|
emit!(Cd(Url::from(s.trim())));
|
||||||
|
}
|
||||||
|
Err(InputError::Completed(before, ticket)) => {
|
||||||
|
emit!(Call(
|
||||||
|
Exec::call("complete", vec![before]).with("ticket", ticket).vec(),
|
||||||
|
KeymapLayer::Input
|
||||||
|
));
|
||||||
|
}
|
||||||
|
_ => break,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
false
|
false
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
use ratatui::{buffer::Buffer, layout::Rect, widgets::{Block, BorderType, Borders, Clear, List, ListItem, Widget}};
|
use ratatui::{buffer::Buffer, layout::Rect, widgets::{Block, BorderType, Borders, Clear, List, ListItem, Widget}};
|
||||||
|
use yazi_config::THEME;
|
||||||
use yazi_core::{Ctx, Position};
|
use yazi_core::{Ctx, Position};
|
||||||
|
|
||||||
pub(crate) struct Completion<'a> {
|
pub(crate) struct Completion<'a> {
|
||||||
|
|
@ -11,8 +12,24 @@ impl<'a> Completion<'a> {
|
||||||
|
|
||||||
impl<'a> Widget for Completion<'a> {
|
impl<'a> Widget for Completion<'a> {
|
||||||
fn render(self, rect: Rect, buf: &mut Buffer) {
|
fn render(self, rect: Rect, buf: &mut Buffer) {
|
||||||
let items =
|
let items = self
|
||||||
self.cx.completion.items.iter().map(|x| ListItem::new(x.as_str())).collect::<Vec<_>>();
|
.cx
|
||||||
|
.completion
|
||||||
|
.window()
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(i, x)| {
|
||||||
|
let mut item = ListItem::new(format!(" {} {}", THEME.completion.icon_file, x));
|
||||||
|
|
||||||
|
if i == self.cx.completion.cursor {
|
||||||
|
item = item.style(THEME.completion.active.into());
|
||||||
|
} else {
|
||||||
|
item = item.style(THEME.completion.inactive.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
item
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
let input_area = self.cx.area(&self.cx.input.position);
|
let input_area = self.cx.area(&self.cx.input.position);
|
||||||
let mut area =
|
let mut area =
|
||||||
|
|
@ -27,7 +44,12 @@ impl<'a> Widget for Completion<'a> {
|
||||||
|
|
||||||
Clear.render(area, buf);
|
Clear.render(area, buf);
|
||||||
List::new(items)
|
List::new(items)
|
||||||
.block(Block::new().borders(Borders::ALL).border_type(BorderType::Rounded))
|
.block(
|
||||||
|
Block::new()
|
||||||
|
.borders(Borders::ALL)
|
||||||
|
.border_type(BorderType::Rounded)
|
||||||
|
.border_style(THEME.completion.border.into()),
|
||||||
|
)
|
||||||
.render(area, buf);
|
.render(area, buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -267,7 +267,13 @@ impl<'a> Executor<'a> {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
"complete" => return self.cx.completion.trigger(exec),
|
"complete" => {
|
||||||
|
return if exec.named.contains_key("apply") {
|
||||||
|
self.cx.input.complete(exec)
|
||||||
|
} else {
|
||||||
|
self.cx.completion.trigger(exec)
|
||||||
|
};
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -315,16 +321,9 @@ impl<'a> Executor<'a> {
|
||||||
match exec.cmd.as_str() {
|
match exec.cmd.as_str() {
|
||||||
"trigger" => self.cx.completion.trigger(exec),
|
"trigger" => self.cx.completion.trigger(exec),
|
||||||
"show" => self.cx.completion.show(exec),
|
"show" => self.cx.completion.show(exec),
|
||||||
"close" => self.cx.completion.close(exec.named.contains_key("submit")),
|
"close" => self.cx.completion.close(exec),
|
||||||
|
|
||||||
"arrow" => {
|
"arrow" => self.cx.completion.arrow(exec),
|
||||||
let step: isize = exec.args.first().and_then(|s| s.parse().ok()).unwrap_or(0);
|
|
||||||
if step > 0 {
|
|
||||||
self.cx.completion.next(step as usize)
|
|
||||||
} else {
|
|
||||||
self.cx.completion.prev(step.unsigned_abs())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
"help" => self.cx.help.toggle(KeymapLayer::Completion),
|
"help" => self.cx.help.toggle(KeymapLayer::Completion),
|
||||||
_ => false,
|
_ => false,
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ use std::{error::Error, fmt::{self, Display}};
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum InputError {
|
pub enum InputError {
|
||||||
Typed(String),
|
Typed(String),
|
||||||
|
Completed(String, usize),
|
||||||
Canceled(String),
|
Canceled(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -10,6 +11,7 @@ impl Display for InputError {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
Self::Typed(text) => write!(f, "Typed error: {text}"),
|
Self::Typed(text) => write!(f, "Typed error: {text}"),
|
||||||
|
Self::Completed(text, _) => write!(f, "Completed error: {text}"),
|
||||||
Self::Canceled(text) => write!(f, "Canceled error: {text}"),
|
Self::Canceled(text) => write!(f, "Canceled error: {text}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue