Skip to content

Commit dfe7035

Browse files
committed
Generate shell completions for nextonic
This is achieved with clap_complete. The current v1 & v2 cli mixture makes it a bit difficult to offer clean completions for the `tectonic` command, so for now we only target the `nextonic` command exclusively for the v2 cli.
1 parent e7e5ea3 commit dfe7035

File tree

6 files changed

+86
-3
lines changed

6 files changed

+86
-3
lines changed

Cargo.lock

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ watchexec-signals = "2.0"
9595
watchexec-supervisor = "1.0"
9696
zip = { version = "^0.6", default-features = false, features = ["deflate"] }
9797
time = "0.3.36"
98+
clap_complete = "4.5.1"
9899

99100
[features]
100101
default = ["geturl-reqwest", "serialization"]

docs/src/ref/v2cli.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,33 @@ nextonic build
4040
You can use various Unix `argv[0]` hacks to achieve this, or you can just rename
4141
or symlink the `tectonic` binary to `nextonic` manually.
4242

43+
## Shell completions
44+
45+
Shell completions for the `nextonic` executable can be generated using
46+
`nextonic show shell-completions`, plus the name of your shell. Currently,
47+
completions are only available for the `nextonic` command.
48+
49+
As an example, you can generate shell completions for zsh and save it to a
50+
file with the following command:
51+
52+
```zsh
53+
nextonic show shell-completions zsh > _nextonic
54+
```
55+
56+
You can then move the completion file to a location where zsh can auto load;
57+
for example, `/usr/local/share/zsh/site-functions` would probably work for
58+
most Unix systems. Alternatively, you can evaluate the completions directly
59+
in you `~/.zshrc`, e.g.
60+
61+
```zsh
62+
eval "$(nextonic show shell-completions zsh)"
63+
```
64+
65+
Currently supported shells are listed in the `--help` text:
66+
67+
```zsh
68+
nextonic show shell-completions --help
69+
```
4370

4471
## External tools
4572

src/bin/tectonic/compile.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use tectonic::{
2222
#[derive(Debug, Parser)]
2323
pub struct CompileOptions {
2424
/// The file to process, or "-" to process the standard input stream
25-
#[arg(name = "input")]
25+
#[arg(name = "input", value_hint = clap::ValueHint::FilePath)]
2626
input: String,
2727

2828
/// The name of the "format" file used to initialize the TeX engine

src/bin/tectonic/v2cli/commands/show.rs

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
use clap::Parser;
1+
use clap::{CommandFactory, Parser};
22
use tectonic::{config::PersistentConfig, errors::Result};
33
use tectonic_status_base::StatusBackend;
44

5-
use crate::v2cli::{CommandCustomizations, TectonicCommand};
5+
use crate::v2cli::{CommandCustomizations, TectonicCommand, V2CliOptions};
66

77
/// `show`: Show various useful pieces of information.
88
#[derive(Debug, Eq, PartialEq, Parser)]
@@ -16,18 +16,24 @@ enum ShowCommands {
1616
#[command(name = "user-cache-dir")]
1717
/// Print the location of the default per-user cache directory
1818
UserCacheDir(ShowUserCacheDirCommand),
19+
20+
#[command(name = "shell-completions")]
21+
/// Print shell completions code for some given shell
22+
ShellCompletions(ShowShellCompletionsCommand),
1923
}
2024

2125
impl TectonicCommand for ShowCommand {
2226
fn customize(&self, cc: &mut CommandCustomizations) {
2327
match &self.command {
2428
ShowCommands::UserCacheDir(c) => c.customize(cc),
29+
ShowCommands::ShellCompletions(c) => c.customize(cc),
2530
}
2631
}
2732

2833
fn execute(self, config: PersistentConfig, status: &mut dyn StatusBackend) -> Result<i32> {
2934
match self.command {
3035
ShowCommands::UserCacheDir(c) => c.execute(config, status),
36+
ShowCommands::ShellCompletions(c) => c.execute(config, status),
3137
}
3238
}
3339
}
@@ -47,3 +53,29 @@ impl ShowUserCacheDirCommand {
4753
Ok(0)
4854
}
4955
}
56+
57+
#[derive(Debug, Eq, PartialEq, Parser)]
58+
struct ShowShellCompletionsCommand {
59+
/// Target shell for the generated completion code
60+
shell: clap_complete::Shell,
61+
}
62+
63+
impl ShowShellCompletionsCommand {
64+
fn customize(&self, cc: &mut CommandCustomizations) {
65+
cc.always_stderr = true;
66+
}
67+
68+
/// Generates shell completions at runtime
69+
fn execute(self, _config: PersistentConfig, _status: &mut dyn StatusBackend) -> Result<i32> {
70+
// The current v1 & v2 cli mixture makes it a bit difficult to offer
71+
// clean completions for the `tectonic` command, so for now we only
72+
// target the `nextonic` command exclusively for the v2 cli.
73+
clap_complete::generate(
74+
self.shell,
75+
&mut V2CliOptions::command(),
76+
"nextonic",
77+
&mut std::io::stdout(),
78+
);
79+
Ok(0)
80+
}
81+
}

tests/executable.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -933,6 +933,19 @@ fn v2_dump_suffix() {
933933
assert!(saw_first && saw_second);
934934
}
935935

936+
/// Checks that shell completions are correctly generated
937+
#[cfg(feature = "serialization")]
938+
#[test]
939+
fn v2_show_shell_completions() {
940+
let (_tempdir, temppath) = setup_v2();
941+
let output = run_tectonic(&temppath, &["-X", "show", "shell-completions", "zsh"]);
942+
success_or_panic(&output);
943+
944+
if !String::from_utf8_lossy(&output.stdout).contains("compdef _nextonic nextonic") {
945+
panic!("shell completions generation failed.")
946+
}
947+
}
948+
936949
const SHELL_ESCAPE_TEST_DOC: &str = r"\immediate\write18{mkdir shellwork}
937950
\immediate\write18{echo 123 >shellwork/persist}
938951
\ifnum123=\input{shellwork/persist}

0 commit comments

Comments
 (0)