aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2018-02-20 01:48:17 -0500
committerJesse Luehrs <doy@tozt.net>2018-02-20 03:30:54 -0500
commit83f89188161b38046b39124ffb45bbbd6fcb572f (patch)
tree05a68afe3ad0394b3383adec01e98225b0ba92d4
parent0820849c2b6793f035bfcf7d5cd22dfbe9b45c25 (diff)
downloadfancy-prompt-83f89188161b38046b39124ffb45bbbd6fcb572f.tar.gz
fancy-prompt-83f89188161b38046b39124ffb45bbbd6fcb572f.zip
add vcs support
-rw-r--r--Cargo.lock171
-rw-r--r--Cargo.toml1
-rw-r--r--src/main.rs3
-rw-r--r--src/prompt.rs115
-rw-r--r--src/system_info.rs5
-rw-r--r--src/vcs/git.rs176
-rw-r--r--src/vcs/mod.rs35
7 files changed, 500 insertions, 6 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 04bd256..2d1cd08 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -23,10 +23,20 @@ dependencies = [
[[package]]
name = "bitflags"
+version = "0.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "bitflags"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
+name = "cc"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
name = "chrono"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -50,11 +60,34 @@ dependencies = [
]
[[package]]
+name = "cmake"
+version = "0.1.29"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "curl-sys"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libz-sys 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl-sys 0.9.26 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
name = "fancy-prompt"
version = "0.1.0"
dependencies = [
"chrono 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"clap 2.30.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "git2 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
"hostname 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
"term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -64,6 +97,19 @@ dependencies = [
]
[[package]]
+name = "git2"
+version = "0.6.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libgit2-sys 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl-sys 0.9.26 (registry+https://github.com/rust-lang/crates.io-index)",
+ "url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
name = "hostname"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -73,6 +119,16 @@ dependencies = [
]
[[package]]
+name = "idna"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
name = "kernel32-sys"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -92,6 +148,49 @@ version = "0.2.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
+name = "libgit2-sys"
+version = "0.6.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
+ "curl-sys 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libssh2-sys 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libz-sys 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl-sys 0.9.26 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "libssh2-sys"
+version = "0.2.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libz-sys 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl-sys 0.9.26 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "libz-sys"
+version = "1.0.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "matches"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
name = "memchr"
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -132,6 +231,32 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
+name = "openssl-probe"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "openssl-sys"
+version = "0.9.26"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "percent-encoding"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "pkg-config"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
name = "redox_syscall"
version = "0.1.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -231,6 +356,19 @@ dependencies = [
]
[[package]]
+name = "unicode-bidi"
+version = "0.3.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "unicode-normalization"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
name = "unicode-width"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -244,6 +382,16 @@ dependencies = [
]
[[package]]
+name = "url"
+version = "1.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "idna 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
name = "users"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -257,6 +405,11 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
+name = "vcpkg"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
name = "vec_map"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -316,18 +469,32 @@ dependencies = [
"checksum aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6531d44de723825aa81398a6415283229725a00fa30713812ab9323faa82fc4"
"checksum ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6b3568b48b7cefa6b8ce125f9bb4989e52fbcc29ebea88df04cc7c5f12f70455"
"checksum atty 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "8352656fd42c30a0c3c89d26dea01e3b77c0ab2af18230835c15e2e13cd51859"
+"checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5"
"checksum bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf"
+"checksum cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "deaf9ec656256bb25b404c51ef50097207b9cbb29c933d31f92cae5a8a0ffee0"
"checksum chrono 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7c20ebe0b2b08b0aeddba49c609fe7957ba2e33449882cb186a180bc60682fa9"
"checksum clap 2.30.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1c07b9257a00f3fc93b7f3c417fc15607ec7a56823bc2c37ec744e266387de5b"
+"checksum cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)" = "56d741ea7a69e577f6d06b36b7dff4738f680593dc27a701ffa8506b73ce28bb"
+"checksum curl-sys 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f46e49c7125131f5afaded06944d6888b55cbdf8eba05dae73c954019b907961"
+"checksum git2 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "ee5b4bb7cd2a44e6e5ee3a26ba6a9ca10d4ce2771cdc3839bbc54b47b7d1be84"
"checksum hostname 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "58fab6e177434b0bb4cd344a4dabaa5bd6d7a8d792b1885aebcae7af1091d1cb"
+"checksum idna 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "014b298351066f1512874135335d62a789ffe78a9974f94b43ed5621951eaf7d"
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
"checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d"
"checksum libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)" = "1e5d97d6708edaa407429faa671b942dc0f2727222fb6b6539bf1db936e4b121"
+"checksum libgit2-sys 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)" = "6eeae66e7b1c995de45cb4e65c5ab438a96a7b4077e448645d4048dc753ad357"
+"checksum libssh2-sys 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0db4ec23611747ef772db1c4d650f8bd762f07b461727ec998f953c614024b75"
+"checksum libz-sys 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)" = "87f737ad6cc6fd6eefe3d9dc5412f1573865bded441300904d2f42269e140f16"
+"checksum matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "100aabe6b8ff4e4a7e32c1c13523379802df0772b82466207ac25b013f193376"
"checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d"
"checksum num 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "4703ad64153382334aa8db57c637364c322d3372e097840c72000dabdcf6156e"
"checksum num-integer 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)" = "f8d26da319fb45674985c78f1d1caf99aa4941f785d384a2ae36d0740bc3e2fe"
"checksum num-iter 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "4b226df12c5a59b63569dd57fafb926d91b385dfce33d8074a412411b689d593"
"checksum num-traits 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e7de20f146db9d920c45ee8ed8f71681fd9ade71909b48c3acbd766aa504cf10"
+"checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de"
+"checksum openssl-sys 0.9.26 (registry+https://github.com/rust-lang/crates.io-index)" = "a5a41ce2f5f2d939c80decde8fcfcf5837c203ca6c06a553510a2fcb84fa3ef1"
+"checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831"
+"checksum pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903"
"checksum redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "0d92eecebad22b767915e4d529f89f28ee96dbbf5a4810d2b844373f136417fd"
"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76"
"checksum regex 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "5be5347bde0c48cfd8c3fdc0766cdfe9d8a755ef84d620d6794c778c91de8b2b"
@@ -340,10 +507,14 @@ dependencies = [
"checksum textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c0b59b6b4b44d867f1370ef1bd91bfb262bf07bf0ae65c202ea2fbc16153b693"
"checksum thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "279ef31c19ededf577bfd12dfae728040a21f635b06a24cd670ff510edd38963"
"checksum time 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "a15375f1df02096fb3317256ce2cee6a1f42fc84ea5ad5fc8c421cfe40c73098"
+"checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5"
+"checksum unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "51ccda9ef9efa3f7ef5d91e8f9b83bbe6955f9bf86aec89d5cce2c874625920f"
"checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f"
"checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56"
+"checksum url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fa35e768d4daf1d85733418a49fb42e10d7f633e394fccab4ab7aba897053fe2"
"checksum users 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "99ab1b53affc9f75f57da4a8b051a188e84d20d43bea0dd9bd8db71eebbca6da"
"checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122"
+"checksum vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9e0a7d8bed3178a8fb112199d466eeca9ed09a14ba8ad67718179b4fd5487d0b"
"checksum vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "887b5b631c2ad01628bbbaa7dd4c869f80d3186688f8d0b6f58774fbe324988c"
"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
"checksum walkdir 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b167e9a4420d8dddb260e70c90a4a375a1e5691f21f70e715553da87b6c2503a"
diff --git a/Cargo.toml b/Cargo.toml
index 0040bae..b875d9b 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -6,6 +6,7 @@ authors = ["Jesse Luehrs <doy@tozt.net>"]
[dependencies]
chrono = "0.4"
clap = "2.30"
+git2 = "0.6"
hostname = "0.1"
regex = "0.2"
term = "0.4"
diff --git a/src/main.rs b/src/main.rs
index 471a3a2..85b4627 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,5 +1,6 @@
extern crate chrono;
extern crate clap;
+extern crate git2;
extern crate hostname;
extern crate regex;
extern crate term;
@@ -11,6 +12,7 @@ mod colors;
mod power;
mod prompt;
mod system_info;
+mod vcs;
fn collect_data() -> prompt::PromptData {
let matches = clap::App::new("fancy-prompt")
@@ -45,6 +47,7 @@ fn collect_data() -> prompt::PromptData {
is_root: system_info::is_root(),
time: system_info::time(),
power_info: system_info::power_info(),
+ vcs_info: system_info::vcs_info(),
}
}
diff --git a/src/prompt.rs b/src/prompt.rs
index 2679bc9..12a7ee5 100644
--- a/src/prompt.rs
+++ b/src/prompt.rs
@@ -2,15 +2,17 @@ use chrono;
use regex;
use std;
+use std::fmt::Write;
+
use colors;
use power;
+use vcs;
pub struct Prompt {
colors: colors::Colors,
data: PromptData,
}
-#[derive(Debug)]
pub struct PromptData {
pub shell: colors::ShellType,
pub error_code: u8,
@@ -22,6 +24,7 @@ pub struct PromptData {
pub is_root: bool,
pub time: chrono::DateTime<chrono::Local>,
pub power_info: power::PowerInfo,
+ pub vcs_info: Option<Box<vcs::VcsInfo>>,
}
impl Prompt {
@@ -36,13 +39,22 @@ impl Prompt {
let user = self.data.user.clone().unwrap_or(String::from("???"));
let host = self.data.hostname.clone().unwrap_or(String::from("???"));
+ let max_vcs_len = 20; // "g*+?:mybr...nch:+1-1"
+ let (vcs, vcs_err) = self.format_vcs();
+ let vcs = vcs.map(|vcs| {
+ compress_vcs(&vcs, max_vcs_len)
+ });
+
let battery_len = 10;
let cols = self.data.terminal_cols.unwrap_or(80);
- // " (~/a/...cde) ---- {--<=======} doy@lance [19:40:50] "
+ // " (~/a/...cde|g*+?:mybr:+1-1) -- {--<=======} doy@lance [19:40:50] "
let max_path_len = cols
- 1 // " "
- - 2 // "()"
+ - vcs
+ .as_ref()
+ .map(|vcs| vcs.len() + 1) // "|g*+?:mybr:+1-1"
+ .unwrap_or(0) - 2 // "()"
- 1 // " "
- 1 // "-"
- 1 // " "
@@ -65,9 +77,10 @@ impl Prompt {
&self.data.home,
max_path_len
);
+ let path_err = false; // XXX
self.colors.pad(1);
- self.display_path(&path);
+ self.display_path(&path, path_err, &vcs, vcs_err);
self.colors.pad(1);
self.display_border(max_path_len - path.len() + 1);
@@ -91,9 +104,19 @@ impl Prompt {
self.colors.pad(1);
}
- fn display_path(&self, path: &str) {
+ fn display_path(
+ &self,
+ path: &str,
+ path_err: bool,
+ vcs: &Option<String>,
+ vcs_err: bool
+ ) {
self.colors.print_host(&self.data.hostname, "(");
- self.colors.print("default", path);
+ self.colors.print(if path_err { "error" } else { "default" }, path);
+ if let &Some(ref vcs) = vcs {
+ self.colors.print_host(&self.data.hostname, "|");
+ self.colors.print(if vcs_err { "error" } else { "default" }, &vcs);
+ }
self.colors.print_host(&self.data.hostname, ")");
}
@@ -159,6 +182,64 @@ impl Prompt {
let prompt = if self.data.is_root { "#" } else { "$" };
self.colors.print_user(&self.data.user, prompt);
}
+
+ fn format_vcs(&self) -> (Option<String>, bool) {
+ (self.data.vcs_info.as_ref().map(|vcs_info| {
+ let mut vcs = String::new();
+
+ write!(vcs, "{}", vcs_id(vcs_info.vcs())).unwrap();
+
+ if vcs_info.has_modified_files() {
+ write!(vcs, "*").unwrap();
+ }
+ if vcs_info.has_staged_files() {
+ write!(vcs, "+").unwrap();
+ }
+ if vcs_info.has_new_files() {
+ write!(vcs, "?").unwrap();
+ }
+ if !vcs_info.has_commits() {
+ write!(vcs, "!").unwrap();
+ }
+
+ let branch = vcs_info.branch().map(|branch| {
+ if branch == "master" {
+ String::new()
+ }
+ else {
+ branch
+ }
+ }).unwrap_or(String::from("???"));
+ if branch != "" {
+ write!(vcs, ":").unwrap();
+ }
+ write!(vcs, "{}", branch).unwrap();
+
+ if let Some((local, remote)) = vcs_info.remote_branch_diff() {
+ if local > 0 || remote > 0 {
+ write!(vcs, ":").unwrap();
+ }
+ if local > 0 {
+ write!(vcs, "+{}", local).unwrap();
+ }
+ if remote > 0 {
+ write!(vcs, "-{}", remote).unwrap();
+ }
+ }
+ else {
+ write!(vcs, ":-").unwrap();
+ }
+
+ match vcs_info.active_operation() {
+ vcs::ActiveOperation::None => {},
+ op => {
+ write!(vcs, "({})", active_operation_id(op)).unwrap();
+ }
+ }
+
+ vcs
+ }), false) // XXX
+ }
}
fn battery_discharge_color(usage: f64, charging: bool) -> &'static str {
@@ -226,3 +307,25 @@ fn compress_path<T, U>(
String::from("???")
}
}
+
+fn compress_vcs(vcs: &str, _len: usize) -> String {
+ // XXX
+ String::from(vcs)
+}
+
+fn vcs_id(vcs: vcs::VcsType) -> String {
+ match vcs {
+ vcs::VcsType::Git => String::from("g"),
+ }
+}
+
+fn active_operation_id(op: vcs::ActiveOperation) -> String {
+ match op {
+ vcs::ActiveOperation::None => String::new(),
+ vcs::ActiveOperation::Merge => String::from("m"),
+ vcs::ActiveOperation::Revert => String::from("v"),
+ vcs::ActiveOperation::CherryPick => String::from("c"),
+ vcs::ActiveOperation::Bisect => String::from("b"),
+ vcs::ActiveOperation::Rebase => String::from("r"),
+ }
+}
diff --git a/src/system_info.rs b/src/system_info.rs
index 2079ea7..47ed0f9 100644
--- a/src/system_info.rs
+++ b/src/system_info.rs
@@ -5,6 +5,7 @@ use std;
use users;
use power;
+use vcs;
pub fn hostname() -> Option<String> {
hostname::get_hostname()
@@ -44,3 +45,7 @@ pub fn time() -> chrono::DateTime<chrono::Local> {
pub fn power_info() -> power::PowerInfo {
power::PowerInfo::new()
}
+
+pub fn vcs_info() -> Option<Box<vcs::VcsInfo>> {
+ vcs::detect()
+}
diff --git a/src/vcs/git.rs b/src/vcs/git.rs
new file mode 100644
index 0000000..749d498
--- /dev/null
+++ b/src/vcs/git.rs
@@ -0,0 +1,176 @@
+use git2;
+use std;
+
+use std::fmt::Write;
+
+#[derive(Debug)]
+pub struct GitInfo {
+ modified_files: bool,
+ staged_files: bool,
+ new_files: bool,
+ commits: bool,
+ active_operation: super::ActiveOperation,
+ branch: Option<String>,
+ remote_branch_diff: Option<(usize, usize)>,
+}
+
+impl GitInfo {
+ pub fn new(git: git2::Repository) -> GitInfo {
+ let mut modified_statuses = git2::Status::empty();
+ modified_statuses.insert(git2::STATUS_WT_DELETED);
+ modified_statuses.insert(git2::STATUS_WT_MODIFIED);
+ modified_statuses.insert(git2::STATUS_WT_RENAMED);
+ modified_statuses.insert(git2::STATUS_WT_TYPECHANGE);
+ let mut staged_statuses = git2::Status::empty();
+ staged_statuses.insert(git2::STATUS_INDEX_DELETED);
+ staged_statuses.insert(git2::STATUS_INDEX_MODIFIED);
+ staged_statuses.insert(git2::STATUS_INDEX_NEW);
+ staged_statuses.insert(git2::STATUS_INDEX_RENAMED);
+ staged_statuses.insert(git2::STATUS_INDEX_TYPECHANGE);
+ let mut new_statuses = git2::Status::empty();
+ new_statuses.insert(git2::STATUS_WT_NEW);
+
+ let mut status_options = git2::StatusOptions::new();
+ status_options.include_untracked(true);
+ if true { // XXX
+ status_options.update_index(true);
+ }
+ else {
+ status_options.update_index(false);
+ status_options.no_refresh(true);
+ }
+ let status = git.statuses(Some(&mut status_options));
+ let mut modified_files = false;
+ let mut staged_files = false;
+ let mut new_files = false;
+ for status in status.iter() {
+ for file in status.iter() {
+ if file.status().intersects(modified_statuses) {
+ modified_files = true;
+ }
+ if file.status().intersects(staged_statuses) {
+ staged_files = true;
+ }
+ if file.status().intersects(new_statuses) {
+ new_files = true;
+ }
+ }
+ }
+
+ let head = git.head();
+ let commits = head.is_ok();
+ let branch = head.ok()
+ .and_then(|head| {
+ if head.is_branch() {
+ head.shorthand().map(|s| s.to_string())
+ }
+ else {
+ head.resolve().ok()
+ .and_then(|head| head.target())
+ .map(|oid| {
+ let mut sha = String::new();
+ for b in oid.as_bytes().iter() {
+ write!(sha, "{:02x}", b).unwrap();
+ }
+ sha.truncate(7);
+ sha
+ })
+ }
+ });
+
+ let active_operation = match git.state() {
+ git2::RepositoryState::Merge
+ => super::ActiveOperation::Merge,
+ git2::RepositoryState::Revert
+ | git2::RepositoryState::RevertSequence
+ => super::ActiveOperation::Revert,
+ git2::RepositoryState::CherryPick
+ | git2::RepositoryState::CherryPickSequence
+ => super::ActiveOperation::CherryPick,
+ git2::RepositoryState::Bisect
+ => super::ActiveOperation::Bisect,
+ git2::RepositoryState::Rebase
+ | git2::RepositoryState::RebaseInteractive
+ | git2::RepositoryState::RebaseMerge
+ => super::ActiveOperation::Rebase,
+ _ => super::ActiveOperation::None,
+ };
+
+ let remote_branch_diff = git.head().ok()
+ .and_then(|head| if head.is_branch() { Some(head) } else { None })
+ .and_then(|head| {
+ head.resolve().ok()
+ })
+ .map(|head| {
+ (head.target(), head.shorthand().map(|s| s.to_string()))
+ })
+ .and_then(|(head_id, name)| {
+ head_id.and_then(|head_id| {
+ name.and_then(|name| {
+ git.refname_to_id(
+ &(String::from("refs/remotes/origin/") + &name)
+ ).ok().and_then(|remote_id| {
+ git.graph_ahead_behind(head_id, remote_id).ok()
+ })
+ })
+ })
+ });
+
+ GitInfo {
+ modified_files: modified_files,
+ staged_files: staged_files,
+ new_files: new_files,
+ commits: commits,
+ active_operation: active_operation,
+ branch: branch,
+ remote_branch_diff: remote_branch_diff,
+ }
+ }
+}
+
+impl super::VcsInfo for GitInfo {
+ fn vcs(&self) -> super::VcsType {
+ super::VcsType::Git
+ }
+
+ fn has_modified_files(&self) -> bool {
+ self.modified_files
+ }
+
+ fn has_staged_files(&self) -> bool {
+ self.staged_files
+ }
+
+ fn has_new_files(&self) -> bool {
+ self.new_files
+ }
+
+ fn has_commits(&self) -> bool {
+ self.commits
+ }
+
+ fn active_operation(&self) -> super::ActiveOperation {
+ self.active_operation
+ }
+
+ fn branch(&self) -> Option<String> {
+ self.branch.clone()
+ }
+
+ fn remote_branch_diff(&self) -> Option<(usize, usize)> {
+ self.remote_branch_diff
+ }
+}
+
+pub fn detect() -> Option<Box<super::VcsInfo>> {
+ let git = std::env::current_dir().ok().and_then(|pwd| {
+ git2::Repository::discover(pwd).ok()
+ });
+
+ if let Some(git) = git {
+ Some(Box::new(GitInfo::new(git)))
+ }
+ else {
+ None
+ }
+}
diff --git a/src/vcs/mod.rs b/src/vcs/mod.rs
new file mode 100644
index 0000000..02c2eb7
--- /dev/null
+++ b/src/vcs/mod.rs
@@ -0,0 +1,35 @@
+mod git;
+
+pub enum VcsType {
+ Git,
+}
+
+#[derive(Debug,Copy,Clone)]
+pub enum ActiveOperation {
+ None,
+ Merge,
+ Revert,
+ CherryPick,
+ Bisect,
+ Rebase,
+}
+
+pub trait VcsInfo {
+ fn vcs(&self) -> VcsType;
+ fn has_modified_files(&self) -> bool;
+ fn has_staged_files(&self) -> bool;
+ fn has_new_files(&self) -> bool;
+ fn has_commits(&self) -> bool;
+ fn active_operation(&self) -> ActiveOperation;
+ fn branch(&self) -> Option<String>;
+ fn remote_branch_diff(&self) -> Option<(usize, usize)>;
+}
+
+pub fn detect() -> Option<Box<VcsInfo>> {
+ if let Some(git) = git::detect() {
+ Some(git)
+ }
+ else {
+ None
+ }
+}