Simple replace implementation

This commit is contained in:
Jeremy Soller 2024-01-09 13:37:10 -07:00
parent 133b8ca667
commit dd459efe06
No known key found for this signature in database
GPG key ID: DCFCA852D3906975
6 changed files with 120 additions and 4 deletions

View file

@ -41,6 +41,9 @@ enable-vim-bindings = Enable Vim bindings
find-placeholder = Find...
find-previous = Find previous
find-next = Find next
replace-placeholder = Replace...
replace = Replace
replace-all = Replace all
# Menu

View file

@ -0,0 +1,7 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M7.70892 2.29365C7.52159 2.10591 7.26735 2.00028 7.00213 2C6.17371 1.99912 5.5 2 5 2C4 2 3.00004 3.00107 3 4C2.99998 4.5 2.99851 5.56725 2.99805 5.99894L0.998047 5.99681L3.99379 10L6.99804 6.0032L4.99804 6.00107C4.99835 5.71751 4.9987 5.52735 4.99804 5C4.99739 4.47265 5.47193 4 6.00049 4C6.50049 4 6.54487 3.99952 7 4C7.26522 4.00028 7.51968 3.8952 7.70742 3.70786C7.89515 3.52052 8.00078 3.26628 8.00106 3.00107C8.00135 2.73585 7.89626 2.48138 7.70892 2.29365Z" fill="#232323"/>
<rect x="9" y="1" width="6" height="4" rx="0.5" fill="#232323"/>
<rect x="4" y="11" width="6" height="4" rx="0.5" fill="#232323"/>
<path opacity="0.67" fill-rule="evenodd" clip-rule="evenodd" d="M6.5 9C6.22386 9 6 9.22386 6 9.5V10H10.5C10.7761 10 11 10.2239 11 10.5V13H11.5C11.7761 13 12 12.7761 12 12.5V9.5C12 9.22386 11.7761 9 11.5 9H6.5Z" fill="#232323"/>
<path opacity="0.33" fill-rule="evenodd" clip-rule="evenodd" d="M8.5 7C8.22386 7 8 7.22386 8 7.5V8H12.5C12.7761 8 13 8.22386 13 8.5V11H13.5C13.7761 11 14 10.7761 14 10.5V7.5C14 7.22386 13.7761 7 13.5 7H8.5Z" fill="#232323"/>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View file

@ -0,0 +1,5 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M7.70892 2.29365C7.52159 2.10591 7.26735 2.00028 7.00213 2C6.17371 1.99912 5.5 2 5 2C4 2 3.00004 3.00107 3 4C2.99998 4.5 2.99851 5.56725 2.99805 5.99894L0.998047 5.99681L3.99379 10L6.99804 6.0032L4.99804 6.00107C4.99835 5.71751 4.9987 5.52735 4.99804 5C4.99739 4.47265 5.47193 4 6.00049 4C6.50049 4 6.54487 3.99952 7 4C7.26522 4.00028 7.51968 3.8952 7.70742 3.70786C7.89515 3.52052 8.00078 3.26628 8.00106 3.00107C8.00135 2.73585 7.89626 2.48138 7.70892 2.29365Z" fill="#232323"/>
<rect x="9" y="1" width="6" height="4" rx="0.5" fill="#232323"/>
<rect x="5" y="11" width="6" height="4" rx="0.5" fill="#232323"/>
</svg>

After

Width:  |  Height:  |  Size: 724 B

View file

@ -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 }

View file

@ -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),
);
}

View file

@ -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();