mirror of
https://github.com/helix-editor/helix.git
synced 2024-11-22 01:16:18 +04:00
Change focus to modified docs on quit (#3872)
* Change focus to modified docs on quit When quitting with modified documents, automatically switch focus to one of them. * Update helix-term/src/commands/typed.rs Co-authored-by: Poliorcetics <poliorcetics@users.noreply.github.com> * Make it work with buffer-close-all and the like * Cleanup Use Cow instead of String, and rename DoesntExist -> DoesNotExist Co-authored-by: Poliorcetics <poliorcetics@users.noreply.github.com>
This commit is contained in:
parent
6764744ce9
commit
1d8bb2249b
@ -2,7 +2,7 @@
|
||||
|
||||
use super::*;
|
||||
|
||||
use helix_view::editor::{Action, ConfigEvent};
|
||||
use helix_view::editor::{Action, CloseError, ConfigEvent};
|
||||
use ui::completers::{self, Completer};
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -71,8 +71,29 @@ fn buffer_close_by_ids_impl(
|
||||
doc_ids: &[DocumentId],
|
||||
force: bool,
|
||||
) -> anyhow::Result<()> {
|
||||
for &doc_id in doc_ids {
|
||||
editor.close_document(doc_id, force)?;
|
||||
let (modified_ids, modified_names): (Vec<_>, Vec<_>) = doc_ids
|
||||
.iter()
|
||||
.filter_map(|&doc_id| {
|
||||
if let Err(CloseError::BufferModified(name)) = editor.close_document(doc_id, force) {
|
||||
Some((doc_id, name))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.unzip();
|
||||
|
||||
if let Some(first) = modified_ids.first() {
|
||||
let current = doc!(editor);
|
||||
// If the current document is unmodified, and there are modified
|
||||
// documents, switch focus to the first modified doc.
|
||||
if !modified_ids.contains(¤t.id()) {
|
||||
editor.switch(*first, Action::Replace);
|
||||
}
|
||||
bail!(
|
||||
"{} unsaved buffer(s) remaining: {:?}",
|
||||
modified_names.len(),
|
||||
modified_names
|
||||
);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@ -513,23 +534,26 @@ fn force_write_quit(
|
||||
force_quit(cx, &[], event)
|
||||
}
|
||||
|
||||
/// Results an error if there are modified buffers remaining and sets editor error,
|
||||
/// otherwise returns `Ok(())`
|
||||
/// Results in an error if there are modified buffers remaining and sets editor
|
||||
/// error, otherwise returns `Ok(())`. If the current document is unmodified,
|
||||
/// and there are modified documents, switches focus to one of them.
|
||||
pub(super) fn buffers_remaining_impl(editor: &mut Editor) -> anyhow::Result<()> {
|
||||
let modified: Vec<_> = editor
|
||||
let (modified_ids, modified_names): (Vec<_>, Vec<_>) = editor
|
||||
.documents()
|
||||
.filter(|doc| doc.is_modified())
|
||||
.map(|doc| {
|
||||
doc.relative_path()
|
||||
.map(|path| path.to_string_lossy().to_string())
|
||||
.unwrap_or_else(|| SCRATCH_BUFFER_NAME.into())
|
||||
})
|
||||
.collect();
|
||||
if !modified.is_empty() {
|
||||
.map(|doc| (doc.id(), doc.display_name()))
|
||||
.unzip();
|
||||
if let Some(first) = modified_ids.first() {
|
||||
let current = doc!(editor);
|
||||
// If the current document is unmodified, and there are modified
|
||||
// documents, switch focus to the first modified doc.
|
||||
if !modified_ids.contains(¤t.id()) {
|
||||
editor.switch(*first, Action::Replace);
|
||||
}
|
||||
bail!(
|
||||
"{} unsaved buffer(s) remaining: {:?}",
|
||||
modified.len(),
|
||||
modified
|
||||
modified_names.len(),
|
||||
modified_names
|
||||
);
|
||||
}
|
||||
Ok(())
|
||||
|
@ -5,6 +5,7 @@
|
||||
use helix_core::Range;
|
||||
use serde::de::{self, Deserialize, Deserializer};
|
||||
use serde::Serialize;
|
||||
use std::borrow::Cow;
|
||||
use std::cell::Cell;
|
||||
use std::collections::HashMap;
|
||||
use std::fmt::Display;
|
||||
@ -1038,6 +1039,12 @@ pub fn relative_path(&self) -> Option<PathBuf> {
|
||||
.map(helix_core::path::get_relative_path)
|
||||
}
|
||||
|
||||
pub fn display_name(&self) -> Cow<'static, str> {
|
||||
self.relative_path()
|
||||
.map(|path| path.to_string_lossy().to_string().into())
|
||||
.unwrap_or_else(|| SCRATCH_BUFFER_NAME.into())
|
||||
}
|
||||
|
||||
// transact(Fn) ?
|
||||
|
||||
// -- LSP methods
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::{
|
||||
clipboard::{get_clipboard_provider, ClipboardProvider},
|
||||
document::{Mode, SCRATCH_BUFFER_NAME},
|
||||
document::Mode,
|
||||
graphics::{CursorKind, Rect},
|
||||
info::Info,
|
||||
input::KeyEvent,
|
||||
@ -28,7 +28,7 @@
|
||||
time::{sleep, Duration, Instant, Sleep},
|
||||
};
|
||||
|
||||
use anyhow::{bail, Error};
|
||||
use anyhow::Error;
|
||||
|
||||
pub use helix_core::diagnostic::Severity;
|
||||
pub use helix_core::register::Registers;
|
||||
@ -711,6 +711,14 @@ pub enum Action {
|
||||
VerticalSplit,
|
||||
}
|
||||
|
||||
/// Error thrown on failed document closed
|
||||
pub enum CloseError {
|
||||
/// Document doesn't exist
|
||||
DoesNotExist,
|
||||
/// Buffer is modified
|
||||
BufferModified(String),
|
||||
}
|
||||
|
||||
impl Editor {
|
||||
pub fn new(
|
||||
mut area: Rect,
|
||||
@ -1070,19 +1078,14 @@ pub fn close(&mut self, id: ViewId) {
|
||||
self._refresh();
|
||||
}
|
||||
|
||||
pub fn close_document(&mut self, doc_id: DocumentId, force: bool) -> anyhow::Result<()> {
|
||||
pub fn close_document(&mut self, doc_id: DocumentId, force: bool) -> Result<(), CloseError> {
|
||||
let doc = match self.documents.get(&doc_id) {
|
||||
Some(doc) => doc,
|
||||
None => bail!("document does not exist"),
|
||||
None => return Err(CloseError::DoesNotExist),
|
||||
};
|
||||
|
||||
if !force && doc.is_modified() {
|
||||
bail!(
|
||||
"buffer {:?} is modified",
|
||||
doc.relative_path()
|
||||
.map(|path| path.to_string_lossy().to_string())
|
||||
.unwrap_or_else(|| SCRATCH_BUFFER_NAME.into())
|
||||
);
|
||||
return Err(CloseError::BufferModified(doc.display_name().into_owned()));
|
||||
}
|
||||
|
||||
if let Some(language_server) = doc.language_server() {
|
||||
|
Loading…
Reference in New Issue
Block a user