summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authororhun <orhun@archlinux.org>2021-07-08 02:05:37 +0300
committerorhun <orhun@archlinux.org>2021-07-08 02:05:37 +0300
commit888a5d836d036e199bde044c08adc04a38d9464d (patch)
tree302fa7cf0c67921d5363a4b55b0e00d9eb95834e
parentcb1df0b004e04f7aa71ac5398355877f18e46ae4 (diff)
feat: Add `--select` option (#24)
-rw-r--r--README.md22
-rw-r--r--demo/gpg-tui-selection_mode.gifbin0 -> 459273 bytes
-rw-r--r--man/gpg-tui.13
-rw-r--r--src/app/handler.rs4
-rw-r--r--src/app/launcher.rs23
-rw-r--r--src/app/prompt.rs2
-rw-r--r--src/app/selection.rs2
-rw-r--r--src/app/state.rs10
-rw-r--r--src/args.rs9
-rw-r--r--src/main.rs9
10 files changed, 75 insertions, 9 deletions
diff --git a/README.md b/README.md
index 4ecb9ab..5ec5f7f 100644
--- a/README.md
+++ b/README.md
@@ -62,6 +62,7 @@ It aims to ease the key management operations such as listing/exporting/signing
- [Scrolling](#scrolling)
- [Options Menu](#options-menu)
- [Copy / Paste](#copy--paste)
+ - [Selection Mode](#selection-mode)
- [Detailed View](#detailed-view)
- [Search](#search)
- [Running commands](#running-commands)
@@ -289,6 +290,8 @@ OPTIONS:
-c, --color <color> Sets the accent color of the terminal [env: COLOR=] [default: gray]
-s, --style <style> Sets the style of the terminal [env: STYLE=] [default: plain]
[possible values: plain, colored]
+ --select <option> Enables the selection mode [env: SELECT=]
+ [possible values: key_id, key_fpr, user_id, row1, row2]
```
## Key Bindings
@@ -504,6 +507,25 @@ Instead of copying values with `copy` mode, you can use the `visual` mode which
![](demo/gpg-tui-visual_mode.gif)
+#### Selection Mode
+
+In the selection mode, key bindings that are responsible for showing the options menu (e.g. `enter`) are used for exiting the user interface and printing out the selection to the standard output. This is useful when you want to use **gpg-tui** in conjunction with shell commands/other tools.
+
+For switching to the selection mode, use the `--select` argument as follows:
+
+```sh
+gpg-tui --select <option>
+```
+
+`<option>` might be one of the following:
+
+- `key_id`: Key ID
+- `key_fpr`: Key fingerprint
+- `user_id`: User ID
+- `row<n>`: Contents of the nth row
+
+![](demo/gpg-tui-selection_mode.gif)
+
#### Detailed View
Press `Tab` to toggle the [detail level](#detail-levels) for the selected entry in the list. Number keys (e.g. `1`, `2`, `3`) can be also used to set a specific level.
diff --git a/demo/gpg-tui-selection_mode.gif b/demo/gpg-tui-selection_mode.gif
new file mode 100644
index 0000000..7dd092f
--- /dev/null
+++ b/demo/gpg-tui-selection_mode.gif
Binary files differ
diff --git a/man/gpg-tui.1 b/man/gpg-tui.1
index 03759b3..0d9046d 100644
--- a/man/gpg-tui.1
+++ b/man/gpg-tui.1
@@ -52,6 +52,9 @@ Sets the accent color of the terminal [env: COLOR=] [default: gray]
.TP
\fB\-s\fR, \fB\-\-style\fR <style>
Sets the style of the terminal [env: STYLE=] [default: plain] [possible values: plain, colored]
+.TP
+\fB\-\-select\fR <option>
+Enables the selection mode [env: SELECT=] [possible values: key_id, key_fpr, user_id, row1, row2]
.SH KEY BINDINGS
.SS USER INTERFACE
diff --git a/src/app/handler.rs b/src/app/handler.rs
index fa1cc18..7ad53c2 100644
--- a/src/app/handler.rs
+++ b/src/app/handler.rs
@@ -310,7 +310,9 @@ fn handle_key_event(key_event: KeyEvent, app: &mut App) -> Command {
}
}
Key::Char('o') | Key::Char(' ') | Key::Enter => {
- if app.state.show_options {
+ if let Some(select_type) = app.state.select {
+ Command::Copy(select_type)
+ } else if app.state.show_options {
app.options.selected().cloned().unwrap_or(Command::None)
} else if !app.keys_table.items.is_empty() {
Command::ShowOptions
diff --git a/src/app/launcher.rs b/src/app/launcher.rs
index 7212ff9..e3b897d 100644
--- a/src/app/launcher.rs
+++ b/src/app/launcher.rs
@@ -22,6 +22,7 @@ use std::path::Path;
use std::process::Command as OsCommand;
use std::str;
use std::str::FromStr;
+use std::time::Instant;
use tui::style::Color;
/// Max duration of prompt messages.
@@ -71,10 +72,20 @@ impl<'a> App<'a> {
.expect("failed to get public keys")
.to_vec(),
);
+ let state = State::from(args);
Ok(Self {
- state: State::from(args),
mode: Mode::Normal,
- prompt: Prompt::default(),
+ prompt: if state.select.is_some() {
+ Prompt {
+ output_type: OutputType::Action,
+ text: String::from("-- select --"),
+ clock: Some(Instant::now()),
+ ..Prompt::default()
+ }
+ } else {
+ Prompt::default()
+ },
+ state,
tab: Tab::Keys(KeyType::Public),
options: StatefulList::with_items(Vec::new()),
splash_screen: SplashScreen::new("splash.jpg", 12)?,
@@ -825,7 +836,11 @@ impl<'a> App<'a> {
};
match content {
Ok(content) => {
- if let Some(clipboard) = self.clipboard.as_mut() {
+ if self.state.select.is_some() {
+ self.state.exit_message = Some(content);
+ self.run_command(Command::Quit)?;
+ } else if let Some(clipboard) = self.clipboard.as_mut()
+ {
clipboard
.set_contents(content)
.expect("failed to set clipboard contents");
@@ -843,7 +858,7 @@ impl<'a> App<'a> {
Err(e) => {
self.prompt.set_output((
OutputType::Failure,
- format!("copy error: {}", e),
+ format!("selection error: {}", e),
));
}
}
diff --git a/src/app/prompt.rs b/src/app/prompt.rs
index d821f6c..45470ee 100644
--- a/src/app/prompt.rs
+++ b/src/app/prompt.rs
@@ -75,7 +75,7 @@ pub struct Prompt {
/// Command history.
pub history: Vec<String>,
/// Index of the selected command from history.
- history_index: usize,
+ pub history_index: usize,
}
impl Prompt {
diff --git a/src/app/selection.rs b/src/app/selection.rs
index bfb2c8b..c35f714 100644
--- a/src/app/selection.rs
+++ b/src/app/selection.rs
@@ -43,7 +43,7 @@ impl FromStr for Selection {
"key_fingerprint" | "key_fpr" | "fingerprint" | "fpr" => {
Ok(Self::KeyFingerprint)
}
- "key_user_id" | "user" => Ok(Self::KeyUserId),
+ "key_user_id" | "user" | "user_id" => Ok(Self::KeyUserId),
_ => Err(String::from("could not parse the type")),
}
}
diff --git a/src/app/state.rs b/src/app/state.rs
index 8cb4276..bc0444d 100644
--- a/src/app/state.rs
+++ b/src/app/state.rs
@@ -1,3 +1,4 @@
+use crate::app::selection::Selection;
use crate::args::Args;
use crate::widget::style::Color;
use tui::style::Color as TuiColor;
@@ -15,6 +16,10 @@ pub struct State {
pub show_options: bool,
/// Is the splash screen showing?
pub show_splash: bool,
+ /// Is the selection mode enabled?
+ pub select: Option<Selection>,
+ /// Exit message of the app.
+ pub exit_message: Option<String>,
}
impl Default for State {
@@ -25,6 +30,8 @@ impl Default for State {
color: Color::default().get(),
show_options: false,
show_splash: false,
+ select: None,
+ exit_message: None,
}
}
}
@@ -35,6 +42,7 @@ impl<'a> From<&'a Args> for State {
colored: args.style == *"colored",
color: args.color.get(),
show_splash: args.splash,
+ select: args.select,
..Self::default()
}
}
@@ -62,5 +70,7 @@ mod tests {
assert_eq!(TuiColor::Gray, state.color);
assert_eq!(false, state.show_options);
assert_eq!(false, state.show_splash);
+ assert_eq!(None, state.select);
+ assert_eq!(None, state.exit_message);
}
}
diff --git a/src/args.rs b/src/args.rs
index a3ae868..0342866 100644
--- a/src/args.rs
+++ b/src/args.rs
@@ -1,6 +1,7 @@
//! Command-line argument parser.
use crate::app::banner::BANNERS;
+use crate::app::selection::Selection;
use crate::widget::style::Color;
use structopt::clap::AppSettings;
use structopt::StructOpt;
@@ -48,6 +49,14 @@ pub struct Args {
default_value = "plain", env
)]
pub style: String,
+ /// Enables the selection mode.
+ #[structopt(
+ long,
+ value_name = "option",
+ possible_values = &["key_id", "key_fpr", "user_id", "row1", "row2"],
+ env
+ )]
+ pub select: Option<Selection>,
}
impl Args {
diff --git a/src/main.rs b/src/main.rs
index a6c1f5e..effc241 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -39,6 +39,11 @@ fn main() -> Result<()> {
_ => {}
}
}
- // Exit.
- tui.exit()
+ // Exit the user interface.
+ tui.exit()?;
+ // Print the exit message if any.
+ if let Some(message) = app.state.exit_message {
+ println!("{}", message);
+ }
+ Ok(())
}