Add clap
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
Austen Adler 2022-12-27 19:58:55 -05:00
parent e9b30934ac
commit abc4367cdd
6 changed files with 259 additions and 40 deletions

View File

@ -16,14 +16,16 @@ steps:
- 'file /var/run/docker.sock || :' - 'file /var/run/docker.sock || :'
- 'pwd' - 'pwd'
- 'earthly +all' - 'earthly +all'
# TODO: use more than one target
# - 'earthly --build-arg TOOLCHAIN=x86_64-unknown-linux-musl --build-arg STRIP_CMD=x86_64-linux-gnu-strip +build'
- 'cp -v ./dist/* /dist/' - 'cp -v ./dist/* /dist/'
- name: Gitea Artifacts - name: Gitea Artifacts
image: plugins/gitea-release image: plugins/gitea-release
when:
event:
- tag
settings: settings:
api_key: "$${GITEA_API_KEY}" api_key:
from_secret: GITEA_API_KEY
base_url: https://gitea.austen-wares.com base_url: https://gitea.austen-wares.com
files: dist/* files: dist/*
volumes: volumes:

180
Cargo.lock generated
View File

@ -32,7 +32,7 @@ version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
dependencies = [ dependencies = [
"hermit-abi", "hermit-abi 0.1.19",
"libc", "libc",
"winapi", "winapi",
] ]
@ -70,6 +70,12 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df8670b8c7b9dae1793364eafadf7239c40d669904660c5960d74cfd80b46a53" checksum = "df8670b8c7b9dae1793364eafadf7239c40d669904660c5960d74cfd80b46a53"
[[package]]
name = "cc"
version = "1.0.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a20104e2335ce8a659d6dd92a51a767a0c062599c73b343fd152cb401e828c3d"
[[package]] [[package]]
name = "cfg-if" name = "cfg-if"
version = "0.1.10" version = "0.1.10"
@ -82,6 +88,43 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "clap"
version = "4.0.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7db700bc935f9e43e88d00b0850dae18a63773cfbec6d8e070fccf7fef89a39"
dependencies = [
"bitflags",
"clap_derive",
"clap_lex",
"is-terminal",
"once_cell",
"strsim",
"termcolor",
]
[[package]]
name = "clap_derive"
version = "4.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0177313f9f02afc995627906bbd8967e2be069f5261954222dac78290c2b9014"
dependencies = [
"heck",
"proc-macro-error",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "clap_lex"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d4198f73e42b4936b35b5bb248d81d2b595ecb170da0bac7655c54eedfa8da8"
dependencies = [
"os_str_bytes",
]
[[package]] [[package]]
name = "cpufeatures" name = "cpufeatures"
version = "0.2.5" version = "0.2.5"
@ -213,6 +256,27 @@ dependencies = [
"winapi", "winapi",
] ]
[[package]]
name = "errno"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1"
dependencies = [
"errno-dragonfly",
"libc",
"winapi",
]
[[package]]
name = "errno-dragonfly"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
dependencies = [
"cc",
"libc",
]
[[package]] [[package]]
name = "filedescriptor" name = "filedescriptor"
version = "0.8.2" version = "0.8.2"
@ -262,6 +326,12 @@ dependencies = [
"wasi 0.11.0+wasi-snapshot-preview1", "wasi 0.11.0+wasi-snapshot-preview1",
] ]
[[package]]
name = "heck"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9"
[[package]] [[package]]
name = "hermit-abi" name = "hermit-abi"
version = "0.1.19" version = "0.1.19"
@ -271,12 +341,43 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "hermit-abi"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7"
dependencies = [
"libc",
]
[[package]] [[package]]
name = "hex" name = "hex"
version = "0.4.3" version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
[[package]]
name = "io-lifetimes"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46112a93252b123d31a119a8d1a1ac19deac4fac6e0e8b0df58f0d4e5870e63c"
dependencies = [
"libc",
"windows-sys",
]
[[package]]
name = "is-terminal"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28dfb6c8100ccc63462345b67d1bbc3679177c75ee4bf59bf29c8b1d110b8189"
dependencies = [
"hermit-abi 0.2.6",
"io-lifetimes",
"rustix",
"windows-sys",
]
[[package]] [[package]]
name = "lazy_static" name = "lazy_static"
version = "1.4.0" version = "1.4.0"
@ -289,13 +390,20 @@ version = "0.2.138"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8" checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8"
[[package]]
name = "linux-raw-sys"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4"
[[package]] [[package]]
name = "live-cli" name = "live-cli"
version = "0.1.0" version = "0.2.0"
dependencies = [ dependencies = [
"ansi4tui", "ansi4tui",
"anyhow", "anyhow",
"atty", "atty",
"clap",
"crossbeam", "crossbeam",
"crossterm", "crossterm",
"parking_lot", "parking_lot",
@ -419,6 +527,12 @@ dependencies = [
"num-traits", "num-traits",
] ]
[[package]]
name = "os_str_bytes"
version = "6.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee"
[[package]] [[package]]
name = "overload" name = "overload"
version = "0.1.1" version = "0.1.1"
@ -508,6 +622,30 @@ version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
[[package]]
name = "proc-macro-error"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
dependencies = [
"proc-macro-error-attr",
"proc-macro2",
"quote",
"syn",
"version_check",
]
[[package]]
name = "proc-macro-error-attr"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
dependencies = [
"proc-macro2",
"quote",
"version_check",
]
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.47" version = "1.0.47"
@ -624,6 +762,20 @@ dependencies = [
"str_indices", "str_indices",
] ]
[[package]]
name = "rustix"
version = "0.36.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4feacf7db682c6c329c4ede12649cd36ecab0f3be5b7d74e6a20304725db4549"
dependencies = [
"bitflags",
"errno",
"io-lifetimes",
"libc",
"linux-raw-sys",
"windows-sys",
]
[[package]] [[package]]
name = "scopeguard" name = "scopeguard"
version = "1.1.0" version = "1.1.0"
@ -738,6 +890,12 @@ version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f026164926842ec52deb1938fae44f83dfdb82d0a5b0270c5bd5935ab74d6dd" checksum = "5f026164926842ec52deb1938fae44f83dfdb82d0a5b0270c5bd5935ab74d6dd"
[[package]]
name = "strsim"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]] [[package]]
name = "syn" name = "syn"
version = "1.0.105" version = "1.0.105"
@ -749,6 +907,15 @@ dependencies = [
"unicode-ident", "unicode-ident",
] ]
[[package]]
name = "termcolor"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755"
dependencies = [
"winapi-util",
]
[[package]] [[package]]
name = "terminfo" name = "terminfo"
version = "0.7.3" version = "0.7.3"
@ -988,6 +1155,15 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
dependencies = [
"winapi",
]
[[package]] [[package]]
name = "winapi-x86_64-pc-windows-gnu" name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0" version = "0.4.0"

View File

@ -17,6 +17,7 @@ parking_lot = "0.12.1"
tracing = { version = "0.1.37", features = ["release_max_level_off"] } tracing = { version = "0.1.37", features = ["release_max_level_off"] }
tracing-subscriber = "0.3.16" tracing-subscriber = "0.3.16"
ropey = "1.5.0" ropey = "1.5.0"
clap = { version = "4.0.32", features = ["derive"] }
[package.metadata.deb] [package.metadata.deb]
maintainer = "Austen Adler <agadler@austenadler.com>" maintainer = "Austen Adler <agadler@austenadler.com>"

View File

@ -13,7 +13,7 @@ use std::{
process::{Command, Stdio}, process::{Command, Stdio},
}; };
pub type CommandRequest = (Arc<RwLock<CommandOptions>>, Arc<String>); pub type CommandRequest = (Arc<RwLock<CommandOptions>>, Arc<Option<String>>);
#[derive(Debug)] #[derive(Debug)]
pub enum CommandCompleted { pub enum CommandCompleted {
@ -34,8 +34,8 @@ pub fn command_event_loop(
) -> Result<()> { ) -> Result<()> {
loop { loop {
match command_request_receiver.recv() { match command_request_receiver.recv() {
// TODO: Drain the command request channel so we only run the command once with the latest value // TODO: Drain the command request channel so we only run the command once with the latest value
// Could use https://docs.rs/single_value_channel/latest/single_value_channel/ // Could use https://docs.rs/single_value_channel/latest/single_value_channel/
Ok(command_request) => { Ok(command_request) => {
event_sender.send(EventMessage::CommandCompleted( event_sender.send(EventMessage::CommandCompleted(
match run_inner(&command_request) { match run_inner(&command_request) {
@ -66,7 +66,6 @@ fn run_inner(command_request: &CommandRequest) -> Result<CommandResult> {
let mut command = Command::new(&request.command); let mut command = Command::new(&request.command);
command command
.stdin(Stdio::piped())
.stdout(Stdio::piped()) .stdout(Stdio::piped())
.stderr(Stdio::piped()) .stderr(Stdio::piped())
.args(&request.hidden_options); .args(&request.hidden_options);
@ -85,16 +84,21 @@ fn run_inner(command_request: &CommandRequest) -> Result<CommandResult> {
command.arg(&request.cmdline); command.arg(&request.cmdline);
} }
command.stdin(Stdio::piped());
std::mem::drop(request); std::mem::drop(request);
command.spawn() command.spawn()
}?; }?;
let mut stdin = child.stdin.take().context("Could not take stdin")?; if command_request.1.is_some() {
let text_orig_clone = command_request.1.clone(); let mut stdin = child.stdin.take().context("Could not take stdin")?;
std::thread::spawn(move || { let text_orig_clone = command_request.1.clone();
let _result = stdin.write_all(text_orig_clone.as_bytes());
}); std::thread::spawn(move || {
let _result = stdin.write_all(text_orig_clone.as_ref().as_ref().unwrap().as_bytes());
});
}
// Collect the output // Collect the output
let output = child.wait_with_output()?; let output = child.wait_with_output()?;

View File

@ -8,7 +8,9 @@ mod ui;
mod util; mod util;
use anyhow::anyhow; use anyhow::anyhow;
use anyhow::bail; use anyhow::bail;
use anyhow::Context;
use anyhow::Result; use anyhow::Result;
use clap::Parser;
use command::CommandCompleted; use command::CommandCompleted;
use command::CommandRequest; use command::CommandRequest;
use command::CommandResult; use command::CommandResult;
@ -36,9 +38,9 @@ use crossterm::{
terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen}, terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
}; };
// Tracing only
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
use { use {
// Tracing
std::fs::File, std::fs::File,
tracing::instrument, tracing::instrument,
tracing::Level, tracing::Level,
@ -46,6 +48,15 @@ use {
tracing_subscriber::{filter, prelude::*}, tracing_subscriber::{filter, prelude::*},
}; };
#[derive(Parser)]
pub struct AppArgs {
#[clap(short, long, help = "Slurp stdin as input")]
stdin: bool,
#[clap(default_value = "sh")]
command: String,
}
/// The state of options for the command /// The state of options for the command
pub struct CommandOptions { pub struct CommandOptions {
/// The actual command to be called /// The actual command to be called
@ -73,10 +84,10 @@ pub struct CommandOptions {
/// The state of the application /// The state of the application
pub struct App { pub struct App {
/// Original text /// Original text
text_orig: Arc<String>, text_orig: Arc<Option<String>>,
/// Original text (for ui) /// Original text (for ui)
text_orig_rope: Rope, text_orig_rope: Option<Rope>,
// text_orig_formatted: Arc<String> // text_orig_formatted: Arc<String>
/// The list of options for a command, given in an RwLock so the command runner can update it /// The list of options for a command, given in an RwLock so the command runner can update it
@ -151,10 +162,11 @@ impl App {
pub fn from_template( pub fn from_template(
message_rx: Receiver<EventMessage>, message_rx: Receiver<EventMessage>,
command_request_tx: Sender<CommandRequest>, command_request_tx: Sender<CommandRequest>,
input: String, input: Option<String>,
template: &Template, template: &Template,
) -> Self { ) -> Self {
let text_orig_rope = Rope::from_str(&input); // let text_orig_rope = Rope::from_str(&input);
let text_orig_rope = input.as_ref().map(|s| Rope::from_str(s));
Self { Self {
text_orig: Arc::new(input), text_orig: Arc::new(input),
text_orig_rope, text_orig_rope,
@ -222,19 +234,19 @@ fn main() -> Result<()> {
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
enable_tracing(); enable_tracing();
// Error if we aren't getting any stdin let args = AppArgs::parse();
if atty::is(atty::Stream::Stdin) {
bail!("You must send stdin to this command");
}
// Get the arguments
let arg = match std::env::args().nth(1) {
Some(a) => a,
None => bail!("You must pass a command"),
};
// Slurp all input // Slurp all input
let text_orig = io::read_to_string(io::stdin())?; let text_orig = match (args.stdin, atty::is(atty::Stream::Stdin)) {
// The requested stdin, but it's a tty
(true, true) => bail!("Stdin was requested with, but stdin is a tty"),
// They did not request stdin, and they didn't pipe to us
(false, true) => None,
// Someone is piping us something
(_, false) => Some(io::read_to_string(io::stdin()).context("Could not read stdin")?),
};
// Start the command worker thread // Start the command worker thread
let (message_rx, command_request_tx) = init_message_passing(); let (message_rx, command_request_tx) = init_message_passing();
@ -244,11 +256,10 @@ fn main() -> Result<()> {
message_rx, message_rx,
command_request_tx, command_request_tx,
text_orig, text_orig,
&Template::from_str(&arg)?, &Template::from_str(&args.command)?,
); );
enable_raw_mode()?; enable_raw_mode()?;
let mut stdout = io::stdout(); let mut stdout = io::stdout();
// execute!(stdout, EnterAlternateScreen, EnableMouseCapture)?;
execute!( execute!(
stdout, stdout,
EnterAlternateScreen, EnterAlternateScreen,

View File

@ -9,7 +9,7 @@ use tracing::instrument;
use tracing::Level; use tracing::Level;
use tui::{ use tui::{
backend::Backend, backend::Backend,
layout::{Constraint, Direction, Layout, Rect}, layout::{Alignment, Constraint, Direction, Layout, Rect},
widgets::{Block, Borders, Paragraph}, widgets::{Block, Borders, Paragraph},
Frame, Frame,
}; };
@ -32,13 +32,38 @@ pub fn draw<B: Backend>(f: &mut Frame<B>, app: &App) {
event!(Level::INFO, "Rendering orig"); event!(Level::INFO, "Rendering orig");
// lazy_render_rope_slice(chunks[0], render_states.stdout) // lazy_render_rope_slice(chunks[0], render_states.stdout)
render_states.stdout = lazy_render_rope_slice( render_states.stdout = if let Some(text_orig_rope) = app.text_orig_rope.as_ref() {
f, lazy_render_rope_slice(
chunks[0], f,
render_states.stdin.as_ref(), chunks[0],
app.text_orig_rope.slice(..), render_states.stdin.as_ref(),
"Output", text_orig_rope.slice(..),
); "Output",
)
} else {
f.render_widget(
Paragraph::new("! No Stdin !")
.alignment(Alignment::Center)
.block(Block::default().title("Output").borders(Borders::ALL)),
chunks[0], // Layout::default()
// .direction(Direction::Vertical)
// .constraints(
// [
// Constraint::Percentage(50),
// Constraint::Length(1),
// Constraint::Min(0),
// ]
// .as_ref(),
// )
// .split(chunks[0])[1],
);
Some(RenderState {
// TODO
size: chunks[0],
input_hash: 0,
})
};
event!(Level::INFO, "Rendering textbox"); event!(Level::INFO, "Rendering textbox");
f.render_widget( f.render_widget(
Paragraph::new(command_options.cmdline.as_ref()).block( Paragraph::new(command_options.cmdline.as_ref()).block(