summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTim Oram <mitmaro@gmail.com>2016-12-20 23:42:30 -0330
committerTim Oram <mitmaro@gmail.com>2016-12-22 09:49:55 -0330
commit4e301fda3053571ef4ea8cdfe42cffdd549958bd (patch)
tree85334d9c83a3c31ec167768d457feff80b59422f
parent9cfc9ac9bc251d071775b68a78b4f6b6606aa443 (diff)
Initial project commit0.1.0
-rw-r--r--.gitignore1
-rw-r--r--Cargo.lock57
-rw-r--r--Cargo.toml7
-rw-r--r--src/main.rs227
4 files changed, 292 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..eb5a316
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+target
diff --git a/Cargo.lock b/Cargo.lock
new file mode 100644
index 0000000..cce25a4
--- /dev/null
+++ b/Cargo.lock
@@ -0,0 +1,57 @@
+[root]
+name = "git-interactive-tool"
+version = "0.1.0"
+dependencies = [
+ "pancurses 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "gcc"
+version = "0.3.40"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "libc"
+version = "0.2.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "log"
+version = "0.3.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "ncurses"
+version = "5.84.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "pancurses"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "ncurses 5.84.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pdcurses-sys 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "pdcurses-sys"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "gcc 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[metadata]
+"checksum gcc 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)" = "872db9e59486ef2b14f8e8c10e9ef02de2bccef6363d7f34835dedb386b3d950"
+"checksum libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "a51822fc847e7a8101514d1d44e354ba2ffa7d4c194dcab48870740e327cac70"
+"checksum log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ab83497bf8bf4ed2a74259c1c802351fcd67a65baa86394b6ba73c36f4838054"
+"checksum ncurses 5.84.0 (registry+https://github.com/rust-lang/crates.io-index)" = "30beffce9ed08187ec156a5d78c501b6ae20ee39eba7d1abf9fdfe522c86ae89"
+"checksum pancurses 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8d50e310b2bd745bbafc0138019729791c6c67bff8094d9136e85fd76e696709"
+"checksum pdcurses-sys 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "27a3bc0e02f0e4b38c3225e5ead84f7d529d44048076bb49980f76edcff7d6f1"
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644
index 0000000..d8a7628
--- /dev/null
+++ b/Cargo.toml
@@ -0,0 +1,7 @@
+[package]
+name = "git-interactive-tool"
+version = "0.1.0"
+authors = ["Tim Oram <mitmaro@gmail.com>"]
+
+[dependencies]
+pancurses = "0.7"
diff --git a/src/main.rs b/src/main.rs
new file mode 100644
index 0000000..0c842de
--- /dev/null
+++ b/src/main.rs
@@ -0,0 +1,227 @@
+extern crate pancurses;
+
+use std::env;
+
+// open.rs
+use std::error::Error;
+use std::fs::File;
+use std::io::prelude::*;
+use std::path::Path;
+
+const COLOR_TABLE: [i16; 8] = [
+ pancurses::COLOR_WHITE,
+ pancurses::COLOR_YELLOW,
+ pancurses::COLOR_BLUE,
+ pancurses::COLOR_GREEN,
+ pancurses::COLOR_CYAN,
+ pancurses::COLOR_MAGENTA,
+ pancurses::COLOR_RED,
+ pancurses::COLOR_BLACK
+];
+
+// Prints each argument on a separate line
+fn main() {
+ let args: Vec<String> = env::args().collect();
+
+ // Create a path to the desired file
+ let path = Path::new(&args[1]);
+ let display = path.display();
+
+ // Open the path in read-only mode, returns `io::Result<File>`
+ let mut file = match File::open(&path) {
+ Err(why) => panic!("couldn't open {}: {}", display, why.description()),
+ Ok(file) => file,
+ };
+
+ // Read the file contents into a string, returns `io::Result<usize>`
+ let mut s = String::new();
+ match file.read_to_string(&mut s) {
+ Err(why) => panic!("couldn't read {}: {}", display, why.description()),
+ Ok(_) => {},
+ }
+
+ let mut v: Vec<Vec<&str>> = s
+ .lines()
+ .filter(|l| !l.starts_with("#") && !l.is_empty())
+ .map(|l| l.splitn(3, " ").collect())
+ .collect();
+
+ let v_len: i16 = v.len() as i16;
+
+ /* Setup pancurses. */
+ let window = pancurses::initscr();
+
+ pancurses::curs_set(0);
+ pancurses::noecho();
+ window.keypad(true);
+
+ if pancurses::has_colors() {
+ pancurses::start_color();
+ }
+
+ pancurses::use_default_colors();
+ for (i, color) in COLOR_TABLE.into_iter().enumerate() {
+ pancurses::init_pair(i as i16, *color, -1);
+ }
+
+ let mut selected_line: i16 = 0;
+
+ loop {
+ window.clear();
+ window.attrset(pancurses::COLOR_PAIR(0));
+ window.addstr("Git Interactive Rebase Type ? for help\n\n");
+ window.attrset(pancurses::COLOR_PAIR(0));
+ window.refresh();
+ let mut i: i16 = 0;
+ for ss in &v {
+ if ss[0] == "pick" {
+ window.attrset(pancurses::COLOR_PAIR(0));
+ } else if ss[0] == "reword" {
+ window.attrset(pancurses::COLOR_PAIR(1));
+ } else if ss[0] == "edit" {
+ window.attrset(pancurses::COLOR_PAIR(2));
+ } else if ss[0] == "squash" {
+ window.attrset(pancurses::COLOR_PAIR(4));
+ } else if ss[0] == "fixup" {
+ window.attrset(pancurses::COLOR_PAIR(5));
+ } else if ss[0] == "exec" {
+ window.attrset(pancurses::COLOR_PAIR(6));
+ } else if ss[0] == "drop" {
+ window.attrset(pancurses::COLOR_PAIR(7));
+ }
+ if i == selected_line {
+ window.attrset(pancurses::COLOR_PAIR(0));
+ window.attron(pancurses::A_STANDOUT);
+ }
+ window.addstr(&format!(" {:6} {} {}\n", &ss[0], &ss[1], &ss[2]).as_ref());
+ window.attroff(pancurses::A_STANDOUT);
+ i += 1;
+ }
+ window.attrset(pancurses::COLOR_PAIR(0));
+ window.refresh();
+ match window.getch() {
+ Some(pancurses::Input::Character(q)) if q == 'q' || q == 'Q' => {
+ window.clear();
+ window.attrset(pancurses::COLOR_PAIR(0));
+ window.addstr("Git Interactive Rebase - Abort Rebase\n\n");
+ window.addstr("Are you sure you want to abort? (y/n)");
+ window.refresh();
+ match window.getch() {
+ Some(pancurses::Input::Character(c)) if c == 'y' || c == 'Y' => {
+ pancurses::curs_set(1);
+ pancurses::endwin();
+ // empty file
+ v.clear();
+ break;
+ },
+ _ => {}
+ }
+ },
+ Some(pancurses::Input::Character(q)) if q == 'w' || q == 'W' => {
+ window.clear();
+ window.attrset(pancurses::COLOR_PAIR(0));
+ window.addstr("Git Interactive Rebase - Confirm Rebase\n\n");
+ window.addstr("Are you sure you want to rebase? (y/n)");
+ window.refresh();
+ match window.getch() {
+ Some(pancurses::Input::Character(c)) if c == 'y' || c == 'Y' => {
+ pancurses::curs_set(1);
+ pancurses::endwin();
+ break;
+ },
+ _ => {}
+ }
+ },
+ Some(pancurses::Input::Character(c)) if c == '?' || c == 'h' || c == 'H' => {
+ window.clear();
+ window.attrset(pancurses::COLOR_PAIR(0));
+ window.addstr("Git Interactive Rebase - Help\n\n");
+ window.addstr(" Up and Down arrow keys to move selection\n");
+ window.addstr(" q, abort interactive rebase\n");
+ window.addstr(" w, write and continue interactive rebase\n");
+ window.addstr(" ?, show this help message\n");
+ window.addstr(" j, move selected commit up\n");
+ window.addstr(" k, move selected commit down\n");
+ window.addstr(" p, pick: use commit\n");
+ window.addstr(" r, reword: use commit, but edit the commit message\n");
+ window.addstr(" e, edit: use commit, but stop for amending\n");
+ window.addstr(" s, squash: use commit, but meld into previous commit\n");
+ window.addstr(" f, fixup: like 'squash', but discard this commit's log message\n");
+ window.addstr(" x, exec: run command (the rest of the line) using shell\n");
+ window.addstr(" d, drop: remove commit\n");
+ window.addstr("\n\nHit any key to close help");
+ window.refresh();
+ window.getch();
+ },
+ Some(pancurses::Input::Character(c)) if c == 'p' || c == 'P' => {
+ v[selected_line as usize].remove(0);
+ v[selected_line as usize].insert(0, "pick");
+ },
+ Some(pancurses::Input::Character(c)) if c == 'r' || c == 'R' => {
+ v[selected_line as usize].remove(0);
+ v[selected_line as usize].insert(0, "reword");
+ },
+ Some(pancurses::Input::Character(c)) if c == 'e' || c == 'E' => {
+ v[selected_line as usize].remove(0);
+ v[selected_line as usize].insert(0, "edit");
+ },
+ Some(pancurses::Input::Character(c)) if c == 's' || c == 'S' => {
+ v[selected_line as usize].remove(0);
+ v[selected_line as usize].insert(0, "squash");
+ },
+ Some(pancurses::Input::Character(c)) if c == 'f' || c == 'F' => {
+ v[selected_line as usize].remove(0);
+ v[selected_line as usize].insert(0, "fixup");
+ },
+ Some(pancurses::Input::Character(c)) if c == 'x' || c == 'X' => {
+ v[selected_line as usize].remove(0);
+ v[selected_line as usize].insert(0, "exec");
+ },
+ Some(pancurses::Input::Character(c)) if c == 'd' || c == 'D' => {
+ v[selected_line as usize].remove(0);
+ v[selected_line as usize].insert(0, "drop");
+ },
+ Some(pancurses::Input::Character(c)) if c == 'd' || c == 'D' => {
+ v[selected_line as usize].remove(0);
+ v[selected_line as usize].insert(0, "drop");
+ },
+ Some(pancurses::Input::Character(c)) if c == 'j' || c == 'J' => {
+ if selected_line != 0 {
+ v.swap(selected_line as usize, selected_line as usize - 1);
+ selected_line -= 1;
+ }
+ },
+ Some(pancurses::Input::Character(c)) if c == 'k' || c == 'K' => {
+ if selected_line != v_len - 1 {
+ v.swap(selected_line as usize, selected_line as usize + 1);
+ selected_line += 1;
+ }
+ },
+ Some(pancurses::Input::KeyUp) => {
+ selected_line -= 1;
+ if selected_line < 0 {
+ selected_line = 0;
+ }
+ },
+ Some(pancurses::Input::KeyDown) => {
+ selected_line += 1;
+ if selected_line > v_len - 1 {
+ selected_line = v_len - 1;
+ }
+ },
+ _ => {}
+ }
+ }
+
+ let mut outfile = match File::create(path) {
+ Err(why) => panic!("couldn't create {}: {}", display, why.description()),
+ Ok(outfile) => outfile,
+ };
+
+ for ss in &v {
+ if let Err(e) = writeln!(outfile, "{} {} {}", &ss[0], &ss[1], &ss[2]) {
+ println!("{}", e);
+ }
+ }
+}
+