Simple replace implementation
This commit is contained in:
parent
133b8ca667
commit
dd459efe06
6 changed files with 120 additions and 4 deletions
|
|
@ -37,6 +37,8 @@ impl IconCache {
|
|||
bundle!("go-up-symbolic", 16);
|
||||
bundle!("list-add-symbolic", 16);
|
||||
bundle!("object-select-symbolic", 16);
|
||||
bundle!("replace-symbolic", 16);
|
||||
bundle!("replace-all-symbolic", 16);
|
||||
bundle!("window-close-symbolic", 16);
|
||||
|
||||
Self { cache }
|
||||
|
|
|
|||
71
src/main.rs
71
src/main.rs
|
|
@ -184,6 +184,8 @@ pub enum Message {
|
|||
Find(Option<bool>),
|
||||
FindNext,
|
||||
FindPrevious,
|
||||
FindReplace,
|
||||
FindReplaceAll,
|
||||
FindReplaceValueChanged(String),
|
||||
FindSearchValueChanged(String),
|
||||
GitProjectStatus(Vec<(String, PathBuf, Vec<GitStatus>)>),
|
||||
|
|
@ -267,6 +269,7 @@ pub struct App {
|
|||
context_page: ContextPage,
|
||||
text_box_id: widget::Id,
|
||||
find_opt: Option<bool>,
|
||||
find_replace_id: widget::Id,
|
||||
find_replace_value: String,
|
||||
find_search_id: widget::Id,
|
||||
find_search_value: String,
|
||||
|
|
@ -976,6 +979,7 @@ impl Application for App {
|
|||
context_page: ContextPage::Settings,
|
||||
text_box_id: widget::Id::unique(),
|
||||
find_opt: None,
|
||||
find_replace_id: widget::Id::unique(),
|
||||
find_replace_value: String::new(),
|
||||
find_search_id: widget::Id::unique(),
|
||||
find_search_value: String::new(),
|
||||
|
|
@ -1242,6 +1246,22 @@ impl Application for App {
|
|||
// Focus correct input
|
||||
return self.update_focus();
|
||||
}
|
||||
Message::FindReplace => {
|
||||
if !self.find_search_value.is_empty() {
|
||||
if let Some(Tab::Editor(tab)) = self.active_tab() {
|
||||
tab.replace(&self.find_search_value, &self.find_replace_value);
|
||||
}
|
||||
}
|
||||
|
||||
// Focus correct input
|
||||
return self.update_focus();
|
||||
}
|
||||
Message::FindReplaceAll => {
|
||||
log::warn!("FIND REPLACE ALL");
|
||||
|
||||
// Focus correct input
|
||||
return self.update_focus();
|
||||
}
|
||||
Message::FindReplaceValueChanged(value) => {
|
||||
self.find_replace_value = value;
|
||||
}
|
||||
|
|
@ -1876,7 +1896,7 @@ impl Application for App {
|
|||
}
|
||||
|
||||
if let Some(replace) = &self.find_opt {
|
||||
let text_input =
|
||||
let find_input =
|
||||
widget::text_input::text_input(fl!("find-placeholder"), &self.find_search_value)
|
||||
.id(self.find_search_id.clone())
|
||||
.on_input(Message::FindSearchValueChanged)
|
||||
|
|
@ -1890,7 +1910,7 @@ impl Application for App {
|
|||
.into(),
|
||||
);
|
||||
let find_widget = widget::row::with_children(vec![
|
||||
text_input.into(),
|
||||
find_input.into(),
|
||||
widget::tooltip(
|
||||
button(icon_cache_get("go-up-symbolic", 16))
|
||||
.on_press(Message::FindPrevious)
|
||||
|
|
@ -1920,9 +1940,52 @@ impl Application for App {
|
|||
.padding(space_xxs)
|
||||
.spacing(space_xxs);
|
||||
|
||||
let mut column = widget::column::with_capacity(2).push(find_widget);
|
||||
if *replace {
|
||||
let replace_input = widget::text_input::text_input(
|
||||
fl!("replace-placeholder"),
|
||||
&self.find_replace_value,
|
||||
)
|
||||
.id(self.find_replace_id.clone())
|
||||
.on_input(Message::FindReplaceValueChanged)
|
||||
.on_submit(Message::FindReplace)
|
||||
.width(Length::Fixed(320.0))
|
||||
.trailing_icon(
|
||||
button(icon_cache_get("edit-clear-symbolic", 16))
|
||||
.on_press(Message::FindReplaceValueChanged(String::new()))
|
||||
.style(style::Button::Icon)
|
||||
.into(),
|
||||
);
|
||||
let replace_widget = widget::row::with_children(vec![
|
||||
replace_input.into(),
|
||||
widget::tooltip(
|
||||
button(icon_cache_get("replace-symbolic", 16))
|
||||
.on_press(Message::FindReplace)
|
||||
.padding(space_xxs)
|
||||
.style(style::Button::Icon),
|
||||
fl!("replace"),
|
||||
widget::tooltip::Position::Top,
|
||||
)
|
||||
.into(),
|
||||
widget::tooltip(
|
||||
button(icon_cache_get("replace-all-symbolic", 16))
|
||||
.on_press(Message::FindReplaceAll)
|
||||
.padding(space_xxs)
|
||||
.style(style::Button::Icon),
|
||||
fl!("replace-all"),
|
||||
widget::tooltip::Position::Top,
|
||||
)
|
||||
.into(),
|
||||
])
|
||||
.align_items(Alignment::Center)
|
||||
.padding(space_xxs)
|
||||
.spacing(space_xxs);
|
||||
|
||||
column = column.push(replace_widget);
|
||||
}
|
||||
|
||||
tab_column = tab_column.push(
|
||||
widget::cosmic_container::container(find_widget)
|
||||
.layer(cosmic_theme::Layer::Primary),
|
||||
widget::cosmic_container::container(column).layer(cosmic_theme::Layer::Primary),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
36
src/tab.rs
36
src/tab.rs
|
|
@ -200,6 +200,42 @@ impl EditorTab {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn replace(&self, value: &str, replace: &str) -> bool {
|
||||
let mut editor = self.editor.lock().unwrap();
|
||||
let mut cursor = editor.cursor();
|
||||
let start_line = cursor.line;
|
||||
while cursor.line < editor.with_buffer(|buffer| buffer.lines.len()) {
|
||||
if let Some(index) = editor.with_buffer(|buffer| {
|
||||
buffer.lines[cursor.line]
|
||||
.text()
|
||||
.match_indices(value)
|
||||
.filter_map(|(i, _)| {
|
||||
if cursor.line != start_line || i >= cursor.index {
|
||||
Some(i)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.next()
|
||||
}) {
|
||||
cursor.index = index;
|
||||
let mut end = cursor;
|
||||
end.index = index + value.len();
|
||||
|
||||
editor.start_change();
|
||||
editor.delete_range(cursor, end);
|
||||
cursor = editor.insert_at(cursor, replace, None);
|
||||
editor.set_cursor(cursor);
|
||||
editor.finish_change();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
cursor.line += 1;
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
// Code adapted from cosmic-text ViEditor search
|
||||
pub fn search(&self, value: &str, forwards: bool) -> bool {
|
||||
let mut editor = self.editor.lock().unwrap();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue