on master help sign in
Implement `hx --tutor` and `:tutor` to load `tutor.txt` (#898)
e2ed691Omnikar
book/src/usage.md+1−1
@@ -2,7 +2,7 @@
2
2
3(Currently not fully documented, see the [keymappings](./keymap.md) list for more.)
3(Currently not fully documented, see the [keymappings](./keymap.md) list for more.)
4
4
5−See [tutor.txt](https://github.com/helix-editor/helix/blob/master/runtime/tutor.txt) for a vimtutor-like introduction.
5+See [tutor.txt](https://github.com/helix-editor/helix/blob/master/runtime/tutor.txt) (accessible via `hx --tutor` or `:tutor`) for a vimtutor-like introduction.
6
6
7## Registers
7## Registers
8
8
helix-term/src/application.rs+6−1
@@ -97,7 +97,12 @@ impl Application {
97 let editor_view = Box::new(ui::EditorView::new(std::mem::take(&mut config.keys)));
97 let editor_view = Box::new(ui::EditorView::new(std::mem::take(&mut config.keys)));
98 compositor.push(editor_view);
98 compositor.push(editor_view);
99
99
100+ if args.load_tutor {
101+ let path = helix_core::runtime_dir().join("tutor.txt");
102+ editor.open(path, Action::VerticalSplit)?;
103+ // Unset path to prevent accidentally saving to the original tutor file.
104+ doc_mut!(editor).set_path(None)?;
100− if !args.files.is_empty() {
105+ } else if !args.files.is_empty() {
101 let first = &args.files[0]; // we know it's not empty
106 let first = &args.files[0]; // we know it's not empty
102 if first.is_dir() {
107 if first.is_dir() {
103 std::env::set_current_dir(&first)?;
108 std::env::set_current_dir(&first)?;
helix-term/src/args.rs+2
@@ -5,6 +5,7 @@ use std::path::PathBuf;
5pub struct Args {
5pub struct Args {
6 pub display_help: bool,
6 pub display_help: bool,
7 pub display_version: bool,
7 pub display_version: bool,
8+ pub load_tutor: bool,
8 pub verbosity: u64,
9 pub verbosity: u64,
9 pub files: Vec<PathBuf>,
10 pub files: Vec<PathBuf>,
10}
11}
@@ -22,6 +23,7 @@ impl Args {
22 "--" => break, // stop parsing at this point treat the remaining as files
23 "--" => break, // stop parsing at this point treat the remaining as files
23 "--version" => args.display_version = true,
24 "--version" => args.display_version = true,
24 "--help" => args.display_help = true,
25 "--help" => args.display_help = true,
26+ "--tutor" => args.load_tutor = true,
25 arg if arg.starts_with("--") => {
27 arg if arg.starts_with("--") => {
26 return Err(Error::msg(format!(
28 return Err(Error::msg(format!(
27 "unexpected double dash argument: {}",
29 "unexpected double dash argument: {}",
helix-term/src/commands.rs+22−2
@@ -1557,7 +1557,8 @@ mod cmd {
1557 let (_, doc) = current!(cx.editor);
1557 let (_, doc) = current!(cx.editor);
1558
1558
1559 if let Some(path) = path {
1559 if let Some(path) = path {
1560+ doc.set_path(Some(path.as_ref()))
1560− doc.set_path(path.as_ref()).context("invalid filepath")?;
1561+ .context("invalid filepath")?;
1561 }
1562 }
1562 if doc.path().is_none() {
1563 if doc.path().is_none() {
1563 bail!("cannot write a buffer without a filename");
1564 bail!("cannot write a buffer without a filename");
@@ -2099,6 +2100,18 @@ mod cmd {
2099 Ok(())
2100 Ok(())
2100 }
2101 }
2101
2102
2103+ fn tutor(
2104+ cx: &mut compositor::Context,
2105+ _args: &[&str],
2106+ _event: PromptEvent,
2107+ ) -> anyhow::Result<()> {
2108+ let path = helix_core::runtime_dir().join("tutor.txt");
2109+ cx.editor.open(path, Action::Replace)?;
2110+ // Unset path to prevent accidentally saving to the original tutor file.
2111+ doc_mut!(cx.editor).set_path(None)?;
2112+ Ok(())
2113+ }
2114+
2102 pub const TYPABLE_COMMAND_LIST: &[TypableCommand] = &[
2115 pub const TYPABLE_COMMAND_LIST: &[TypableCommand] = &[
2103 TypableCommand {
2116 TypableCommand {
2104 name: "quit",
2117 name: "quit",
@@ -2351,7 +2364,14 @@ mod cmd {
2351 doc: "Open the file in a horizontal split.",
2364 doc: "Open the file in a horizontal split.",
2352 fun: hsplit,
2365 fun: hsplit,
2353 completer: Some(completers::filename),
2366 completer: Some(completers::filename),
2354− }
2367+ },
2368+ TypableCommand {
2369+ name: "tutor",
2370+ aliases: &[],
2371+ doc: "Open the tutorial.",
2372+ fun: tutor,
2373+ completer: None,
2374+ },
2355 ];
2375 ];
2356
2376
2357 pub static COMMANDS: Lazy<HashMap<&'static str, &'static TypableCommand>> = Lazy::new(|| {
2377 pub static COMMANDS: Lazy<HashMap<&'static str, &'static TypableCommand>> = Lazy::new(|| {
helix-view/src/document.rs+8−4
@@ -368,7 +368,7 @@ impl Document {
368 let mut doc = Self::from(rope, Some(encoding));
368 let mut doc = Self::from(rope, Some(encoding));
369
369
370 // set the path and try detecting the language
370 // set the path and try detecting the language
371− doc.set_path(path)?;
371+ doc.set_path(Some(path))?;
372 if let Some(loader) = config_loader {
372 if let Some(loader) = config_loader {
373 doc.detect_language(theme, loader);
373 doc.detect_language(theme, loader);
374 }
374 }
@@ -553,12 +553,16 @@ impl Document {
553 self.encoding
553 self.encoding
554 }
554 }
555
555
556− pub fn set_path(&mut self, path: &Path) -> Result<(), std::io::Error> {
556+ pub fn set_path(&mut self, path: Option<&Path>) -> Result<(), std::io::Error> {
557+ let path = if let Some(p) = path {
557− let path = helix_core::path::get_canonicalized_path(path)?;
558+ Some(helix_core::path::get_canonicalized_path(p)?)
559+ } else {
560+ path.map(|p| p.into())
561+ };
558
562
559 // if parent doesn't exist we still want to open the document
563 // if parent doesn't exist we still want to open the document
560 // and error out when document is saved
564 // and error out when document is saved
561− self.path = Some(path);
565+ self.path = path;
562
566
563 Ok(())
567 Ok(())
564 }
568 }