add palette kind symbol

This commit is contained in:
Dongdong Zhou 2023-03-09 20:10:59 +00:00
parent 89f19a2356
commit d0bbeff1f6
6 changed files with 214 additions and 56 deletions

19
Cargo.lock generated
View File

@ -1587,7 +1587,7 @@ dependencies = [
"leptos_reactive",
"once_cell",
"parking_lot 0.12.1",
"parley 0.1.0 (git+https://github.com/lapce/parley?rev=421e5c1eb07d108a9c05da4f021a34f5bd6532cd)",
"parley 0.1.0 (git+https://github.com/lapce/parley?rev=dd30cc9e4ae733d80650ad3ab0db0462ccd67e57)",
"rustc-hash",
"smallvec",
"taffy",
@ -1733,8 +1733,9 @@ dependencies = [
[[package]]
name = "fount"
version = "0.1.0"
source = "git+https://github.com/lapce/fount?rev=0ac37ef400d4048e2dbebe34b1a74f55dab4654d#0ac37ef400d4048e2dbebe34b1a74f55dab4654d"
source = "git+https://github.com/lapce/fount?rev=7952647649c119be454691764c20768330a6e8f2#7952647649c119be454691764c20768330a6e8f2"
dependencies = [
"peniko",
"swash 0.1.6 (git+https://github.com/dfrg/swash)",
]
@ -4201,9 +4202,9 @@ dependencies = [
[[package]]
name = "parley"
version = "0.1.0"
source = "git+https://github.com/lapce/parley?rev=421e5c1eb07d108a9c05da4f021a34f5bd6532cd#421e5c1eb07d108a9c05da4f021a34f5bd6532cd"
source = "git+https://github.com/lapce/parley?rev=dd30cc9e4ae733d80650ad3ab0db0462ccd67e57#dd30cc9e4ae733d80650ad3ab0db0462ccd67e57"
dependencies = [
"fount 0.1.0 (git+https://github.com/lapce/fount?rev=0ac37ef400d4048e2dbebe34b1a74f55dab4654d)",
"fount 0.1.0 (git+https://github.com/lapce/fount?rev=7952647649c119be454691764c20768330a6e8f2)",
"once_cell",
"swash 0.1.6 (git+https://github.com/dfrg/swash)",
]
@ -4257,7 +4258,7 @@ checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099"
[[package]]
name = "peniko"
version = "0.1.0"
source = "git+https://github.com/linebender/peniko?rev=8cb710f#8cb710ffcb0f04fa24648440f9b9fb038174a341"
source = "git+https://github.com/linebender/peniko?rev=cafdac9a211a0fb2fec5656bd663d1ac770bcc81#cafdac9a211a0fb2fec5656bd663d1ac770bcc81"
dependencies = [
"kurbo 0.9.0",
"smallvec",
@ -6575,8 +6576,8 @@ checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
[[package]]
name = "vello"
version = "0.1.0"
source = "git+https://github.com/linebender/vello#020a7f5c016ab5c572cefbe169f19082a0e34ffe"
version = "0.0.1"
source = "git+https://github.com/linebender/vello?rev=2f268d4e0f8596c2c05f4982ddc558e1cae0ffa2#2f268d4e0f8596c2c05f4982ddc558e1cae0ffa2"
dependencies = [
"bytemuck",
"futures-intrusive",
@ -6590,8 +6591,8 @@ dependencies = [
[[package]]
name = "vello_svg"
version = "0.1.0"
source = "git+https://github.com/linebender/vello#020a7f5c016ab5c572cefbe169f19082a0e34ffe"
version = "0.0.1"
source = "git+https://github.com/linebender/vello?rev=2f268d4e0f8596c2c05f4982ddc558e1cae0ffa2#2f268d4e0f8596c2c05f4982ddc558e1cae0ffa2"
dependencies = [
"usvg 0.28.0",
"vello",

View File

@ -1503,6 +1503,7 @@ fn palette_content(cx: AppContext, window_tab_data: WindowTabData) -> impl View
let index = window_tab_data.palette.index.read_only();
let config = window_tab_data.palette.config;
let run_id = window_tab_data.palette.run_id;
let input = window_tab_data.palette.input.read_only();
let palette_item_height = 24.0;
container(cx, |cx| {
scroll(cx, |cx| {
@ -1510,7 +1511,9 @@ fn palette_content(cx: AppContext, window_tab_data: WindowTabData) -> impl View
cx,
VirtualListDirection::Vertical,
move || PaletteItems(items.get()),
move |(i, _item)| (run_id.get_untracked(), *i),
move |(i, _item)| {
(run_id.get_untracked(), *i, input.get_untracked().input)
},
move |cx, (i, item)| {
palette_item(cx, i, item, index, palette_item_height, config)
},
@ -1636,15 +1639,14 @@ fn completion(cx: AppContext, window_tab_data: WindowTabData) -> impl View {
let completion_data = window_tab_data.completion;
let config = window_tab_data.config;
let active = completion_data.with_untracked(|c| c.active);
let request_id = create_memo(cx.scope, move |_| {
completion_data.with(|c| (c.request_id, c.input_id))
});
let request_id =
move || completion_data.with_untracked(|c| (c.request_id, c.input_id));
scroll(cx, move |cx| {
virtual_list(
cx,
VirtualListDirection::Vertical,
move || completion_data.with(|c| VectorItems(c.filtered_items.clone())),
move |(i, item)| (request_id.get_untracked(), *i),
move |(i, item)| (request_id(), *i),
move |cx, (i, item)| {
stack(cx, |cx| {
(

View File

@ -75,7 +75,6 @@ pub fn receive(
return;
}
println!("receive completion");
let items = match resp {
CompletionResponse::Array(items) => items,
CompletionResponse::List(list) => &list.items,

View File

@ -282,7 +282,6 @@ fn run_focus_command(
}
}
FocusCommand::SplitExchange => {
println!("split exchage");
if let Some(editor_tab_id) = self.editor_tab_id {
self.internal_command
.set(Some(InternalCommand::SplitExchange { editor_tab_id }));
@ -575,7 +574,6 @@ fn update_completion(&self, display_if_empty_input: bool) {
});
return;
}
println!("offset {offset} start offset {start_offset} input {input}");
if self.completion.with_untracked(|completion| {
completion.status != CompletionStatus::Inactive
@ -608,7 +606,6 @@ fn update_completion(&self, display_if_empty_input: bool) {
}
self.completion.update(|completion| {
println!("new completion");
completion.path = path.clone();
completion.offset = start_offset;
completion.input = input.clone();
@ -689,7 +686,6 @@ fn apply_completion_item(&self, item: &CompletionItem) -> Result<()> {
&selection,
additional_edit,
start_offset,
edit_start,
)?;
return Ok(());
}
@ -725,7 +721,6 @@ fn completion_apply_snippet(
selection: &Selection,
additional_edit: Vec<(Selection, &str)>,
start_offset: usize,
edit_start: usize,
) -> Result<()> {
let snippet = Snippet::from_str(snippet)?;
let text = snippet.text();
@ -747,13 +742,6 @@ fn completion_apply_snippet(
let selection = selection.apply_delta(&delta, true, InsertDrift::Default);
let start_offset = additional_edit
.iter()
.map(|(selection, _)| selection.min_offset())
.min()
.map(|offset| offset.min(start_offset).min(edit_start))
.unwrap_or(start_offset);
let mut transformer = Transformer::new(&delta);
let offset = transformer.transform(start_offset, false);
let snippet_tabs = snippet.tabs(offset);

View File

@ -62,19 +62,32 @@ pub enum PaletteStatus {
Done,
}
#[derive(Clone, Debug)]
pub struct PaletteInput {
pub input: String,
pub kind: PaletteKind,
}
impl PaletteInput {
pub fn update_input(&mut self, input: String) {
self.kind = self.kind.get_palette_kind(&input);
self.input = self.kind.get_input(&input).to_string();
}
}
#[derive(Clone)]
pub struct PaletteData {
run_id_counter: Arc<AtomicU64>,
run_tx: Sender<(u64, String, im::Vector<PaletteItem>)>,
internal_command: WriteSignal<Option<InternalCommand>>,
pub run_id: ReadSignal<u64>,
pub run_id: RwSignal<u64>,
pub workspace: Arc<LapceWorkspace>,
pub status: RwSignal<PaletteStatus>,
pub index: RwSignal<usize>,
pub kind: RwSignal<PaletteKind>,
pub items: RwSignal<im::Vector<PaletteItem>>,
pub filtered_items: ReadSignal<im::Vector<PaletteItem>>,
pub proxy_rpc: ProxyRpcHandler,
pub input: RwSignal<PaletteInput>,
pub editor: EditorData,
pub focus: RwSignal<Focus>,
pub keypress: ReadSignal<KeyPressData>,
@ -95,9 +108,15 @@ pub fn new(
config: ReadSignal<Arc<LapceConfig>>,
) -> Self {
let status = create_rw_signal(cx.scope, PaletteStatus::Inactive);
let kind = create_rw_signal(cx.scope, PaletteKind::File);
let items = create_rw_signal(cx.scope, im::Vector::new());
let index = create_rw_signal(cx.scope, 0);
let input = create_rw_signal(
cx.scope,
PaletteInput {
input: "".to_string(),
kind: PaletteKind::File,
},
);
let editor = EditorData::new_local(
cx,
EditorId::next(),
@ -107,19 +126,43 @@ pub fn new(
proxy_rpc.clone(),
config,
);
let run_id = create_rw_signal(cx.scope, 0);
let run_id_counter = Arc::new(AtomicU64::new(0));
let (run_tx, run_rx) = crossbeam_channel::unbounded();
{
let run_id = run_id_counter.clone();
let doc = editor.doc.read_only();
let run_id = run_id.read_only();
let input = input.read_only();
let items = items.read_only();
let tx = run_tx.clone();
create_effect(cx.scope, move |_| {
let run_id = run_id.fetch_add(1, Ordering::Relaxed) + 1;
let input = doc.with(|doc| doc.buffer().text().to_string());
let items = items.get();
let _ = tx.send((run_id, input, items));
{
let tx = tx.clone();
// this effect only monitors items change
create_effect(cx.scope, move |_| {
let items = items.get();
println!("filter items when items change");
let input = input.get_untracked();
let run_id = run_id.get_untracked();
let _ = tx.send((run_id, input.input, items));
});
}
// this effect only monitors input change
create_effect(cx.scope, move |last_kind| {
let input = input.get();
println!("new input {input:?}");
let kind = input.kind;
if last_kind != Some(kind) {
println!("got new kind {kind:?}");
return kind;
}
println!("filter items when input change");
let items = items.get_untracked();
let run_id = run_id.get_untracked();
let _ = tx.send((run_id, input.input, items));
kind
});
}
@ -131,20 +174,18 @@ pub fn new(
});
}
let (run_id, set_run_id) = create_signal(cx.scope, 0);
let (filtered_items, set_filtered_items) =
create_signal(cx.scope, im::Vector::new());
{
let resp = create_signal_from_channel(cx, resp_rx);
let run_id = run_id_counter.clone();
let run_id = run_id.read_only();
let input = input.read_only();
let index = index.write_only();
create_effect(cx.scope, move |_| {
if let Some((current_run_id, items)) = resp.get() {
if run_id.load(std::sync::atomic::Ordering::Acquire)
== current_run_id
if let Some((filter_run_id, filter_input, items)) = resp.get() {
if run_id.get_untracked() == filter_run_id
&& input.get_untracked().input == filter_input
{
set_run_id.set(current_run_id);
set_filtered_items.set(items);
index.set(0);
}
@ -152,7 +193,7 @@ pub fn new(
});
}
Self {
let palette = Self {
run_id_counter,
run_tx,
internal_command,
@ -160,26 +201,80 @@ pub fn new(
focus,
workspace,
status,
kind,
index,
items,
filtered_items,
editor,
input,
proxy_rpc,
keypress,
config,
executed_commands: Rc::new(RefCell::new(HashMap::new())),
};
{
let palette = palette.clone();
let doc = palette.editor.doc.read_only();
let input = palette.input.write_only();
let status = palette.status.read_only();
// this effect monitors the document change in the palette input editor
create_effect(cx.scope, move |last_input| {
let new_input = doc.with(|doc| doc.buffer().text().to_string());
let status = status.get_untracked();
if status == PaletteStatus::Inactive {
// If the status is inactive, we set the input to None,
// so that when we actually run the palette, the input
// can be compared with this None.
return None;
}
let last_input_is_none = !matches!(last_input, Some(Some(_)));
let changed = match last_input {
None => true,
Some(last_input) => {
Some(new_input.as_str()) != last_input.as_deref()
}
};
if changed {
let new_kind = input
.update_returning(|input| {
let kind = input.kind;
input.update_input(new_input.clone());
if last_input_is_none || kind != input.kind {
Some(input.kind)
} else {
None
}
})
.unwrap();
if let Some(new_kind) = new_kind {
palette.run_inner(cx, new_kind);
}
}
Some(new_input)
});
}
palette
}
pub fn run(&self, cx: AppContext, kind: PaletteKind) {
self.status.set(PaletteStatus::Started);
let symbol = kind.symbol();
self.editor
.doc
.update(|doc| doc.reload(Rope::from(""), true));
.update(|doc| doc.reload(Rope::from(symbol), true));
self.editor
.cursor
.update(|cursor| cursor.set_insert(Selection::caret(0)));
.update(|cursor| cursor.set_insert(Selection::caret(symbol.len())));
}
fn run_inner(&self, cx: AppContext, kind: PaletteKind) {
println!("palette run inner");
let run_id = self.run_id_counter.fetch_add(1, Ordering::Relaxed) + 1;
self.run_id.set(run_id);
match kind {
PaletteKind::File => {
self.get_files(cx);
@ -188,7 +283,6 @@ pub fn run(&self, cx: AppContext, kind: PaletteKind) {
self.get_commands(cx);
}
}
self.kind.set(kind);
}
fn get_files(&self, cx: AppContext) {
@ -299,13 +393,13 @@ fn select(&self, cx: AppContext) {
fn cancel(&self, cx: AppContext) {
self.status.set(PaletteStatus::Inactive);
self.focus.set(Focus::Workbench);
self.items.update(|items| items.clear());
self.editor
.doc
.update(|doc| doc.reload(Rope::from(""), true));
self.editor
.cursor
.update(|cursor| cursor.set_insert(Selection::caret(0)));
self.items.update(|items| items.clear());
}
fn next(&self) {
@ -384,9 +478,11 @@ fn filter_items(
}
filtered_items.sort_by(|a, b| {
b.score
.partial_cmp(&a.score)
.unwrap_or(std::cmp::Ordering::Less)
let order = b.score.cmp(&a.score);
match order {
std::cmp::Ordering::Equal => a.filter_text.cmp(&b.filter_text),
_ => order,
}
});
if run_id.load(std::sync::atomic::Ordering::Acquire) != current_run_id {
@ -398,7 +494,7 @@ fn filter_items(
fn update_process(
run_id: Arc<AtomicU64>,
receiver: Receiver<(u64, String, im::Vector<PaletteItem>)>,
resp_tx: Sender<(u64, im::Vector<PaletteItem>)>,
resp_tx: Sender<(u64, String, im::Vector<PaletteItem>)>,
) {
fn receive_batch(
receiver: &Receiver<(u64, String, im::Vector<PaletteItem>)>,
@ -428,7 +524,7 @@ fn receive_batch(
items,
&matcher,
) {
let _ = resp_tx.send((current_run_id, filtered_items));
let _ = resp_tx.send((current_run_id, input, filtered_items));
}
} else {
return;

View File

@ -1,5 +1,77 @@
#[derive(Clone, Debug, PartialEq, Eq)]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum PaletteKind {
File,
Command,
}
impl PaletteKind {
pub fn symbol(&self) -> &'static str {
match &self {
// PaletteKind::Line => "/",
// PaletteKind::DocumentSymbol => "@",
// PaletteKind::WorkspaceSymbol => "#",
// PaletteKind::GlobalSearch => "?",
// PaletteKind::Workspace => ">",
PaletteKind::Command => ":",
PaletteKind::File
// | PaletteKind::Reference
// | PaletteKind::ColorTheme
// | PaletteKind::IconTheme
// | PaletteKind::SshHost
// | PaletteKind::RunAndDebug
// | PaletteKind::Language
=> "",
}
}
pub fn from_input(input: &str) -> PaletteKind {
match input {
// _ if input.starts_with('/') => PaletteKind::Line,
// _ if input.starts_with('@') => PaletteKind::DocumentSymbol,
// _ if input.starts_with('#') => PaletteKind::WorkspaceSymbol,
// _ if input.starts_with('>') => PaletteKind::Workspace,
_ if input.starts_with(':') => PaletteKind::Command,
_ => PaletteKind::File,
}
}
// pub fn has_preview(&self) -> bool {
// matches!(
// self,
// PaletteType::Line
// | PaletteType::DocumentSymbol
// | PaletteType::WorkspaceSymbol
// | PaletteType::GlobalSearch
// | PaletteType::Reference
// )
// }
pub fn get_input<'a>(&self, input: &'a str) -> &'a str {
match self {
PaletteKind::File
// | PaletteKind::Reference
// | PaletteKind::ColorTheme
// | PaletteKind::IconTheme
// | PaletteKind::Language
// | PaletteKind::RunAndDebug
// | PaletteKind::SshHost
=> input,
PaletteKind::Command
// | PaletteType::DocumentSymbol
// | PaletteType::WorkspaceSymbol
// | PaletteType::Workspace
// | PaletteType::Line
// | PaletteType::GlobalSearch
=> if !input.is_empty() {&input[1..]} else {input},
}
}
/// Get the palette kind that it should be considered as based on the current
/// [`PaletteKind`] and the current input.
pub fn get_palette_kind(&self, input: &str) -> PaletteKind {
if self != &PaletteKind::File && self.symbol() == "" {
return self.clone();
}
PaletteKind::from_input(input)
}
}