Skip to content

Commit

Permalink
Generate shell completions for nextonic
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
bryango committed Mar 12, 2024
1 parent 6351252 commit 11d0b41
Show file tree
Hide file tree
Showing 6 changed files with 86 additions and 3 deletions.
10 changes: 10 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ watchexec = "^2.3.0"
watchexec-filterer-globset = "1.2"
watchexec-signals = "1.0"
zip = { version = "^0.6", default-features = false, features = ["deflate"] }
clap_complete = "4.5.1"

[features]
default = ["geturl-reqwest", "serialization"]
Expand Down
27 changes: 27 additions & 0 deletions docs/src/ref/v2cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,33 @@ nextonic build
You can use various Unix `argv[0]` hacks to achieve this, or you can just rename
or symlink the `tectonic` binary to `nextonic` manually.

## Shell completions

Shell completions for the `nextonic` executable can be generated using
`nextonic show shell-completions`, plus the name of your shell. Currently,
completions are only available for the `nextonic` command.

As an example, you can generate shell completions for zsh and save it to a
file with the following command:

```zsh
nextonic show shell-completions zsh > _nextonic
```

You can then move the completion file to a location where zsh can auto load;
for example, `/usr/local/share/zsh/site-functions` would probably work for
most Unix systems. Alternatively, you can evaluate the completions directly
in you `~/.zshrc`, e.g.

```zsh
eval "$(nextonic show shell-completions zsh)"
```

Currently supported shells are listed in the `--help` text:

```zsh
nextonic show shell-completions --help
```

## External tools

Expand Down
2 changes: 1 addition & 1 deletion src/bin/tectonic/compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use tectonic::{
#[derive(Debug, Parser)]
pub struct CompileOptions {
/// The file to process, or "-" to process the standard input stream
#[arg(name = "input")]
#[arg(name = "input", value_hint = clap::ValueHint::FilePath)]
input: String,

/// The name of the "format" file used to initialize the TeX engine
Expand Down
36 changes: 34 additions & 2 deletions src/bin/tectonic/v2cli/commands/show.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use clap::Parser;
use clap::{CommandFactory, Parser};
use tectonic::{config::PersistentConfig, errors::Result};
use tectonic_status_base::StatusBackend;

use crate::v2cli::{CommandCustomizations, TectonicCommand};
use crate::v2cli::{CommandCustomizations, TectonicCommand, V2CliOptions};

/// `show`: Show various useful pieces of information.
#[derive(Debug, Eq, PartialEq, Parser)]
Expand All @@ -16,18 +16,24 @@ enum ShowCommands {
#[command(name = "user-cache-dir")]
/// Print the location of the default per-user cache directory
UserCacheDir(ShowUserCacheDirCommand),

#[command(name = "shell-completions")]
/// Print shell completions code for some given shell
ShellCompletions(ShowShellCompletionsCommand),
}

impl TectonicCommand for ShowCommand {
fn customize(&self, cc: &mut CommandCustomizations) {
match &self.command {
ShowCommands::UserCacheDir(c) => c.customize(cc),
ShowCommands::ShellCompletions(c) => c.customize(cc),
}
}

fn execute(self, config: PersistentConfig, status: &mut dyn StatusBackend) -> Result<i32> {
match self.command {
ShowCommands::UserCacheDir(c) => c.execute(config, status),
ShowCommands::ShellCompletions(c) => c.execute(config, status),
}
}
}
Expand All @@ -47,3 +53,29 @@ impl ShowUserCacheDirCommand {
Ok(0)
}
}

#[derive(Debug, Eq, PartialEq, Parser)]
struct ShowShellCompletionsCommand {
/// Target shell for the generated completion code
shell: clap_complete::Shell,
}

impl ShowShellCompletionsCommand {
fn customize(&self, cc: &mut CommandCustomizations) {
cc.always_stderr = true;
}

/// Generates shell completions at runtime
fn execute(self, _config: PersistentConfig, _status: &mut dyn StatusBackend) -> Result<i32> {
// 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.
clap_complete::generate(
self.shell,
&mut V2CliOptions::command(),
"nextonic",
&mut std::io::stdout(),
);
Ok(0)
}
}
13 changes: 13 additions & 0 deletions tests/executable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -933,6 +933,19 @@ fn v2_dump_suffix() {
assert!(saw_first && saw_second);
}

/// Checks that shell completions are correctly generated
#[cfg(feature = "serialization")]
#[test]
fn v2_show_shell_completions() {
let (_tempdir, temppath) = setup_v2();
let output = run_tectonic(&temppath, &["-X", "show", "shell-completions", "zsh"]);
success_or_panic(&output);

if !String::from_utf8_lossy(&output.stdout).contains("compdef _nextonic nextonic") {
panic!("shell completions generation failed.")
}
}

const SHELL_ESCAPE_TEST_DOC: &str = r"\immediate\write18{mkdir shellwork}
\immediate\write18{echo 123 >shellwork/persist}
\ifnum123=\input{shellwork/persist}
Expand Down

0 comments on commit 11d0b41

Please sign in to comment.