Compare commits
1 Commits
debug-view
...
vim-global
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d8d8f90893 |
1
Cargo.lock
generated
1
Cargo.lock
generated
@@ -14538,6 +14538,7 @@ dependencies = [
|
|||||||
"collections",
|
"collections",
|
||||||
"command_palette",
|
"command_palette",
|
||||||
"command_palette_hooks",
|
"command_palette_hooks",
|
||||||
|
"db",
|
||||||
"editor",
|
"editor",
|
||||||
"futures 0.3.31",
|
"futures 0.3.31",
|
||||||
"git_ui",
|
"git_ui",
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ async-trait = { workspace = true, "optional" = true }
|
|||||||
collections.workspace = true
|
collections.workspace = true
|
||||||
command_palette.workspace = true
|
command_palette.workspace = true
|
||||||
command_palette_hooks.workspace = true
|
command_palette_hooks.workspace = true
|
||||||
|
db.workspace = true
|
||||||
editor.workspace = true
|
editor.workspace = true
|
||||||
futures.workspace = true
|
futures.workspace = true
|
||||||
gpui.workspace = true
|
gpui.workspace = true
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ impl Vim {
|
|||||||
}) else {
|
}) else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
self.marks.insert(text.to_string(), anchors);
|
self.set_mark(text.to_string(), anchors);
|
||||||
self.clear_operator(window, cx);
|
self.clear_operator(window, cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,8 +71,8 @@ impl Vim {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
self.marks.insert("<".to_string(), starts);
|
self.set_mark("<".to_string(), starts);
|
||||||
self.marks.insert(">".to_string(), ends);
|
self.set_mark(">".to_string(), ends);
|
||||||
self.stored_visual_mode.replace((mode, reversed));
|
self.stored_visual_mode.replace((mode, reversed));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -131,14 +131,14 @@ impl Vim {
|
|||||||
let mut clipboard_selections = Vec::with_capacity(selections.len());
|
let mut clipboard_selections = Vec::with_capacity(selections.len());
|
||||||
let mut ranges_to_highlight = Vec::new();
|
let mut ranges_to_highlight = Vec::new();
|
||||||
|
|
||||||
self.marks.insert(
|
self.set_mark(
|
||||||
"[".to_string(),
|
"[".to_string(),
|
||||||
selections
|
selections
|
||||||
.iter()
|
.iter()
|
||||||
.map(|s| buffer.anchor_before(s.start))
|
.map(|s| buffer.anchor_before(s.start))
|
||||||
.collect(),
|
.collect(),
|
||||||
);
|
);
|
||||||
self.marks.insert(
|
self.set_mark(
|
||||||
"]".to_string(),
|
"]".to_string(),
|
||||||
selections
|
selections
|
||||||
.iter()
|
.iter()
|
||||||
|
|||||||
@@ -5,18 +5,25 @@ use crate::{motion::Motion, object::Object};
|
|||||||
use crate::{UseSystemClipboard, Vim, VimSettings};
|
use crate::{UseSystemClipboard, Vim, VimSettings};
|
||||||
use collections::HashMap;
|
use collections::HashMap;
|
||||||
use command_palette_hooks::{CommandPaletteFilter, CommandPaletteInterceptor};
|
use command_palette_hooks::{CommandPaletteFilter, CommandPaletteInterceptor};
|
||||||
|
use db::sqlez_macros::sql;
|
||||||
|
use db::{define_connection, query};
|
||||||
use editor::{Anchor, ClipboardSelection, Editor};
|
use editor::{Anchor, ClipboardSelection, Editor};
|
||||||
use gpui::{
|
use gpui::{
|
||||||
Action, App, BorrowAppContext, ClipboardEntry, ClipboardItem, Entity, Global, WeakEntity,
|
Action, App, BorrowAppContext, ClipboardEntry, ClipboardItem, Entity, Global, WeakEntity,
|
||||||
};
|
};
|
||||||
use language::Point;
|
use language::{BufferId, Point};
|
||||||
use schemars::JsonSchema;
|
use schemars::JsonSchema;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use settings::{Settings, SettingsStore};
|
use settings::{Settings, SettingsStore};
|
||||||
use std::borrow::BorrowMut;
|
use std::borrow::BorrowMut;
|
||||||
|
use std::ffi::OsString;
|
||||||
|
use std::os::unix::ffi::OsStringExt;
|
||||||
|
use std::path::{Path, PathBuf};
|
||||||
use std::{fmt::Display, ops::Range, sync::Arc};
|
use std::{fmt::Display, ops::Range, sync::Arc};
|
||||||
use ui::{Context, SharedString};
|
use ui::{Context, SharedString};
|
||||||
|
use util::ResultExt;
|
||||||
use workspace::searchable::Direction;
|
use workspace::searchable::Direction;
|
||||||
|
use workspace::{Workspace, WorkspaceDb, WorkspaceId};
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Deserialize, JsonSchema, Serialize)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Deserialize, JsonSchema, Serialize)]
|
||||||
pub enum Mode {
|
pub enum Mode {
|
||||||
@@ -172,7 +179,7 @@ impl From<String> for Register {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Clone)]
|
#[derive(Default)]
|
||||||
pub struct VimGlobals {
|
pub struct VimGlobals {
|
||||||
pub last_find: Option<Motion>,
|
pub last_find: Option<Motion>,
|
||||||
|
|
||||||
@@ -201,6 +208,15 @@ pub struct VimGlobals {
|
|||||||
pub recordings: HashMap<char, Vec<ReplayableAction>>,
|
pub recordings: HashMap<char, Vec<ReplayableAction>>,
|
||||||
|
|
||||||
pub focused_vim: Option<WeakEntity<Vim>>,
|
pub focused_vim: Option<WeakEntity<Vim>>,
|
||||||
|
|
||||||
|
pub local_marks: HashMap<(WorkspaceId, Arc<Path>), HashMap<String, Vec<Point>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
// when you open a buffer, read from the local marks and convert to anchor
|
||||||
|
// when you create a mark, or edit a buffer such that an anchor's point changes, write that to the database
|
||||||
|
pub struct MarksCollection {
|
||||||
|
pub local_loaded: HashMap<BufferId, HashMap<String, Vec<Anchor>>>, // keep this type on non-global-vim
|
||||||
|
pub local: HashMap<Arc<Path>, HashMap<String, Vec<Point>>>,
|
||||||
}
|
}
|
||||||
impl Global for VimGlobals {}
|
impl Global for VimGlobals {}
|
||||||
|
|
||||||
@@ -235,6 +251,22 @@ impl VimGlobals {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
.detach();
|
.detach();
|
||||||
|
cx.observe_new(|workspace: &mut Workspace, _, cx| {
|
||||||
|
let Some(workspace_id) = workspace.database_id() else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
cx.spawn(|this, mut cx| async move {
|
||||||
|
let marks = cx
|
||||||
|
.background_executor()
|
||||||
|
.spawn(async move { DB.get_local_marks(workspace_id) })
|
||||||
|
.await?;
|
||||||
|
cx.update_global(|g: &mut VimGlobals, cx: &mut App| {
|
||||||
|
g.load_local_marks(workspace_id, marks, cx)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.detach_and_log_err(cx)
|
||||||
|
})
|
||||||
|
.detach()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn write_registers(
|
pub(crate) fn write_registers(
|
||||||
@@ -362,6 +394,29 @@ impl VimGlobals {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn load_local_marks(
|
||||||
|
&mut self,
|
||||||
|
workspace_id: WorkspaceId,
|
||||||
|
marks: Vec<(Vec<u8>, String, String)>,
|
||||||
|
cx: &mut App,
|
||||||
|
) {
|
||||||
|
for (abs_path, name, values) in marks {
|
||||||
|
let Some(value) = serde_json::from_str::<Vec<(u32, u32)>>(&values).log_err() else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
let path = PathBuf::from(OsString::from_vec(abs_path));
|
||||||
|
let mut marks = self
|
||||||
|
.local_marks
|
||||||
|
.entry((workspace_id, Arc::from(path)))
|
||||||
|
.or_default();
|
||||||
|
let points = value
|
||||||
|
.into_iter()
|
||||||
|
.map(|(row, col)| Point::new(row, col))
|
||||||
|
.collect();
|
||||||
|
marks.insert(name, points);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn system_clipboard_is_newer(&self, cx: &mut Context<Editor>) -> bool {
|
fn system_clipboard_is_newer(&self, cx: &mut Context<Editor>) -> bool {
|
||||||
cx.read_from_clipboard().is_some_and(|item| {
|
cx.read_from_clipboard().is_some_and(|item| {
|
||||||
if let Some(last_state) = &self.last_yank {
|
if let Some(last_state) = &self.last_yank {
|
||||||
@@ -558,3 +613,45 @@ impl Operator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
define_connection! {
|
||||||
|
pub static ref DB: VimDb<WorkspaceDb> = &[
|
||||||
|
sql! (
|
||||||
|
CREATE TABLE vim_local_marks(
|
||||||
|
workspace_id INTEGER,
|
||||||
|
mark_name TEXT,
|
||||||
|
absolute_path BLOB,
|
||||||
|
value TEXT
|
||||||
|
);
|
||||||
|
CREATE UNIQUE INDEX idx_vim_local_marks
|
||||||
|
ON vim_local_marks (workspace_id, mark_name, absolute_path);
|
||||||
|
|
||||||
|
),
|
||||||
|
sql! (
|
||||||
|
CREATE TABLE vim_global_marks(
|
||||||
|
workspace_id INTEGER,
|
||||||
|
mark_name TEXT,
|
||||||
|
absolute_path BLOB,
|
||||||
|
value TEXT
|
||||||
|
);
|
||||||
|
CREATE UNIQUE INDEX idx_vim_global_marks
|
||||||
|
ON vim_global_marks (workspace_id, mark_name);
|
||||||
|
),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
impl VimDb {
|
||||||
|
query! {
|
||||||
|
pub fn set_local_mark(workspace_id: WorkspaceId, mark_name: String, absolute_path: Vec<u8>, value: String) -> Result<Vec<(PathBuf, bool)>> {
|
||||||
|
INSERT OR REPLACE INTO vim_local_marks (workspace_id, mark_name, absolute_path, value)
|
||||||
|
VALUES (?, ?, ?, ?)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
query! {
|
||||||
|
pub fn get_local_marks(workspace_id: WorkspaceId) -> Result<Vec<(Vec<u8>, String, String)>> {
|
||||||
|
SELECT absolute_path, mark_name, value FROM vim_local_marks
|
||||||
|
WHERE workspace_id = ?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ use anyhow::Result;
|
|||||||
use collections::HashMap;
|
use collections::HashMap;
|
||||||
use editor::{
|
use editor::{
|
||||||
movement::{self, FindRange},
|
movement::{self, FindRange},
|
||||||
Anchor, Bias, Editor, EditorEvent, EditorMode, ToPoint,
|
Anchor, Bias, Editor, EditorEvent, EditorMode, MultiBuffer, ToPoint,
|
||||||
};
|
};
|
||||||
use gpui::{
|
use gpui::{
|
||||||
actions, impl_actions, Action, App, AppContext as _, Axis, Context, Entity, EventEmitter,
|
actions, impl_actions, Action, App, AppContext as _, Axis, Context, Entity, EventEmitter,
|
||||||
@@ -38,7 +38,7 @@ use schemars::JsonSchema;
|
|||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde_derive::Serialize;
|
use serde_derive::Serialize;
|
||||||
use settings::{update_settings_file, Settings, SettingsSources, SettingsStore};
|
use settings::{update_settings_file, Settings, SettingsSources, SettingsStore};
|
||||||
use state::{Mode, Operator, RecordedSelection, SearchState, VimGlobals};
|
use state::{Mode, Operator, RecordedSelection, SearchState, VimDb, VimGlobals};
|
||||||
use std::{mem, ops::Range, sync::Arc};
|
use std::{mem, ops::Range, sync::Arc};
|
||||||
use surrounds::SurroundsType;
|
use surrounds::SurroundsType;
|
||||||
use theme::ThemeSettings;
|
use theme::ThemeSettings;
|
||||||
@@ -457,6 +457,17 @@ impl Vim {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_mark(&mut self, name: String, positions: Vec<Anchor>) {
|
||||||
|
match name.to_string() {
|
||||||
|
m if m.starts_with(|c: char| c.is_uppercase()) => {
|
||||||
|
// VimGlobals::set_mark(m, positions);
|
||||||
|
} // global mark
|
||||||
|
m => {
|
||||||
|
let _ = self.marks.insert(m, positions);
|
||||||
|
} // local mark
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
fn handle_editor_event(
|
fn handle_editor_event(
|
||||||
&mut self,
|
&mut self,
|
||||||
event: &EditorEvent,
|
event: &EditorEvent,
|
||||||
|
|||||||
Reference in New Issue
Block a user