Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(zkstack_cli): Autocompletion support #3097

Merged
merged 51 commits into from
Oct 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
63089e2
feat: add clap_complete dependency
manuelmauro Oct 15, 2024
8d827d9
fix: remove duplicated short args (-n)
manuelmauro Oct 15, 2024
7ede924
feat: draft autocompletion
manuelmauro Oct 15, 2024
a5a5265
refactor: add subcommand to generate shell autocompletion files
manuelmauro Oct 15, 2024
3d7efd1
style: format code
manuelmauro Oct 15, 2024
b435613
refactor: remove ValueHint::Other
manuelmauro Oct 16, 2024
3756dcc
fix: remove unused ignore
manuelmauro Oct 16, 2024
9767085
feat: add autocompletion files
manuelmauro Oct 16, 2024
febc890
feat: ignore untracked autocomplete files
manuelmauro Oct 16, 2024
3bca49e
feat: add dirs crate
manuelmauro Oct 16, 2024
2caa48c
feat: add --out option to shell completion generator subcommand
manuelmauro Oct 16, 2024
12f1629
feat: copy completion files at build time
manuelmauro Oct 16, 2024
bc7d89e
refactor: do not fail in build.rs
manuelmauro Oct 16, 2024
d7c7360
Merge branch 'main' into manuel-auto-completion-support
manuelmauro Oct 16, 2024
ce75676
refactor: remove eyre dependency
manuelmauro Oct 17, 2024
9a50122
fix: fix subcommands descriptions
manuelmauro Oct 17, 2024
2c7034d
fix: fix completion scripts installation
manuelmauro Oct 17, 2024
3597bef
Merge branch 'main' into manuel-auto-completion-support
manuelmauro Oct 17, 2024
ce9289b
refactor: split file creation and writing in autocomplete scripts cre…
manuelmauro Oct 17, 2024
08e168c
feat: add linter for sh autocomplete files
manuelmauro Oct 17, 2024
1219682
feat: update autocomplete files
manuelmauro Oct 17, 2024
65fba3c
docs: add outro to linting command
manuelmauro Oct 17, 2024
8777240
ci: check autocompletion files in CI
manuelmauro Oct 17, 2024
cbf26b3
Merge branch 'main' into manuel-auto-completion-support
manuelmauro Oct 17, 2024
e4fd787
test: check no_port_reallocation flag
manuelmauro Oct 17, 2024
8c46f4d
feat: bail if not running the linter from the project's root folder
manuelmauro Oct 17, 2024
3410896
fix: remove autocompletion lint from default list of targets
manuelmauro Oct 17, 2024
492ad74
test: test CI lint failure
manuelmauro Oct 17, 2024
039e5dd
docs: remove outdated docs
manuelmauro Oct 17, 2024
0e41e1d
test: linter correctly failed in CI
manuelmauro Oct 17, 2024
b823a30
Merge branch 'main' into manuel-auto-completion-support
manuelmauro Oct 17, 2024
09dfe6f
feat: update autocompletion files
manuelmauro Oct 17, 2024
2af6b3b
docs: better error
manuelmauro Oct 17, 2024
fc52c3f
feat: do not fail linting when running in the wrong folder
manuelmauro Oct 17, 2024
bb4dea0
feat: add autocompletion back to the linting default targets
manuelmauro Oct 17, 2024
919db1f
refactor: remove one Inception::command() invocation
manuelmauro Oct 18, 2024
fa44791
refactor: avoid tempfile creation on lint
manuelmauro Oct 18, 2024
ac22d84
feat: print informative error on failed autocompletion configuration
manuelmauro Oct 18, 2024
c91b67a
Update zkstack_cli/crates/zkstack/src/commands/dev/commands/lint.rs
manuelmauro Oct 18, 2024
7ad0b96
Merge branch 'manuel-auto-completion-support' of https://github.com/m…
manuelmauro Oct 18, 2024
53b1885
feat: generate fish autocompletion file on linting
manuelmauro Oct 18, 2024
20539ba
refactor: refactor autocomplete mod folder structure
manuelmauro Oct 18, 2024
61ac014
feat: add support for fish shell
manuelmauro Oct 18, 2024
2933c5a
Merge branch 'main' into manuel-auto-completion-support
manuelmauro Oct 18, 2024
b172bc6
refactor: rename inception_args to zkstack_args
manuelmauro Oct 18, 2024
e924ef7
fix: rename Inception to ZkStack
manuelmauro Oct 18, 2024
f058b06
Merge branch 'main' into manuel-auto-completion-support
manuelmauro Oct 18, 2024
9c34cc0
refactor: clippy
manuelmauro Oct 18, 2024
b090806
chore: regenerate autocompletion files
manuelmauro Oct 18, 2024
0fee9d5
refactor: use function in place of trait for autocomplete filenames
manuelmauro Oct 21, 2024
ed0ec84
refactor: use a better naming for autocomplete_extra
manuelmauro Oct 21, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/ci-core-lint-reusable.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ jobs:
ci_run zkstack dev lint -t js --check
ci_run zkstack dev lint -t ts --check
ci_run zkstack dev lint -t rs --check
ci_run zkstack dev lint -t autocompletion --check

- name: Check Database
run: |
Expand Down
12 changes: 11 additions & 1 deletion zkstack_cli/Cargo.lock

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

3 changes: 2 additions & 1 deletion zkstack_cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,12 @@ zksync_protobuf_build = "=0.5.0"
# External dependencies
anyhow = "1.0.82"
clap = { version = "4.4", features = ["derive", "wrap_help", "string"] }
clap_complete = "4.5.33"
dirs = "5.0.1"
slugify-rs = "0.0.3"
cliclack = "0.2.5"
console = "0.15.8"
chrono = "0.4.38"
eyre = "0.6.12"
ethers = "2.0"
futures = "0.3.30"
human-panic = "2.0"
Expand Down
6 changes: 5 additions & 1 deletion zkstack_cli/crates/zkstack/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,12 @@ keywords.workspace = true
anyhow.workspace = true
chrono.workspace = true
clap.workspace = true
clap_complete.workspace = true
clap-markdown.workspace = true
cliclack.workspace = true
common.workspace = true
config.workspace = true
dirs.workspace = true
ethers.workspace = true
futures.workspace = true
human-panic.workspace = true
Expand Down Expand Up @@ -49,6 +51,8 @@ rand.workspace = true
zksync_consensus_utils.workspace = true

[build-dependencies]
eyre.workspace = true
anyhow.workspace = true
clap_complete.workspace = true
dirs.workspace = true
ethers.workspace = true
zksync_protobuf_build.workspace = true
121 changes: 116 additions & 5 deletions zkstack_cli/crates/zkstack/build.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,23 @@
use std::path::PathBuf;
use std::path::{Path, PathBuf};

use anyhow::{anyhow, Context};
use ethers::contract::Abigen;

fn main() -> eyre::Result<()> {
const COMPLETION_DIR: &str = "completion";

fn main() -> anyhow::Result<()> {
let outdir = PathBuf::from(std::env::var("OUT_DIR")?).canonicalize()?;
Abigen::new("ConsensusRegistry", "abi/ConsensusRegistry.json")?
.generate()?
.write_to_file(outdir.join("consensus_registry_abi.rs"))?;
Abigen::new("ConsensusRegistry", "abi/ConsensusRegistry.json")
.map_err(|_| anyhow!("Failed ABI deserialization"))?
.generate()
.map_err(|_| anyhow!("Failed ABI generation"))?
.write_to_file(outdir.join("consensus_registry_abi.rs"))
.context("Failed to write ABI to file")?;

if let Err(e) = configure_shell_autocompletion() {
println!("cargo:warning=It was not possible to install autocomplete scripts. Please generate them manually with `zkstack autocomplete`");
println!("cargo:error={}", e);
};

zksync_protobuf_build::Config {
input_root: "src/commands/consensus/proto".into(),
Expand All @@ -19,3 +30,103 @@ fn main() -> eyre::Result<()> {
.unwrap();
Ok(())
}

fn configure_shell_autocompletion() -> anyhow::Result<()> {
// Array of supported shells
let shells = [
clap_complete::Shell::Bash,
clap_complete::Shell::Fish,
clap_complete::Shell::Zsh,
];

for shell in shells {
std::fs::create_dir_all(&shell.autocomplete_folder()?)
.context("it was impossible to create the configuration directory")?;

let src = Path::new(COMPLETION_DIR).join(shell.autocomplete_file_name()?);
let dst = shell
.autocomplete_folder()?
.join(shell.autocomplete_file_name()?);

std::fs::copy(src, dst)?;

shell
.configure_autocomplete()
.context("failed to run extra configuration requirements")?;
}

Ok(())
}

pub trait ShellAutocomplete {
fn autocomplete_folder(&self) -> anyhow::Result<PathBuf>;
fn autocomplete_file_name(&self) -> anyhow::Result<String>;
/// Extra steps required for shells enable command autocomplete.
fn configure_autocomplete(&self) -> anyhow::Result<()>;
}

impl ShellAutocomplete for clap_complete::Shell {
fn autocomplete_folder(&self) -> anyhow::Result<PathBuf> {
let home_dir = dirs::home_dir().context("missing home folder")?;

match self {
clap_complete::Shell::Bash => Ok(home_dir.join(".bash_completion.d")),
clap_complete::Shell::Fish => Ok(home_dir.join(".config/fish/completions")),
clap_complete::Shell::Zsh => Ok(home_dir.join(".zsh/completion")),
_ => anyhow::bail!("unsupported shell"),
}
}

fn autocomplete_file_name(&self) -> anyhow::Result<String> {
let crate_name = env!("CARGO_PKG_NAME");

match self {
clap_complete::Shell::Bash => Ok(format!("{}.sh", crate_name)),
clap_complete::Shell::Fish => Ok(format!("{}.fish", crate_name)),
clap_complete::Shell::Zsh => Ok(format!("_{}.zsh", crate_name)),
_ => anyhow::bail!("unsupported shell"),
}
}

fn configure_autocomplete(&self) -> anyhow::Result<()> {
match self {
clap_complete::Shell::Bash | clap_complete::Shell::Zsh => {
let shell = &self.to_string().to_lowercase();
let completion_file = self
.autocomplete_folder()?
.join(self.autocomplete_file_name()?);

// Source the completion file inside .{shell}rc
let shell_rc = dirs::home_dir()
.context("missing home directory")?
.join(format!(".{}rc", shell));

if shell_rc.exists() {
let shell_rc_content = std::fs::read_to_string(&shell_rc)
.context(format!("could not read .{}rc", shell))?;

if !shell_rc_content.contains("# zkstack completion") {
std::fs::write(
shell_rc,
format!(
"{}\n# zkstack completion\nsource \"{}\"\n",
shell_rc_content,
completion_file.to_str().unwrap()
),
)
.context(format!("could not write .{}rc", shell))?;
}
} else {
println!(
"cargo:warning=Please add the following line to your .{}rc:",
shell
);
println!("cargo:warning=source {}", completion_file.to_str().unwrap());
}
}
_ => (),
}

Ok(())
}
}
Loading
Loading