Compare commits
17 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
95c394cbaf | ||
|
3637091341 | ||
|
4b8087bf8d | ||
|
3471ea3c0b | ||
|
bdd28da59e | ||
|
6e258ad2a4 | ||
|
9f7fea0cfa | ||
|
20a62f7be3 | ||
|
f5e8bd8e2c | ||
|
162890f731 | ||
|
5807c7cf9f | ||
|
90596e8670 | ||
|
cb6f3def3c | ||
|
f5e9fe8584 | ||
|
abc4367cdd | ||
|
e9b30934ac | ||
|
279092951b |
36
.drone.yml
36
.drone.yml
@ -15,15 +15,41 @@ steps:
|
|||||||
commands:
|
commands:
|
||||||
- '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: Minio Artifacts
|
||||||
|
# image: plugins/s3
|
||||||
|
# settings:
|
||||||
|
# bucket: artifacts
|
||||||
|
# access_key:
|
||||||
|
# from_secret: MINIO_ARTIFACTS_ACCESS_KEY
|
||||||
|
# secret_key:
|
||||||
|
# from_secret: MINIO_ARTIFACTS_SECRET_KEY
|
||||||
|
# source: dist/**/*
|
||||||
|
# target: live-cli/${DRONE_BUILD_CREATED}-${DRONE_COMMIT}
|
||||||
|
|
||||||
|
- name: Publish Artifacts
|
||||||
|
image: curlimages/curl
|
||||||
|
volumes:
|
||||||
|
- name: dist
|
||||||
|
path: /dist
|
||||||
|
environment:
|
||||||
|
GITEA_SVC_USERNAME:
|
||||||
|
from_secrete: GITEA_SVC_USERNAME
|
||||||
|
GITEA_SVC_PASSWORD:
|
||||||
|
from_secret: GITEA_SVC_PASSWORD
|
||||||
|
commands:
|
||||||
|
- sh -c 'set -ex; cd /dist; for f in *; do curl --user "drone-svc:$${GITEA_SVC_PASSWORD}" -X PUT https://gitea.austen-wares.com.com/api/packages/public/generic/$${DRONE_REPO_NAME}/$$(date -Isecond)-$${DRONE_COMMIT}/$${f}; done'
|
||||||
|
|
||||||
|
- name: Publish release
|
||||||
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:
|
||||||
|
@ -1 +1,5 @@
|
|||||||
/target
|
*
|
||||||
|
!/Cargo.lock
|
||||||
|
!/Cargo.toml
|
||||||
|
!/src
|
||||||
|
!/.cargo
|
||||||
|
180
Cargo.lock
generated
180
Cargo.lock
generated
@ -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.3.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"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "live-cli"
|
name = "live-cli"
|
||||||
version = "0.2.0"
|
version = "0.3.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
@ -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>"
|
||||||
|
@ -41,13 +41,13 @@ build:
|
|||||||
COPY ./Cargo.toml ./Cargo.lock .
|
COPY ./Cargo.toml ./Cargo.lock .
|
||||||
RUN \
|
RUN \
|
||||||
mkdir src && touch src/lib.rs && \
|
mkdir src && touch src/lib.rs && \
|
||||||
cargo build --offline --release --target "$TOOLCHAIN" --jobs 1 && \
|
cargo build --offline --release --target "$TOOLCHAIN" `#--jobs 1` && \
|
||||||
rm src/lib.rs && rmdir src && \
|
rm src/lib.rs && rmdir src && \
|
||||||
:
|
:
|
||||||
|
|
||||||
# Actually build the program
|
# Actually build the program
|
||||||
COPY . .
|
COPY . .
|
||||||
RUN cargo build --offline --release --target "$TOOLCHAIN" --jobs 1
|
RUN cargo build --offline --release --target "$TOOLCHAIN" `#--jobs 1`
|
||||||
|
|
||||||
ARG EXT
|
ARG EXT
|
||||||
ARG STRIP_CMD
|
ARG STRIP_CMD
|
||||||
|
@ -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 {
|
||||||
@ -90,11 +90,14 @@ fn run_inner(command_request: &CommandRequest) -> Result<CommandResult> {
|
|||||||
command.spawn()
|
command.spawn()
|
||||||
}?;
|
}?;
|
||||||
|
|
||||||
|
if command_request.1.is_some() {
|
||||||
let mut stdin = child.stdin.take().context("Could not take stdin")?;
|
let mut stdin = child.stdin.take().context("Could not take stdin")?;
|
||||||
let text_orig_clone = command_request.1.clone();
|
let text_orig_clone = command_request.1.clone();
|
||||||
|
|
||||||
std::thread::spawn(move || {
|
std::thread::spawn(move || {
|
||||||
let _result = stdin.write_all(text_orig_clone.as_bytes());
|
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()?;
|
||||||
|
200
src/main.rs
200
src/main.rs
@ -6,9 +6,10 @@ mod command;
|
|||||||
mod event;
|
mod event;
|
||||||
mod ui;
|
mod ui;
|
||||||
mod util;
|
mod util;
|
||||||
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;
|
||||||
@ -16,10 +17,11 @@ use crossbeam::channel::Receiver;
|
|||||||
use crossbeam::channel::Sender;
|
use crossbeam::channel::Sender;
|
||||||
use crossterm::event::DisableBracketedPaste;
|
use crossterm::event::DisableBracketedPaste;
|
||||||
use crossterm::event::EnableBracketedPaste;
|
use crossterm::event::EnableBracketedPaste;
|
||||||
|
use crossterm::event::KeyEvent;
|
||||||
|
use crossterm::event::KeyModifiers;
|
||||||
use event::EventMessage;
|
use event::EventMessage;
|
||||||
use parking_lot::RwLock;
|
use parking_lot::RwLock;
|
||||||
use ropey::Rope;
|
use ropey::Rope;
|
||||||
use std::str::FromStr;
|
|
||||||
use std::{
|
use std::{
|
||||||
io::{self, Write},
|
io::{self, Write},
|
||||||
sync::Arc,
|
sync::Arc,
|
||||||
@ -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
|
||||||
@ -68,15 +79,18 @@ pub struct CommandOptions {
|
|||||||
|
|
||||||
/// The position of the cursor
|
/// The position of the cursor
|
||||||
cmdline_position: u16,
|
cmdline_position: u16,
|
||||||
|
|
||||||
|
/// Command combined
|
||||||
|
combined_command: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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
|
||||||
@ -92,53 +106,31 @@ pub struct App {
|
|||||||
render_states: RwLock<RenderStates>,
|
render_states: RwLock<RenderStates>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CommandOptions {
|
impl Default for CommandOptions {
|
||||||
#[must_use]
|
fn default() -> Self {
|
||||||
pub fn from_template(template: &Template) -> Self {
|
Self {
|
||||||
let defaults = Self {
|
command: String::from("sh"),
|
||||||
command: template.command(),
|
|
||||||
cmdline_position: 0_u16,
|
cmdline_position: 0_u16,
|
||||||
hidden_options: Vec::new(),
|
hidden_options: vec!["-c"],
|
||||||
cmdline: String::new(),
|
cmdline: String::new(),
|
||||||
command_result: None,
|
command_result: None,
|
||||||
autorun: true,
|
autorun: true,
|
||||||
wordsplit: true,
|
|
||||||
};
|
|
||||||
|
|
||||||
match template {
|
|
||||||
Template::Awk => Self { ..defaults },
|
|
||||||
Template::Sh(_) => Self {
|
|
||||||
hidden_options: vec!["-c"],
|
|
||||||
wordsplit: false,
|
wordsplit: false,
|
||||||
..defaults
|
combined_command: String::new(),
|
||||||
},
|
|
||||||
Template::Jq => Self {
|
|
||||||
cmdline_position: 2,
|
|
||||||
cmdline: String::from("'.'"),
|
|
||||||
hidden_options: vec!["-C"],
|
|
||||||
..defaults
|
|
||||||
},
|
|
||||||
Template::Grep | Template::Rg => Self {
|
|
||||||
cmdline_position: 1,
|
|
||||||
cmdline: String::from("''"),
|
|
||||||
hidden_options: vec!["--color=always"],
|
|
||||||
..defaults
|
|
||||||
},
|
|
||||||
Template::Sed => Self {
|
|
||||||
cmdline_position: 3_u16,
|
|
||||||
cmdline: String::from("'s///g'"),
|
|
||||||
..defaults
|
|
||||||
},
|
|
||||||
Template::Perl => Self {
|
|
||||||
cmdline_position: 9_u16,
|
|
||||||
cmdline: String::from("-p -e 's///'"),
|
|
||||||
..defaults
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// impl App<'_> {
|
impl CommandOptions {
|
||||||
|
pub fn append_command(&mut self) {
|
||||||
|
if !self.combined_command.is_empty() {
|
||||||
|
self.combined_command += " | ";
|
||||||
|
}
|
||||||
|
|
||||||
|
self.combined_command += self.cmdline.as_ref();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl App {
|
impl App {
|
||||||
/// Constructs a new instance of `App`
|
/// Constructs a new instance of `App`
|
||||||
///
|
///
|
||||||
@ -146,19 +138,18 @@ impl App {
|
|||||||
///
|
///
|
||||||
/// * `command_request_tx` - The sender for the command request worker
|
/// * `command_request_tx` - The sender for the command request worker
|
||||||
/// * `input` - The stdin to be passed in to each invocation
|
/// * `input` - The stdin to be passed in to each invocation
|
||||||
/// * `template` - The template to use
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn from_template(
|
pub fn new(
|
||||||
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,
|
|
||||||
) -> 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,
|
||||||
command_options: Arc::new(RwLock::new(CommandOptions::from_template(template))),
|
command_options: Arc::new(RwLock::new(CommandOptions::default())),
|
||||||
message_rx,
|
message_rx,
|
||||||
command_request_tx,
|
command_request_tx,
|
||||||
render_states: RwLock::new(RenderStates::default()),
|
render_states: RwLock::new(RenderStates::default()),
|
||||||
@ -177,78 +168,31 @@ impl App {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum Template {
|
|
||||||
Sh(String),
|
|
||||||
Jq,
|
|
||||||
Grep,
|
|
||||||
Rg,
|
|
||||||
Sed,
|
|
||||||
Awk,
|
|
||||||
Perl,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FromStr for Template {
|
|
||||||
type Err = anyhow::Error;
|
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
||||||
match s.to_lowercase().trim() {
|
|
||||||
"jq" => Ok(Self::Jq),
|
|
||||||
"grep" => Ok(Self::Grep),
|
|
||||||
"rg" => Ok(Self::Rg),
|
|
||||||
"sed" => Ok(Self::Sed),
|
|
||||||
"awk" => Ok(Self::Awk),
|
|
||||||
"perl" => Ok(Self::Perl),
|
|
||||||
s @ ("sh" | "bash" | "zsh" | "dash") => Ok(Self::Sh(s.to_string())),
|
|
||||||
e => Err(anyhow!("{e} is not a supported command")),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Template {
|
|
||||||
#[must_use]
|
|
||||||
pub fn command(&self) -> String {
|
|
||||||
match self {
|
|
||||||
Self::Sh(s) => s.to_string(),
|
|
||||||
Self::Jq => String::from("jq"),
|
|
||||||
Self::Grep => String::from("grep"),
|
|
||||||
Self::Rg => String::from("rg"),
|
|
||||||
Self::Sed => String::from("sed"),
|
|
||||||
Self::Awk => String::from("awk"),
|
|
||||||
Self::Perl => String::from("perl"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() -> Result<()> {
|
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();
|
||||||
|
|
||||||
// Run the actual application
|
// Run the actual application
|
||||||
let app = App::from_template(
|
let mut app = App::new(message_rx, command_request_tx, text_orig);
|
||||||
message_rx,
|
|
||||||
command_request_tx,
|
|
||||||
text_orig,
|
|
||||||
&Template::from_str(&arg)?,
|
|
||||||
);
|
|
||||||
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,
|
||||||
@ -258,7 +202,7 @@ fn main() -> Result<()> {
|
|||||||
let backend = CrosstermBackend::new(stdout);
|
let backend = CrosstermBackend::new(stdout);
|
||||||
let mut terminal = Terminal::new(backend)?;
|
let mut terminal = Terminal::new(backend)?;
|
||||||
|
|
||||||
let res = run_app(&mut terminal, app);
|
let resulting_commandline = run_app(&mut terminal, &mut app);
|
||||||
|
|
||||||
// Restore terminal
|
// Restore terminal
|
||||||
disable_raw_mode()?;
|
disable_raw_mode()?;
|
||||||
@ -270,11 +214,13 @@ fn main() -> Result<()> {
|
|||||||
)?;
|
)?;
|
||||||
terminal.show_cursor()?;
|
terminal.show_cursor()?;
|
||||||
|
|
||||||
let res = res?;
|
let resulting_commandline = resulting_commandline?;
|
||||||
|
|
||||||
if let Some(res) = res {
|
if let Some(resulting_commandline) = resulting_commandline {
|
||||||
std::io::stderr().write_all(res.as_bytes())?;
|
// TODO: I do not want to collect the whole thing into a vec
|
||||||
|
app.command_options.read().command_result.as_ref().map(|r| std::io::stdout().write_all(&r.stdout.bytes().collect::<Vec<u8>>())).transpose()?;
|
||||||
std::io::stderr().write_all(b"\n")?;
|
std::io::stderr().write_all(b"\n")?;
|
||||||
|
std::io::stderr().write_all(resulting_commandline.as_bytes())?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -304,7 +250,7 @@ fn init_message_passing() -> (Receiver<EventMessage>, Sender<CommandRequest>) {
|
|||||||
|
|
||||||
#[allow(clippy::too_many_lines)]
|
#[allow(clippy::too_many_lines)]
|
||||||
#[cfg_attr(debug_assertions, instrument(skip(terminal, app)))]
|
#[cfg_attr(debug_assertions, instrument(skip(terminal, app)))]
|
||||||
fn run_app<B: Backend>(terminal: &mut Terminal<B>, app: App) -> Result<Option<String>> {
|
fn run_app<B: Backend>(terminal: &mut Terminal<B>, app: &mut App) -> Result<Option<String>> {
|
||||||
// When starting the app, ensure the command runs at least once
|
// When starting the app, ensure the command runs at least once
|
||||||
{
|
{
|
||||||
let mut command_options = app.command_options.write();
|
let mut command_options = app.command_options.write();
|
||||||
@ -332,6 +278,26 @@ fn run_app<B: Backend>(terminal: &mut Terminal<B>, app: App) -> Result<Option<St
|
|||||||
let mut command_options = app.command_options.write();
|
let mut command_options = app.command_options.write();
|
||||||
|
|
||||||
match crossterm_event {
|
match crossterm_event {
|
||||||
|
Event::Key(KeyEvent {
|
||||||
|
code: KeyCode::Char('p'),
|
||||||
|
modifiers: KeyModifiers::CONTROL,
|
||||||
|
..
|
||||||
|
}) => {
|
||||||
|
if command_options.command_result.is_some() {
|
||||||
|
command_options.append_command();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move stdout to stdin
|
||||||
|
if let Some(result) = &command_options.command_result {
|
||||||
|
app.text_orig = Arc::new(Some(result.stdout.to_string()));
|
||||||
|
app.text_orig_rope = Some(result.stdout.clone());
|
||||||
|
command_options.cmdline = String::new();
|
||||||
|
command_options.cmdline_position = 0;
|
||||||
|
if command_options.autorun {
|
||||||
|
app.run_command()?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Event::Key(key) => match key.code {
|
Event::Key(key) => match key.code {
|
||||||
KeyCode::Esc => {
|
KeyCode::Esc => {
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
@ -376,10 +342,10 @@ fn run_app<B: Backend>(terminal: &mut Terminal<B>, app: App) -> Result<Option<St
|
|||||||
command_options.cmdline_position = 0_u16;
|
command_options.cmdline_position = 0_u16;
|
||||||
}
|
}
|
||||||
KeyCode::Enter => {
|
KeyCode::Enter => {
|
||||||
return Ok(Some(format!(
|
if command_options.command_result.is_some() {
|
||||||
"{} {}",
|
command_options.append_command();
|
||||||
command_options.command, command_options.cmdline
|
}
|
||||||
)));
|
return Ok(Some(command_options.combined_command.to_string()));
|
||||||
}
|
}
|
||||||
KeyCode::Left => {
|
KeyCode::Left => {
|
||||||
command_options.cmdline_position =
|
command_options.cmdline_position =
|
||||||
|
41
src/ui.rs
41
src/ui.rs
@ -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,39 @@ 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(
|
|
||||||
|
let stdin_title = if command_options.combined_command.is_empty() {
|
||||||
|
String::from("Input")
|
||||||
|
} else {
|
||||||
|
format!("Input ({})", command_options.combined_command)
|
||||||
|
};
|
||||||
|
|
||||||
|
render_states.stdin = if let Some(text_orig_rope) = app.text_orig_rope.as_ref() {
|
||||||
|
lazy_render_rope_slice(
|
||||||
f,
|
f,
|
||||||
chunks[0],
|
chunks[0],
|
||||||
render_states.stdin.as_ref(),
|
render_states.stdin.as_ref(),
|
||||||
app.text_orig_rope.slice(..),
|
text_orig_rope.slice(..),
|
||||||
"Output",
|
stdin_title.as_str(),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
f.render_widget(
|
||||||
|
Paragraph::new("! No Stdin !")
|
||||||
|
.alignment(Alignment::Center)
|
||||||
|
.block(
|
||||||
|
Block::default()
|
||||||
|
.title(stdin_title.as_str())
|
||||||
|
.borders(Borders::ALL),
|
||||||
|
),
|
||||||
|
chunks[0],
|
||||||
);
|
);
|
||||||
|
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(
|
||||||
@ -61,6 +87,11 @@ pub fn draw<B: Backend>(f: &mut Frame<B>, app: &App) {
|
|||||||
// Render the output in the outpout region
|
// Render the output in the outpout region
|
||||||
if let Some(ref command_result) = command_options.command_result {
|
if let Some(ref command_result) = command_options.command_result {
|
||||||
ui_output(f, chunks[1], &mut render_states, command_result);
|
ui_output(f, chunks[1], &mut render_states, command_result);
|
||||||
|
} else {
|
||||||
|
f.render_widget(
|
||||||
|
Block::default().title("Output").borders(Borders::ALL),
|
||||||
|
chunks[1],
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
f.set_cursor(
|
f.set_cursor(
|
||||||
@ -131,7 +162,7 @@ fn lazy_render_rope_slice<'a, B: Backend>(
|
|||||||
output: Rect,
|
output: Rect,
|
||||||
previous_state: Option<&RenderState>,
|
previous_state: Option<&RenderState>,
|
||||||
data: RopeSlice<'_>,
|
data: RopeSlice<'_>,
|
||||||
block_title: &'static str,
|
block_title: &str,
|
||||||
) -> Option<RenderState> {
|
) -> Option<RenderState> {
|
||||||
let data = data
|
let data = data
|
||||||
.lines()
|
.lines()
|
||||||
|
Loading…
Reference in New Issue
Block a user