Skip to content

Commit

Permalink
Merge pull request #62 from glotzerlab/complete
Browse files Browse the repository at this point in the history
Shell autocomplete
  • Loading branch information
joaander authored Dec 5, 2024
2 parents 3c18956 + 6b2d16e commit 0425472
Show file tree
Hide file tree
Showing 13 changed files with 735 additions and 20 deletions.
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

0 comments on commit 0425472

Please sign in to comment.