From dd4746d4d72937e6d3a2aaa0bbcd4942c3210459 Mon Sep 17 00:00:00 2001 From: Nazmul Idris Date: Sun, 17 Dec 2023 16:49:19 -0800 Subject: [PATCH] [tuify][cmdr] Move giti.rs from tuify to cmdr --- CHANGELOG.md | 16 ++-- cmdr/Cargo.toml | 24 ++++- cmdr/README.md | 109 ++++++++++++---------- cmdr/run.nu | 4 +- {tuify => cmdr}/src/bin/giti.rs | 18 +++- {tuify => cmdr}/src/giti/branch/delete.rs | 55 +++++++++-- cmdr/src/giti/branch/mod.rs | 19 ++++ cmdr/src/giti/mod.rs | 19 ++++ cmdr/src/lib.rs | 8 +- cmdr/src/{entry_point => rc}/app.rs | 2 +- cmdr/src/{entry_point => rc}/mod.rs | 0 tuify/Cargo.toml | 8 +- tuify/README.md | 12 --- tuify/run.nu | 6 -- tuify/src/giti/branch/mod.rs | 2 - tuify/src/giti/mod.rs | 2 - tuify/src/lib.rs | 2 - 17 files changed, 199 insertions(+), 107 deletions(-) rename {tuify => cmdr}/src/bin/giti.rs (91%) rename {tuify => cmdr}/src/giti/branch/delete.rs (85%) create mode 100644 cmdr/src/giti/branch/mod.rs create mode 100644 cmdr/src/giti/mod.rs rename cmdr/src/{entry_point => rc}/app.rs (99%) rename cmdr/src/{entry_point => rc}/mod.rs (100%) delete mode 100644 tuify/src/giti/branch/mod.rs delete mode 100644 tuify/src/giti/mod.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 69b8d98e7..c8e4a5cbe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -64,6 +64,15 @@ ### r3bl-cmdr first release +Added: + - Binary target for `giti`. This is an interactive git client that is tuified. It is a + productivity tool for git workflows, and is meant as a replacement for directly using + `git`. This also serves as a real world example of using the `r3bl_tuify` crate. + - View all the `giti branch` subcommands (e.g. `delete`, `checkout`, `new`, etc.) and + select one subcommand using the `select_from_list()` when `giti branch` runs. + - Delete one or more branches using `select_from_list()` when `giti branch delete` + command runs. + ## `r3bl_tuify` @@ -82,13 +91,6 @@ and Windows. Add many different themes to choose from. - Added: - - Binary target for `giti`. This is an interactive git client that is tuified. It is a - productivity tool for git workflows, and is meant as a replacement for directly using - `git`. This also serves as a real world example of using the `r3bl_tuify` crate. - - View all the `giti branch` subcommands (e.g. `delete`, `checkout`, `new`, etc.) and - select one subcommand using the `select_from_list()` when `giti branch` runs. - - Delete one or more branches using `select_from_list()` when `giti branch delete` - command runs. - `Ctrl + c` now behaves just like the `Escape` key. In the past, pressing `Ctrl + c` would do nothing the user could not exit the app by pressing this shortcut. - More code quality and ability to test the main event loop, by creating a new diff --git a/cmdr/Cargo.toml b/cmdr/Cargo.toml index 5b6b3c88c..3d6a8b585 100644 --- a/cmdr/Cargo.toml +++ b/cmdr/Cargo.toml @@ -22,6 +22,14 @@ documentation = "https://developerlife.com/category/Rust/" # More info on default-run: https://stackoverflow.com/a/51790493/2085356 default-run = "rc" +[[bin]] +name = "giti" +path = "src/bin/giti.rs" + +[[bin]] +name = "rc" +path = "src/bin/rc.rs" + # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] @@ -29,12 +37,24 @@ default-run = "rc" # Tokio. tokio = { version = "1.24.1", features = ["full"] } -# CLI argument parser. -clap = { version = "4.1.1", features = ["derive"] } +# Clap. +# More info: https://stackoverflow.com/a/76131914/2085356 +clap = { version = "4.4.6", features = ["derive", "wrap_help"] } +reedline = "0.27.1" # serde-json serde_json = "1.0.91" # R3BL crates (from this mono repo). +r3bl_ansi_color = { path = "../ansi_color", version = "0.6.9" } r3bl_rs_utils_core = { path = "../core", version = "0.9.9" } r3bl_tui = { path = "../tui", version = "0.3.10" } +r3bl_tuify = { path = "../tuify", version = "0.1.21" } + +# Logging. +is-terminal = "0.4.9" +log = { version = "0.4.20", features = ["std"] } + +[dev-dependencies] +pretty_assertions = "1.4.0" +serial_test = "2.0.0" diff --git a/cmdr/README.md b/cmdr/README.md index 3e543d292..1acc9578e 100644 --- a/cmdr/README.md +++ b/cmdr/README.md @@ -5,20 +5,20 @@ # r3bl-cmdr - - [Context](#context) -- [This binary crate: r3bl-cmdr](#this-binary-crate-r3bl-cmdr) -- [Building & running locally](#building--running-locally) -- [Contributing](#contributing) +- [Run giti binary target](#run-giti-binary-target) +- [Run r3bl-cmdr or rc binary target](#run-r3bl-cmdr-or-rc-binary-target) +- [Build, run, test tasks](#build-run-test-tasks) + - [Prerequisites](#prerequisites) + - [Nu shell scripts to build, run, test etc.](#nu-shell-scripts-to-build-run-test-etc) ## Context - R3BL @@ -61,9 +61,19 @@ it. 2. integrations w/ github issues 3. integrations w/ calendar, email, contacts APIs -## This binary crate: r3bl-cmdr - +## Run `giti` binary target + + +1. Move to `./tuify` folder in your terminal +2. Run `nu run.nu install` to install `giti` locally to `~/.cargo/bin` +3. Run `giti` from anywhere on your system +4. To delete one or more branches in your repo run `giti branch delete` + +[![asciicast](https://asciinema.org/a/14V8v3OKKYvDkUDkRFiMDsCNg.svg)](https://asciinema.org/a/14V8v3OKKYvDkUDkRFiMDsCNg) +## Run `r3bl-cmdr` or `rc` binary target + + `r3bl-cmdr` is the second thing that's described above. It contains a set of apps for developers by developers. It is engineered to enhance your: @@ -75,44 +85,47 @@ developers. It is engineered to enhance your: Our goal is to put a smile on your face every time you use this product. -## Building & running locally - - - -You can run it using `cargo run`. There are 2 other ways to launch it if you install it on your -machine both that involve a little less typing. - -```sh -cargo install --path . -r3bl-cmdr # this is the same as `cargo run` or `cargo run --bin r3bl-cmdr` -rc # this is an alias for `r3bl-cmdr`, equivalent to `cargo run --bin rc`` -``` - -The `Cargo.toml` file contains a `[dependencies]` section which lists all the dependencies that this -crate has, one of which is a -[path dependency](https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#multiple-locations) -on the `r3bl_rs_utils` crate. The creates.io version uses the `r3bl_rs_utils` crate from the -crates.io repository, but your local copy will use the folder specified in the path. - -> We plan to remove the `path` dependency when this crate is ready to be used by end users. -> Currently it early WIP so it has this dependency for ease of development. - -So, to build and run this locally, you have to clone the -[r3bl_rs_utils](https://github.com/r3bl-org/r3bl_rs_utils) repo so that it shares the same parent as -this crate. Here's a sample folder structure. - -```text -├── github -│   ├── r3bl-cmdr -│ └── r3bl-rs-utils -``` - -## Contributing - - - -This binary crate is being developed as a set of examples. The actual product will emerge as these -examples are evolved into features of the actual product, which is intended to be released to -developers. - -Please read our [community contributing guidelines here](./CONTRIBUTING.md). +## Build, run, test tasks + + +### Prerequisites + + +🌠 In order for these to work you have to install the Rust toolchain, `nu`, `cargo-watch`, `bat`, +and `flamegraph` on your system. Here are the instructions: + +1. Install the Rust toolchain using `rustup` by following the instructions + [here](https://rustup.rs/). +1. Install `cargo-watch` using `cargo install cargo-watch`. +1. Install `flamegraph` using `cargo install flamegraph`. +1. Install `bat` using `cargo install bat`. +1. Install [`nu`](https://crates.io/crates/nu) shell on your system using `cargo install nu`. It is + available for Linux, macOS, and Windows. + +### Nu shell scripts to build, run, test etc. + + +| Command | Description | +| ----------------------------------------- | ------------------------------------------------- | +| `nu run.nu run` | Run the default binary target | +| `nu run.nu install` | Install `giti` and `rc` locally to `~/.cargo/bin` | +| `nu run.nu build` | Build | +| `nu run.nu clean` | Clean | +| `nu run.nu all` | All | +| `nu run.nu run-with-flamegraph-profiling` | Run examples with flamegraph profiling | +| `nu run.nu test` | Run tests | +| `nu run.nu clippy` | Run clippy | +| `nu run.nu docs` | Build docs | +| `nu run.nu serve-docs` | Serve docs over VSCode Remote SSH session. | +| `nu run.nu upgrade-deps` | Upgrade deps | +| `nu run.nu rustfmt` | Run rustfmt | + +The following commands will watch for changes in the source folder and re-run: + +| Command | Description | +| ------------------------------------------------------ | ---------------------------------- | +| `nu run.nu watch-run` | Watch run | +| `nu run.nu watch-all-tests` | Watch all test | +| `nu run.nu watch-one-test ` | Watch one test | +| `nu run.nu watch-clippy` | Watch clippy | +| `nu run.nu watch-macro-expansion-one-test ` | Watch macro expansion for one test | diff --git a/cmdr/run.nu b/cmdr/run.nu index dca974661..a5289a619 100755 --- a/cmdr/run.nu +++ b/cmdr/run.nu @@ -150,11 +150,11 @@ def clean [] { } def run [] { - cargo run --example main_interactive -q + cargo run } def install [] { - cargo install --path . + cargo install --path . --force } def run-with-flamegraph [] { diff --git a/tuify/src/bin/giti.rs b/cmdr/src/bin/giti.rs similarity index 91% rename from tuify/src/bin/giti.rs rename to cmdr/src/bin/giti.rs index 7da05a235..8306b88a4 100644 --- a/tuify/src/bin/giti.rs +++ b/cmdr/src/bin/giti.rs @@ -18,11 +18,18 @@ //! For more information on how to use CLAP and Tuify, please read this tutorial: //! -use crate::giti::branch::delete::try_delete_branch; use clap::{Args, Parser, Subcommand, ValueEnum}; use clap_config::*; -use r3bl_rs_utils_core::{call_if_true, log_debug, log_error, try_to_set_log_level, CommonResult}; -use r3bl_tuify::{giti_ui_templates::ask_user_to_select_from_list, *}; +use giti::{branch::delete::try_delete_branch, + giti_ui_templates::ask_user_to_select_from_list, + *}; +use r3bl_cmdr::{giti, DEVELOPMENT_MODE}; +use r3bl_rs_utils_core::{call_if_true, + log_debug, + log_error, + try_to_set_log_level, + CommonResult}; +use r3bl_tuify::SelectionMode; fn main() { // If no args are passed, the following line will fail, and help will be printed @@ -91,7 +98,8 @@ pub fn get_giti_command_subcommand_names(arg: CLICommand) -> Vec { CLICommand::Branch { .. } => BranchSubcommand::value_variants() .iter() .map(|subcommand| { - let lower_case_subcommand = format!("{:?}", subcommand).to_ascii_lowercase(); + let lower_case_subcommand = + format!("{:?}", subcommand).to_ascii_lowercase(); lower_case_subcommand }) .collect(), @@ -102,6 +110,8 @@ pub fn get_giti_command_subcommand_names(arg: CLICommand) -> Vec { /// - /// - mod clap_config { + use r3bl_tuify::SelectionMode; + use super::*; #[derive(Debug, Parser)] diff --git a/tuify/src/giti/branch/delete.rs b/cmdr/src/giti/branch/delete.rs similarity index 85% rename from tuify/src/giti/branch/delete.rs rename to cmdr/src/giti/branch/delete.rs index 03c6dd45f..bc2cae6ca 100644 --- a/tuify/src/giti/branch/delete.rs +++ b/cmdr/src/giti/branch/delete.rs @@ -1,8 +1,27 @@ -use self::giti_ui_templates::ask_user_to_select_from_list; -use crate::*; +/* + * Copyright (c) 2023 R3BL LLC + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +use std::process::Command; + use r3bl_ansi_color::{AnsiStyledText, Color, Style}; use r3bl_rs_utils_core::{log_error, CommonError, CommonErrorType, CommonResult}; -use std::process::Command; +use r3bl_tuify::{SelectionMode, DELETE_BRANCH, DELETE_BRANCHES, EXIT}; + +use self::giti_ui_templates::ask_user_to_select_from_list; pub fn try_delete_branch() -> CommonResult<()> { giti_ui_templates::multi_select_instruction_header(); @@ -51,13 +70,17 @@ pub fn try_delete_branch() -> CommonResult<()> { match Selection::from(selected) { Delete => { let mut command = - inner::run_git_command_to_delete_branches_on_all_branches(&branches); + inner::run_git_command_to_delete_branches_on_all_branches( + &branches, + ); let output = command.output()?; if output.status.success() { if num_of_branches == 1 { inner::display_one_branch_deleted_success_message(&branches); } else { - inner::display_all_branches_deleted_success_messages(&branches); + inner::display_all_branches_deleted_success_messages( + &branches, + ); } } else { inner::display_correct_error_message(branches, output); @@ -82,7 +105,8 @@ pub fn try_delete_branch() -> CommonResult<()> { impl From> for Selection { fn from(selected: Vec) -> Selection { - let selected_to_delete_one_branch = selected[0] == DELETE_BRANCH.to_string(); + let selected_to_delete_one_branch = + selected[0] == DELETE_BRANCH.to_string(); let selected_to_delete_multiple_branches = selected[0] == DELETE_BRANCHES.to_string(); let selected_to_exit = selected[0] == EXIT.to_string(); @@ -99,9 +123,14 @@ pub fn try_delete_branch() -> CommonResult<()> { } mod inner { + use r3bl_tuify::{FAILED_COLOR, LIGHT_GRAY_COLOR, SUCCESS_COLOR}; + use super::*; - pub fn display_correct_error_message(branches: Vec, output: std::process::Output) { + pub fn display_correct_error_message( + branches: Vec, + output: std::process::Output, + ) { if branches.len() == 1 { let branch = &branches[0]; AnsiStyledText { @@ -199,9 +228,14 @@ pub fn try_execute_git_command_to_get_branches() -> CommonResult> { } pub mod giti_ui_templates { + use r3bl_rs_utils_core::{ch, ChUnit}; + use r3bl_tuify::{get_size, + select_from_list, + StyleSheet, + DUSTY_LIGHT_BLUE_COLOR, + LIGHT_GRAY_COLOR}; + use super::*; - use r3bl_rs_utils_core::ch; - use r3bl_rs_utils_core::ChUnit; pub fn multi_select_instruction_header() { AnsiStyledText { @@ -236,7 +270,8 @@ pub mod giti_ui_templates { selection_mode: SelectionMode, ) -> Option> { let max_height_row_count = 20; - let max_width_col_count = get_size().map(|it| it.col_count).unwrap_or(ch!(80)).into(); + let max_width_col_count = + get_size().map(|it| it.col_count).unwrap_or(ch!(80)).into(); let style = StyleSheet::default(); let user_input = select_from_list( header, diff --git a/cmdr/src/giti/branch/mod.rs b/cmdr/src/giti/branch/mod.rs new file mode 100644 index 000000000..aa7159465 --- /dev/null +++ b/cmdr/src/giti/branch/mod.rs @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2023 R3BL LLC + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +pub mod delete; +pub use delete::*; diff --git a/cmdr/src/giti/mod.rs b/cmdr/src/giti/mod.rs new file mode 100644 index 000000000..dfaebc929 --- /dev/null +++ b/cmdr/src/giti/mod.rs @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2023 R3BL LLC + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +pub mod branch; +pub use branch::*; diff --git a/cmdr/src/lib.rs b/cmdr/src/lib.rs index 278539eeb..a2e84e7c9 100644 --- a/cmdr/src/lib.rs +++ b/cmdr/src/lib.rs @@ -40,8 +40,10 @@ #![warn(clippy::all)] #![warn(rust_2018_idioms)] -pub const DEBUG: bool = true; +pub const DEVELOPMENT_MODE: bool = true; -pub mod entry_point; +pub mod giti; +pub mod rc; -pub use entry_point::*; +pub use giti::*; +pub use rc::*; diff --git a/cmdr/src/entry_point/app.rs b/cmdr/src/rc/app.rs similarity index 99% rename from cmdr/src/entry_point/app.rs rename to cmdr/src/rc/app.rs index 956c15b61..457d0b547 100644 --- a/cmdr/src/entry_point/app.rs +++ b/cmdr/src/rc/app.rs @@ -59,7 +59,7 @@ macro_rules! DEBUG_MSG_TEMPLATE { } pub async fn debug_cli_args() { - call_if_true!(DEBUG, { + call_if_true!(DEVELOPMENT_MODE, { // Get the command line arguments w/out the process name. Eg: `$ rc edit file --help` will // produce `edit file --help`. let argv_without_process: Vec = args().filter_and_convert_to_strings(); diff --git a/cmdr/src/entry_point/mod.rs b/cmdr/src/rc/mod.rs similarity index 100% rename from cmdr/src/entry_point/mod.rs rename to cmdr/src/rc/mod.rs diff --git a/tuify/Cargo.toml b/tuify/Cargo.toml index 424d518bf..c74bf6709 100644 --- a/tuify/Cargo.toml +++ b/tuify/Cargo.toml @@ -17,7 +17,7 @@ license = "Apache-2.0" # This is the default binary to run when running `cargo run`. # More info: https://stackoverflow.com/a/51790493/2085356 -default-run = "giti" +default-run = "rt" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -25,10 +25,6 @@ default-run = "giti" name = "rt" path = "src/bin/rt.rs" -[[bin]] -name = "giti" -path = "src/bin/giti.rs" - [dependencies] # r3bl_rs_utils r3bl_ansi_color = { path = "../ansi_color", version = "0.6.9" } @@ -51,4 +47,4 @@ reedline = "0.27.1" [dev-dependencies] pretty_assertions = "1.4.0" -serial_test = "2.0.0" \ No newline at end of file +serial_test = "2.0.0" diff --git a/tuify/README.md b/tuify/README.md index 7b8af1d49..37e8eeabb 100644 --- a/tuify/README.md +++ b/tuify/README.md @@ -14,7 +14,6 @@ - [Build, run, test tasks](#build-run-test-tasks) - [Prerequisites](#prerequisites) - [Nu shell scripts to build, run, test etc.](#nu-shell-scripts-to-build-run-test-etc) -- [Run giti](#run-giti) - [References](#references) @@ -384,7 +383,6 @@ fn main() -> Result<()> { | Command | Description | | ----------------------------------------- | ------------------------------------------ | | `nu run.nu run` | Run examples in the `./examples` folder | -| `nu run.nu install-giti` | Install `giti` locally to `~/.cargo/bin` | | `nu run.nu run-piped` | Run binary with piped input | | `nu run.nu build` | Build | | `nu run.nu clean` | Clean | @@ -407,16 +405,6 @@ The following commands will watch for changes in the source folder and re-run: | `nu run.nu watch-clippy` | Watch clippy | | `nu run.nu watch-macro-expansion-one-test ` | Watch macro expansion for one test | -## Run `giti` - - -1. Move to `./tuify` folder in your terminal -2. Run `nu run.nu install-giti` to install `giti` locally to `~/.cargo/bin` -3. Run `giti` from anywhere on your system -4. To delete one or more branches in your repo run `giti branch delete` - -[![asciicast](https://asciinema.org/a/14V8v3OKKYvDkUDkRFiMDsCNg.svg)](https://asciinema.org/a/14V8v3OKKYvDkUDkRFiMDsCNg) - ## References diff --git a/tuify/run.nu b/tuify/run.nu index 5125b5909..d5f4fbcf6 100755 --- a/tuify/run.nu +++ b/tuify/run.nu @@ -33,7 +33,6 @@ def main [...args: string] { "build" => {build} "clean" => {clean} "run" => {run} - "install-giti" => {install-giti} "run-piped" => {run-piped} "log" => {log} "test" => {test} @@ -117,7 +116,6 @@ def print-help [command: string] { print $' (ansi green)build(ansi reset)' print $' (ansi green)clean(ansi reset)' print $' (ansi green)run(ansi reset)' - print $' (ansi green)install-giti(ansi reset)' print $' (ansi green)run-piped(ansi reset)' print $' (ansi green)log(ansi reset)' print $' (ansi green)run-with-flamegraph-profiling(ansi reset), (ansi blue)For more info, watch: https://www.youtube.com/watch?v=Sy26IMkOEiM(ansi reset)' @@ -155,10 +153,6 @@ def run [] { cargo run --example main_interactive -q } -def install-giti [] { - cargo install --path . -} - def run-piped [] { bat Cargo.toml | cargo run -q --bin rt -- select-from-list } diff --git a/tuify/src/giti/branch/mod.rs b/tuify/src/giti/branch/mod.rs deleted file mode 100644 index 8334163ad..000000000 --- a/tuify/src/giti/branch/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod delete; -pub use delete::*; diff --git a/tuify/src/giti/mod.rs b/tuify/src/giti/mod.rs deleted file mode 100644 index 6cfc6cfc9..000000000 --- a/tuify/src/giti/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod branch; -pub use branch::*; diff --git a/tuify/src/lib.rs b/tuify/src/lib.rs index b4ef1582b..21726c588 100644 --- a/tuify/src/lib.rs +++ b/tuify/src/lib.rs @@ -433,7 +433,6 @@ pub mod components; pub mod constants; pub mod event_loop; -pub mod giti; pub mod keypress; pub mod public_api; pub mod react; @@ -445,7 +444,6 @@ pub mod test_utils; pub use components::*; pub use constants::*; pub use event_loop::*; -pub use giti::*; pub use keypress::*; pub use public_api::*; pub use react::*;