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

Shell autocomplete #62

Merged
merged 11 commits into from
Dec 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
50 changes: 50 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 @@ -15,6 +15,7 @@ categories = ["command-line-utilities", "science"]
[dependencies]
clap = { version = "4.5.21", features = ["derive", "env"] }
clap-verbosity-flag = "3.0.1"
clap_complete = { version = "4.5.38", features = ["unstable-dynamic"] }
console = "0.15.8"
env_logger = "0.11.5"
home = "0.5.9"
Expand Down
573 changes: 564 additions & 9 deletions THIRDPARTY.yaml

Large diffs are not rendered by default.

19 changes: 19 additions & 0 deletions doc/src/guide/install.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,22 @@ cargo install --path row --locked
```

Ensure that `$HOME/.cargo/bin` is on your `$PATH`.

## Configuring shell autocompletion

Execute the appropriate command in your shell's profile:
* Bash:
```shell
source <(COMPLETE=bash row)
```
* Fish:
```shell
source (COMPLETE=fish row | psub)
```
* Zsh:
```shell
source <(COMPLETE=zsh row)
```
For additional shell configurations, see [clap-complete's documentation].

[clap-complete's documentation]: https://docs.rs/clap_complete/latest/clap_complete/env/index.html
13 changes: 13 additions & 0 deletions doc/src/release-notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,18 @@

*Highlights:*

**Row** 0.4 expands the `command` templating functionality to improve support for
command line applications as actions. This removes the need for _shim_ scripts that
access the workspace path and/or directory values before invoking a subprocess.
`{workspace_path}` expands to the current project's workspace path and `{/JSON pointer}`
expands to the value of the given JSON pointer for the directory acted on.

**Row** 0.4 also adds _shell autocompletion_. To enable, execute the appropriate
command in your shell's profile:
* Bash: `source <(COMPLETE=bash row)`
* Fish: `source (COMPLETE=fish row | psub)`
* Zsh: `source <(COMPLETE=zsh row)`

*Added:*

* In job scripts, set the environment variable `ACTION_WORKSPACE_PATH` to the _relative_
Expand All @@ -12,6 +24,7 @@
_relative_ path to the current workspace.
* `{/JSON pointer}` template parameter in `action.command` - replaced with the portion
of the directory's value referenced by the given JSON pointer.
* Shell autocomplete.

*Fixed:*

Expand Down
5 changes: 4 additions & 1 deletion src/cli.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright (c) 2024 The Regents of the University of Michigan.
// Part of row, released under the BSD 3-Clause License.

pub mod autocomplete;
pub mod clean;
pub mod cluster;
pub mod directories;
Expand All @@ -11,6 +12,7 @@ pub mod status;
pub mod submit;

use clap::{Args, Parser, Subcommand, ValueEnum};
use clap_complete::ArgValueCandidates;
use clap_verbosity_flag::{Verbosity, WarnLevel};
use log::trace;
use std::io;
Expand Down Expand Up @@ -50,7 +52,8 @@ pub struct GlobalOptions {
/// Check the job submission status on the given cluster.
///
/// Autodetected by default.
#[arg(long, global = true, env = "ROW_CLUSTER", display_order = 2)]
#[arg(long, global = true, env = "ROW_CLUSTER", display_order = 2,
add=ArgValueCandidates::new(autocomplete::get_cluster_candidates))]
cluster: Option<String>,
}

Expand Down
55 changes: 55 additions & 0 deletions src/cli/autocomplete.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// Copyright (c) 2024 The Regents of the University of Michigan.
// Part of row, released under the BSD 3-Clause License.

use clap_complete::CompletionCandidate;
use indicatif::{MultiProgress, ProgressDrawTarget};

use row::workflow::Workflow;
use row::MultiProgressContainer;
use row::{cluster, workspace};

/// List the actions in the current workflow.
pub fn get_action_candidates() -> Vec<CompletionCandidate> {
let Ok(workflow) = Workflow::open() else {
return Vec::new();
};

workflow
.action
.into_iter()
.map(|a| CompletionCandidate::new(a.name()))
.collect()
}

/// List the clusters in the user's configuration
pub fn get_cluster_candidates() -> Vec<CompletionCandidate> {
let Ok(clusters) = cluster::Configuration::open() else {
return Vec::new();
};

clusters
.cluster
.into_iter()
.map(|a| CompletionCandidate::new(a.name))
.collect()
}

/// List the directories in the project's workspace
pub fn get_directory_candidates() -> Vec<CompletionCandidate> {
let multi_progress = MultiProgress::with_draw_target(ProgressDrawTarget::hidden());
let mut multi_progress_container = MultiProgressContainer::new(multi_progress.clone());

let Ok(workflow) = Workflow::open() else {
return Vec::new();
};

let Ok(directories) = workspace::list_directories(&workflow, &mut multi_progress_container)
else {
return Vec::new();
};

directories
.into_iter()
.map(CompletionCandidate::new)
.collect()
}
7 changes: 5 additions & 2 deletions src/cli/directories.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@
// Part of row, released under the BSD 3-Clause License.

use clap::Args;
use clap_complete::ArgValueCandidates;
use console::Style;
use log::{debug, warn};
use std::collections::HashSet;
use std::error::Error;
use std::io::Write;
use std::path::PathBuf;

use crate::cli::{self, GlobalOptions};
use crate::cli::{self, autocomplete, GlobalOptions};
use crate::ui::{Alignment, Item, Row, Table};
use row::project::Project;
use row::MultiProgressContainer;
Expand All @@ -18,10 +19,12 @@ use row::MultiProgressContainer;
#[allow(clippy::struct_excessive_bools)]
pub struct Arguments {
/// Select directories to summarize (defaults to all). Use 'show directories -' to read from stdin.
#[arg(add=ArgValueCandidates::new(autocomplete::get_directory_candidates))]
directories: Vec<PathBuf>,

/// Select directories that are included by the provided action.
#[arg(long, short, display_order = 0)]
#[arg(long, short, display_order = 0,
add=ArgValueCandidates::new(autocomplete::get_action_candidates))]
action: Option<String>,

/// Hide the table header.
Expand Down
3 changes: 2 additions & 1 deletion src/cli/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// Part of row, released under the BSD 3-Clause License.

use clap::Args;
use clap_complete::ValueHint;
use log::{debug, info, trace, warn};
use path_absolutize::Absolutize;
use std::fmt::Write as _;
Expand All @@ -23,7 +24,7 @@ pub struct Arguments {
workspace: String,

/// Directory to initialize.
#[arg(display_order = 0)]
#[arg(display_order = 0, value_hint=ValueHint::DirPath)]
directory: PathBuf,
}

Expand Down
7 changes: 5 additions & 2 deletions src/cli/scan.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@
// Part of row, released under the BSD 3-Clause License.

use clap::Args;
use clap_complete::ArgValueCandidates;
use log::{debug, info, trace, warn};
use postcard;
use std::fs::{self, File};
use std::io::prelude::*;
use std::path::PathBuf;
use uuid::Uuid;

use crate::cli::{self, GlobalOptions};
use crate::cli::{self, autocomplete, GlobalOptions};
use row::workflow::Workflow;
use row::{
workspace, Error, MultiProgressContainer, COMPLETED_DIRECTORY_NAME, DATA_DIRECTORY_NAME,
Expand All @@ -18,10 +19,12 @@ use row::{
#[derive(Args, Debug)]
pub struct Arguments {
/// Select the action to scan (defaults to all).
#[arg(short, long, display_order = 0)]
#[arg(short, long, display_order = 0,
add=ArgValueCandidates::new(autocomplete::get_action_candidates))]
action: Option<String>,

/// Select directories to scan (defaults to all). Use 'scan -' to read from stdin.
#[arg(add=ArgValueCandidates::new(autocomplete::get_directory_candidates))]
directories: Vec<PathBuf>,
}

Expand Down
7 changes: 5 additions & 2 deletions src/cli/status.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// Part of row, released under the BSD 3-Clause License.

use clap::Args;
use clap_complete::ArgValueCandidates;
use console::Style;
use indicatif::HumanCount;
use log::{debug, trace, warn};
Expand All @@ -10,7 +11,7 @@ use std::io::Write;
use std::path::PathBuf;
use wildmatch::WildMatch;

use crate::cli::{self, GlobalOptions};
use crate::cli::{self, autocomplete, GlobalOptions};
use crate::ui::{Alignment, Item, Row, Table};
use row::project::{Project, Status};
use row::workflow::ResourceCost;
Expand All @@ -20,14 +21,16 @@ use row::MultiProgressContainer;
#[derive(Args, Debug)]
pub struct Arguments {
/// Select the actions to summarize with a wildcard pattern.
#[arg(short, long, value_name = "pattern", default_value_t=String::from("*"), display_order=0)]
#[arg(short, long, value_name = "pattern", default_value_t=String::from("*"), display_order=0,
add=ArgValueCandidates::new(autocomplete::get_action_candidates))]
action: String,

/// Hide the table header.
#[arg(long, display_order = 0)]
no_header: bool,

/// Select directories to summarize (defaults to all). Use 'status -' to read from stdin.
#[arg(add=ArgValueCandidates::new(autocomplete::get_directory_candidates))]
directories: Vec<PathBuf>,

/// Show actions with completed directories.
Expand Down
7 changes: 5 additions & 2 deletions src/cli/submit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// Part of row, released under the BSD 3-Clause License.

use clap::Args;
use clap_complete::ArgValueCandidates;
use console::style;
use indicatif::HumanCount;
use log::{debug, info, trace, warn};
Expand All @@ -17,7 +18,7 @@ use std::sync::Arc;
use std::time::Instant;
use wildmatch::WildMatch;

use crate::cli::GlobalOptions;
use crate::cli::{autocomplete, GlobalOptions};
use row::format::HumanDuration;
use row::project::Project;
use row::workflow::{Action, ResourceCost};
Expand All @@ -26,10 +27,12 @@ use row::MultiProgressContainer;
#[derive(Args, Debug)]
pub struct Arguments {
/// Select the actions to summarize with a wildcard pattern.
#[arg(short, long, value_name = "pattern", default_value_t=String::from("*"), display_order=0)]
#[arg(short, long, value_name = "pattern", default_value_t=String::from("*"), display_order=0,
add=ArgValueCandidates::new(autocomplete::get_action_candidates))]
action: String,

/// Select directories to summarize (defaults to all).
#[arg(add=ArgValueCandidates::new(autocomplete::get_directory_candidates))]
directories: Vec<PathBuf>,

/// Skip confirmation check.
Expand Down
8 changes: 7 additions & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@

#![warn(clippy::pedantic)]

use clap::Parser;
use clap::{CommandFactory, Parser};
use clap_complete::env::CompleteEnv;
use clap_verbosity_flag::log::LevelFilter;
use indicatif::{MultiProgress, ProgressDrawTarget};
use indicatif_log_bridge::LogWrapper;
Expand All @@ -23,6 +24,11 @@ use ui::MultiProgressWriter;

fn main_detail() -> Result<(), Box<dyn Error>> {
let instant = Instant::now();

// Autocomplete
CompleteEnv::with_factory(Options::command).complete();

// Normal execution
let options = Options::parse();

let log_style;
Expand Down
Loading