Add :help command

help-command
Omnikar 2 years ago committed by Michael Davis
parent fa436fa680
commit 321fce3ba6
No known key found for this signature in database

@ -73,3 +73,4 @@
| `:pipe` | Pipe each selection to the shell command. |
| `:pipe-to` | Pipe each selection to the shell command, ignoring output. |
| `:run-shell-command`, `:sh` | Run a shell command |
| `:help`, `:h` | Open documentation for a command or keybind. |

@ -1808,6 +1808,155 @@ fn run_shell_command(
Ok(())
}
fn help(cx: &mut compositor::Context, args: &[Cow<str>], event: PromptEvent) -> anyhow::Result<()> {
if event != PromptEvent::Validate {
return Ok(());
}
if args.is_empty() {
// TODO: Open a list of commands?
todo!()
}
if args[0] == "topics" {
let dir_path = helix_loader::runtime_dir().join("help/topics");
struct Topic(PathBuf);
impl crate::ui::menu::Item for Topic {
type Data = ();
fn label(&self, _data: &Self::Data) -> Spans {
self.0
.file_stem()
.and_then(|s| s.to_str())
.map(From::from)
.unwrap_or_default()
}
}
let entries: Vec<Topic> = std::fs::read_dir(&dir_path)
.map(|entries| {
entries
.filter_map(|entry| {
let entry = entry.ok()?;
let path = entry.path();
Some(path)
})
.map(Topic)
.collect()
})
.unwrap_or_default();
cx.jobs.callback(async move {
let callback = job::Callback::EditorCompositor(Box::new(
move |_editor: &mut Editor, compositor: &mut Compositor| {
let picker = FilePicker::new(
entries,
(),
|cx, Topic(path), _action| {
if let Err(e) =
cx.editor
.open(path, Action::HorizontalSplit)
.and_then(|id| {
cx.editor
.document_mut(id)
.unwrap()
.set_path(None)
.map_err(Into::into)
})
{
cx.editor.set_error(e.to_string());
}
},
|_editor, Topic(path)| Some((path.clone().into(), None)),
);
compositor.push(Box::new(picker));
},
));
Ok(callback)
});
return Ok(());
}
let args_msg = args.join(" ");
let open_help =
move |help_dir: &str, command: &str, editor: &mut Editor| -> anyhow::Result<()> {
let mut path = helix_loader::runtime_dir();
path.push("help");
path.push(help_dir);
path.push(format!("{}.txt", command));
ensure!(path.is_file(), "No help available for '{}'", args_msg);
let id = editor.open(&path, Action::HorizontalSplit)?;
editor.document_mut(id).unwrap().set_path(None)?;
Ok(())
};
const STATIC_HELP_DIR: &str = "static-commands";
const TYPABLE_HELP_DIR: &str = "typable-commands";
let (help_dir, command): (&str, &str) = {
let arg = &args[0];
if let Some(command) = arg.strip_prefix(':').and_then(|arg| {
TYPABLE_COMMAND_LIST.iter().find_map(|command| {
(command.name == arg || command.aliases.iter().any(|alias| *alias == arg))
.then(|| command.name)
})
}) {
(TYPABLE_HELP_DIR, command)
} else if MappableCommand::STATIC_COMMAND_LIST
.iter()
.any(|command| command.name() == arg)
{
(STATIC_HELP_DIR, arg)
} else {
let arg = arg.to_owned().into_owned();
let keys = arg
.parse::<KeyEvent>()
.map(|key| vec![key])
.or_else(|_| helix_view::input::parse_macro(&arg))?;
cx.jobs.callback(async move {
let callback = job::Callback::EditorCompositor(Box::new(
move |editor: &mut Editor, compositor: &mut Compositor| {
use crate::keymap::KeymapResult;
let editor_view = compositor.find::<ui::EditorView>().unwrap();
let mode = editor.mode;
let keymaps = &mut editor_view.keymaps;
let (keys, last_key) = (&keys[..keys.len() - 1], keys.last().unwrap());
keys.iter().for_each(|key| {
keymaps.get(mode, *key);
});
let result = keymaps.get(mode, *last_key);
let res: anyhow::Result<(&str, &str)> = match &result {
KeymapResult::Matched(command) => match command {
MappableCommand::Static { name, .. } => Ok((STATIC_HELP_DIR, name)),
MappableCommand::Typable { name, .. } => {
Ok((TYPABLE_HELP_DIR, name))
}
},
KeymapResult::NotFound | KeymapResult::Cancelled(_) => {
Err(anyhow!("No command found for '{}'", arg))
}
_ => todo!(),
};
if let Err(e) =
res.and_then(|(help_dir, command)| open_help(help_dir, command, editor))
{
editor.set_error(e.to_string());
}
},
));
Ok(callback)
});
return Ok(());
}
};
open_help(help_dir, command, cx.editor)
}
pub const TYPABLE_COMMAND_LIST: &[TypableCommand] = &[
TypableCommand {
name: "quit",
@ -2323,6 +2472,13 @@ pub const TYPABLE_COMMAND_LIST: &[TypableCommand] = &[
fun: run_shell_command,
completer: Some(completers::directory),
},
TypableCommand {
name: "help",
aliases: &["h"],
doc: "Open documentation for a command or keybind.",
fun: help,
completer: Some(completers::help),
},
];
pub static TYPABLE_COMMAND_MAP: Lazy<HashMap<&'static str, &'static TypableCommand>> =

@ -441,6 +441,50 @@ pub mod completers {
})
}
pub fn help(_editor: &Editor, input: &str) -> Vec<Completion> {
let static_cmds_path = helix_loader::runtime_dir().join("help/static-commands");
let typable_cmds_path = helix_loader::runtime_dir().join("help/typable-commands");
let mut items: Vec<String> = std::fs::read_dir(static_cmds_path)
.map(|entries| {
entries
.filter_map(|entry| {
let entry = entry.ok()?;
let path = entry.path();
(path.extension()? == "txt")
.then(|| path.file_stem().unwrap().to_string_lossy().into_owned())
})
.chain(
std::fs::read_dir(typable_cmds_path)
.map(|entries| {
entries.filter_map(|entry| {
let entry = entry.ok()?;
let path = entry.path();
(path.extension()? == "txt").then(|| {
format!(":{}", path.file_stem().unwrap().to_string_lossy())
})
})
})
.into_iter()
.flatten(),
)
.collect()
})
.unwrap_or_default();
items.push("topics".to_owned());
let matcher = Matcher::default();
let mut matches: Vec<_> = items
.into_iter()
.map(Cow::from)
.filter_map(|name| matcher.fuzzy_match(&name, input).map(|score| (name, score)))
.collect();
matches.sort_unstable_by_key(|(_file, score)| Reverse(*score));
matches.into_iter().map(|(name, _)| ((0..), name)).collect()
}
#[derive(Copy, Clone, PartialEq, Eq)]
enum FileMatch {
/// Entry should be ignored

@ -0,0 +1,5 @@
`append_mode`
Enters Insert mode at the end of the selection.
For information about Insert mode, see "Primary Modes".

@ -0,0 +1,5 @@
`append_to_line`
Enters Insert mode at the end of the line.
For information about Insert mode, see "Primary Modes".

@ -0,0 +1,18 @@
`copy_selection_on_next_line`
Copies the current primary selection to the next line long enough to accomodate it.
--- Examples ---
The selection is copied from line 1 to line 2.
┌───────────────────────────┐ ┌───────────────────────────┐
│ This is text (on line 1]. │ --> │ This is text (on line 1]. │
│ This is text on line 2. │ │ This is text (on line 2]. │
└───────────────────────────┘ └───────────────────────────┘
The selection duplication skips line 2 because it is too short.
┌──────────────────────────────────┐ ┌──────────────────────────────────┐
│ This is a longer li(ne of t]ext. │ │ This is a longer li(ne of t]ext. │
│ This is a shorter line. │ --> │ This is a shorter line. │
│ This is another longer line. │ │ This is another lon(ger lin]e. │
└──────────────────────────────────┘ └──────────────────────────────────┘

@ -0,0 +1,18 @@
`copy_selection_on_prev_line`
Copies the current primary selection to the first previous line long enough to accomodate it.
--- Examples ---
The selection is copied from line 2 to line 1.
┌───────────────────────────┐ ┌───────────────────────────┐
│ This is text on line 1. │ --> │ This is text (on line 1]. │
│ This is text (on line 2]. │ │ This is text (on line 2]. │
└───────────────────────────┘ └───────────────────────────┘
The selection duplication skips line 2 because it is too short.
┌──────────────────────────────────┐ ┌──────────────────────────────────┐
│ This is a longer line of text. │ │ This is a longer li(ne of t]ext. │
│ This is a shorter line. │ --> │ This is a shorter line. │
│ This is another lon(ger lin]e. │ │ This is another lon(ger lin]e. │
└──────────────────────────────────┘ └──────────────────────────────────┘

@ -0,0 +1,3 @@
`extend_char_left`
Extending version of `move_char_left`.

@ -0,0 +1,3 @@
`extend_char_right`
Extending version of `move_char_right`.

@ -0,0 +1,3 @@
`extend_line_down`
Extending version of `move_line_down`.

@ -0,0 +1,3 @@
`extend_line_up`
Extending version of `move_line_up`.

@ -0,0 +1,3 @@
`extend_next_char`
Extending version of `find_next_char`.

@ -0,0 +1,3 @@
`extend_next_long_word_end`
Extending version of `move_next_long_word_end`.

@ -0,0 +1,3 @@
`extend_next_long_word_start`
Extending version of `move_next_long_word_start`.

@ -0,0 +1,3 @@
`extend_next_word_end`
Extending version of `move_next_word_end`.

@ -0,0 +1,3 @@
`extend_next_word_start`
Extending version of `move_next_word_start`.

@ -0,0 +1,3 @@
`extend_prev_char`
Extending version of `find_prev_char`.

@ -0,0 +1,3 @@
`extend_prev_long_word_start`
Extending version of `move_prev_long_word_start`.

@ -0,0 +1,3 @@
`extend_prev_word_start`
Extending version of `move_prev_word_start`.

@ -0,0 +1,3 @@
`extend_till_char`
Extending version of `find_till_char`.

@ -0,0 +1,3 @@
`extend_till_prev_char`
Extending version of `till_prev_char`.

@ -0,0 +1,22 @@
`find_next_char`
Waits for another keypress, then moves and
selects forward, stopping at the first
instance of the pressed key. Can take
a count, which will cause it to stop
at the nth instance of the keypress,
rather than the first.
--- Examples ---
The cursor moves forward, stopping at 'c'
and selecting everything along the way.
┌───────────────────────┐ c ┌───────────────────────┐
│ This i[s] a sentence. │ --> │ This i(s a sentenc]e. │
└───────────────────────┘ └───────────────────────┘
The cursor is not stopped by line breaks.
┌───────────────────────────┐ ┌────────────────────────────┐
│ This is the fi[r]st line. │ Q │ This is the fi(rst line. │
│ This second line has a Q. │ --> │ This second line has a Q]. │
└───────────────────────────┘ └────────────────────────────┘

@ -0,0 +1,22 @@
`find_prev_char`
Waits for another keypress, then moves and
selects backward, stopping at the first
instance of the pressed key. Can take
a count, which will cause it to stop
at the nth instance of the keypress,
rather than the first.
--- Examples ---
The cursor moves backward, stopping at 'h'
and selecting everything along the way.
┌───────────────────────┐ h ┌───────────────────────┐
│ This is a sent[e]nce. │ --> │ T[his is a sente)nce. │
└───────────────────────┘ └───────────────────────┘
The cursor is not stopped by line breaks.
┌──────────────────────────────────┐ ┌───────────────────────────────────┐
│ There is a Q in this first line. │ Q │ There is a [Q in this first line. │
│ This is the se[c]ond line. │ --> │ This is the sec)ond line. │
└──────────────────────────────────┘ └───────────────────────────────────┘

@ -0,0 +1,22 @@
`find_till_char`
Waits for another keypress, then moves and
selects forward, stopping before the first
instance of the pressed key. Can take
a count, which will cause it to stop
before the nth instance of the keypress,
rather than the first.
--- Examples ---
The cursor moves forward, stopping before 'c'
and selecting everything along the way.
┌───────────────────────┐ c ┌───────────────────────┐
│ This i[s] a sentence. │ --> │ This i(s a senten]ce. │
└───────────────────────┘ └───────────────────────┘
The cursor is not stopped by line breaks.
┌───────────────────────────┐ ┌────────────────────────────┐
│ This is the fi[r]st line. │ Q │ This is the fi(rst line. │
│ This second line has a Q. │ --> │ This second line has a ]Q. │
└───────────────────────────┘ └────────────────────────────┘

@ -0,0 +1,3 @@
`half_page_down`
Scrolls down by half of a screen.

@ -0,0 +1,3 @@
`half_page_up`
Scrolls up by half of a screen.

@ -0,0 +1,5 @@
`insert_mode`
Enters Insert mode at the start of the selection.
For information about Insert mode, see "Primary Modes".

@ -0,0 +1,4 @@
`move_char_left`
Moves all cursors 1 character left, removing
any selections and wrapping across line breaks.

@ -0,0 +1,4 @@
`move_char_right`
Moves all cursors 1 character right, removing
any selections and wrapping across line breaks.

@ -0,0 +1,15 @@
`move_line_down`
Moves all cursors 1 line down, removing any selections.
Repeating this will remember the vertical position of the cursors,
even when moving across shorter lines.
--- Examples ---
The cursor remembers its vertical position,
even after moving across the shorter line.
┌────────────────────────────┐ ┌────────────────────────────┐ ┌──────────────────────────────┐
│ This is a longer l[i]ne. │ │ This is a longer line. │ │ This is a longer line. │
│ Shorter line. │ --> │ Shorter line.[] │ --> │ Shorter line. │
│ This is another long line. │ │ This is another long line. │ │ This is another lo[n]g line. │
└────────────────────────────┘ └────────────────────────────┘ └──────────────────────────────┘

@ -0,0 +1,15 @@
`move_line_up`
Moves all cursors 1 line up, removing any selections.
Repeating this will remember the vertical position of the cursors,
even when moving across shorter lines.
--- Examples ---
The cursor remembers its vertical position,
even after moving across the shorter line.
┌──────────────────────────────┐ ┌────────────────────────────┐ ┌────────────────────────────┐
│ This is a longer line. │ │ This is a longer line. │ │ This is a longer l[i]ne. │
│ Shorter line. │ --> │ Shorter line.[] │ --> │ Shorter line. │
│ This is another lo[n]g line. │ │ This is another long line. │ │ This is another long line. │
└──────────────────────────────┘ └────────────────────────────┘ └────────────────────────────┘

@ -0,0 +1,17 @@
`move_next_long_word_end`
Moves and selects forward, stopping at
the last character of the current WORD.
For the difference between words and WORDS, see "Words vs. WORDS".
--- Examples ---
The cursor moves forward, stopping at the end of 'These-are'
and selecting everything along the way.
┌────────────────────┐ ┌────────────────────┐
│ [T]hese-are WORDS. │ --> │ (These-are] WORDS. │
└────────────────────┘ └────────────────────┘
┌────────────────────┐ ┌────────────────────┐
│ Th[e]se-are WORDS. │ --> │ Th(ese-are] WORDS. │
└────────────────────┘ └────────────────────┘

@ -0,0 +1,17 @@
`move_next_long_word_start`
Moves and selects forward, stopping before
the first character of the next WORD.
For the difference between words and WORDS, see "Words vs. WORDS".
--- Examples ---
The cursor moves forward, stopping before the start of 'WORDS'
and selecting everything along the way.
┌────────────────────┐ ┌────────────────────┐
│ [T]hese-are WORDS. │ --> │ (These-are ]WORDS. │
└────────────────────┘ └────────────────────┘
┌────────────────────┐ ┌────────────────────┐
│ Th[e]se-are WORDS. │ --> │ Th(ese-are ]WORDS. │
└────────────────────┘ └────────────────────┘

@ -0,0 +1,15 @@
`move_next_word_end`
Moves and selects forward, stopping at
the last character of the current word.
--- Examples ---
The cursor moves forward, stopping at the end of 'These'
and selecting everything along the way.
┌────────────────────┐ ┌────────────────────┐
│ [T]hese are words. │ --> │ (These] are words. │
└────────────────────┘ └────────────────────┘
┌────────────────────┐ ┌────────────────────┐
│ Th[e]se are words. │ --> │ Th(ese] are words. │
└────────────────────┘ └────────────────────┘

@ -0,0 +1,15 @@
`move_next_word_start`
Moves and selects forward, stopping before
the first character of the next word.
--- Examples ---
The cursor moves forward, stopping before the start of 'are'
and selecting everything along the way.
┌────────────────────┐ ┌────────────────────┐
│ [T]hese are words. │ --> │ (These ]are words. │
└────────────────────┘ └────────────────────┘
┌────────────────────┐ ┌────────────────────┐
│ Th[e]se are words. │ --> │ Th(ese ]are words. │
└────────────────────┘ └────────────────────┘

@ -0,0 +1,20 @@
`move_prev_long_word_start`
Moves and selects backward, stopping at
the first character of the previous WORD.
For the difference between words and WORDS, see "Words vs. WORDS".
--- Examples ---
The cursor moves backwards, stopping at the start of 'These-are'
and selecting everything along the way.
┌────────────────────┐ ┌────────────────────┐
│ These-are[ ]WORDS. │ --> │ [These-are )WORDS. │
└────────────────────┘ └────────────────────┘
┌────────────────────┐ ┌────────────────────┐
│ These-are [W]ORDS. │ --> │ [These-are )WORDS. │
└────────────────────┘ └────────────────────┘
┌────────────────────┐ ┌────────────────────┐
│ These-a[r]e WORDS. │ --> │ [These-ar)e WORDS. │
└────────────────────┘ └────────────────────┘

@ -0,0 +1,18 @@
`move_prev_word_start`
Moves and selects backward, stopping at
the first character of the previous word.
--- Examples ---
The cursor moves backwards, stopping at the start of 'These'
and selecting everything along the way.
┌────────────────────┐ ┌────────────────────┐
│ These[ ]are words. │ --> │ [These )are words. │
└────────────────────┘ └────────────────────┘
┌────────────────────┐ ┌────────────────────┐
│ These [a]re words. │ --> │ [These )are words. │
└────────────────────┘ └────────────────────┘
┌────────────────────┐ ┌────────────────────┐
│ Th[e]se are words. │ --> │ [The)se are words. │
└────────────────────┘ └────────────────────┘

@ -0,0 +1,3 @@
`no_op`
Does nothing. Use this to disable default keybinds.

@ -0,0 +1,3 @@
`page_down`
Scrolls down by one screen.

@ -0,0 +1,3 @@
`page_up`
Scrolls up by one screen.

@ -0,0 +1,5 @@
`prepend_to_line`
Enters Insert mode before the first non-whitespace character in the line.
For information about Insert mode, see "Primary Modes".

@ -0,0 +1,21 @@
`replace`
Waits for another keypress, then replaces all
selected characters with the pressed key.
--- Examples ---
'a' is replaced with 'e'.
┌──────────────────────────┐ e ┌──────────────────────────┐
│ Do this, th[a]n do that. │ --> │ Do this, th[e]n do that. │
└──────────────────────────┘ └──────────────────────────┘
All instances of ',' are replaced with '.'.
┌──────────────────────────────┐ . ┌──────────────────────────────┐
│ This sentence continues(,,,] │ --> │ This sentence continues(...] │
└──────────────────────────────┘ └──────────────────────────────┘
All instances of 'a' are replaced with 'e'.
┌──────────────────────────────────┐ e ┌──────────────────────────────────┐
│ 1, th[a]n 2, th[a]n 3, th[a]n 4. │ --> │ 1, th[e]n 2, th[e]n 3, th[e]n 4. │
└──────────────────────────────────┘ └──────────────────────────────────┘

@ -0,0 +1,3 @@
`select_all`
Selects the entire buffer.

@ -0,0 +1,13 @@
`switch_case`
Toggles the case of all selected letters.
--- Examples ---
┌───────────────────────┐ ┌───────────────────────┐
│ [t]his is a sentence. │ --> │ [T]his is a sentence. │
└───────────────────────┘ └───────────────────────┘
┌───────────────────────┐ ┌───────────────────────┐
│ (tHIS] is a sentence. │ --> │ (This] is a sentence. │
└───────────────────────┘ └───────────────────────┘

@ -0,0 +1,9 @@
`switch_to_lowercase`
Changes all selected letters to lowercase.
--- Examples ---
┌──────────────────────────────────┐ ┌──────────────────────────────────┐
│ This (wOrD] should be lowercase. │ --> │ This (word] should be lowercase. │
└──────────────────────────────────┘ └──────────────────────────────────┘

@ -0,0 +1,9 @@
`switch_to_uppercase`
Changes all selected letters to uppercase.
--- Examples ---
┌──────────────────────────────────┐ ┌──────────────────────────────────┐
│ This (wOrD] should be uppercase. │ --> │ This (WORD] should be uppercase. │
└──────────────────────────────────┘ └──────────────────────────────────┘

@ -0,0 +1,22 @@
`till_prev_char`
Waits for another keypress, then moves and
selects backward, stopping before the first
instance of the pressed key. Can take
a count, which will cause it to stop
before the nth instance of the keypress,
rather than the first.
--- Examples ---
The cursor moves backward, stopping before 'h'
and selecting everything along the way.
┌───────────────────────┐ h ┌───────────────────────┐
│ This is a sent[e]nce. │ --> │ Th[is is a sente)nce. │
└───────────────────────┘ └───────────────────────┘
The cursor is not stopped by line breaks.
┌──────────────────────────────────┐ ┌───────────────────────────────────┐
│ There is a Q in this first line. │ Q │ There is a Q[ in this first line. │
│ This is the se[c]ond line. │ --> │ This is the sec)ond line. │
└──────────────────────────────────┘ └───────────────────────────────────┘

@ -0,0 +1,21 @@
Primary Modes
Helix is a modal editor, and has two primary "modes" of operation.
Normal mode, which is the mode you start in by default, and which
you will likely spend a substantial amount of time in, is the main
mode used for text editing operations.
Insert mode, which can be entered in numerous ways — such as by
pressing i — is used for typing text.
A third mode, called "Select" or "Extend" mode, is essentially a
subset of Normal mode, where moving cursors leaves selection
anchors in place — useful for making modifications to existing
selections. Select mode can be toggled by pressing v.
You can see which of these three modes you are currently in by
looking at the left side of the statusline. It will display:
NOR — Normal mode
INS — Insert mode
SEL — Select mode

@ -0,0 +1,19 @@
Words vs. WORDS
Words and WORDS are two very similar types of text objects. A word
is a string of "word" characters, which include letters, numbers,
and underscores. A WORD, on the other hand, is any string of
non-whitespace characters.
In the example below, the words are underlined by 'w', and the
WORDS are underlined by 'W'.
This "stuff" is not-so difficult!
---------------------------------
wwww wwwww ww www ww wwwwwwwww
WWWW WWWWWWW WW WWWWWW WWWWWWWWWW
As is visible in the example, the words do not include any of the
non-alphanumeric punctuation, while the WORDS do include the
quotes, hyphen, and exclamation point. Also notice that 'not-so'
contains two words, but only one WORD.

@ -0,0 +1,6 @@
`:buffer-close!`
Aliases: `:bc!`, `:bclose!`
Closes the current buffer, discarding any
unsaved changes to the buffer.

@ -0,0 +1,6 @@
`:buffer-close`
Aliases: `:bc`, `:bclose`
Closes the current buffer, failing if the buffer
has unsaved changes.

@ -0,0 +1,6 @@
`:new`
Aliases: `:n`
Creates and switches to a new scratch buffer. This
buffer will not be associated with any file path.

@ -0,0 +1,8 @@
`:open <path>`
Aliases: `:o`
If <path> exists, opens the file at <path>.
If <path> does not exist, creates a new buffer
and associates it with <path>. Note that this
does not automatically save the created buffer.

@ -0,0 +1,7 @@
`:quit!`
Aliases: `:q!`
Closes the current view, exiting the editor if it is
the last view. If this would exit the editor, unsaved
changes are discarded.

@ -0,0 +1,6 @@
`:quit-all!`
Aliases: `:qa!`
Closes all views, exiting the editor. This will
discard any unsaved changes.

@ -0,0 +1,6 @@
`:quit-all`
Aliases: `:qa`
Closes all views, exiting the editor. This will
fail if there are any unsaved changes.

@ -0,0 +1,7 @@
`:quit`
Aliases: `:q`
Closes the current view, exiting the editor if it is
the last view. This will fail if it would exit the
editor while there are unsaved changes.

@ -0,0 +1,7 @@
`:write-all`
Aliases: `:wa`
Writes (saves) all unsaved buffers to disk.
Scratch buffers (without associated paths)
will not be saved.

@ -0,0 +1,9 @@
`:write-quit! [path]`
Aliases: `:wq!`, `:x!`
Writes (saves) the buffer to disk, then
closes the view, discarding unsaved changes
if this would exit the editor.
Identical to `:write [path]` followed by `:quit!`.
See those commands for more info.

@ -0,0 +1,10 @@
`:write-quit-all!`
Aliases: `:wqa!`, `:xa!`
Writes (saves) all unsaved buffers to disk, then
closes all views, exiting the editor.
Scratch buffers (without associated paths) will
not be saved, and will be discarded when the
editor exits.
Identical to `:write-all` followed by `:quit-all!`.

@ -0,0 +1,10 @@
`:write-quit-all`
Aliases: `:wqa`, `:xa`
Writes (saves) all unsaved buffers to disk, then
closes all views, exiting the editor.
Scratch buffers (without associated paths) will
not be saved, and exiting the editor will fail
if there are any such buffers open.
Identical to `:write-all` followed by `:quit-all`.

@ -0,0 +1,8 @@
`:write-quit [path]`
Aliases: `:wq`, `:x`
Writes (saves) the buffer to disk, then
closes the view.
Identical to `:write [path]` followed by `:quit`.
See those commands for more info.

@ -0,0 +1,9 @@
`:write [path]`
Aliases: `:w`
Writes (saves) the buffer to disk.
If [path] is supplied, that path is written to.
If the buffer is a scratch buffer, meaning it
is not already bound to a file path, [path]
becomes required for this command to succeed.
Loading…
Cancel
Save