Skip to main content

glitter_lang/
lib.rs

1//! glitter, a git repository status pretty-printer
2//!
3//! An expression based, ergonomic language for writing the status of your git repository into
4//! your shell prompt.
5//!
6//! For example :`"\<\b\(\+\-)>\[\M\A\R\D':'\m\a\u\d]\{\h('@')}':'"` results in something that
7//! might look like `<master(+1)>[M1:D3]{@5}:` where
8//!
9//! - `master` is the name of the current branch.
10//! - `+1`: means we are 1 commit ahead of the remote branch
11//! - `M1`: the number of staged modifications
12//! - `D3`: is the number of unstaged deleted files
13//! - `@5`: is the number of stashes
14//!
15//! `glit` expressions also support inline format expressions to do things like making text red,
16//! or bold, or using ANSI terminal escape sequences, or setting RGB colors for your git
17//! information.
18//!
19//! # Grammar
20//!
21//! `glit` expressions have four basic types of expressions:
22//!
23//! 1. Named expressions
24//! 2. Format expressions
25//! 3. Group expressions
26//! 4. Literals
27//!
28//! ## Literals
29//!
30//! Any characters between single quotes literal, except for backslashes and single quotes.
31//! Literals are left untouched.  For example, `'literal'` outputs `literal`.
32//!
33//! ## Named expressions
34//!
35//! Named expressions represent information about your git repository.
36//!
37//! | Name  | Meaning                        | Example         |
38//! |:------|:-------------------------------|:----------------|
39//! | `\b`  | branch name or head commit id  | `master`        |
40//! | `\B`  | remote name                    | `origin/master` |
41//! | `\+`  | # of commits ahead remote      | `+1`            |
42//! | `\-`  | # of commits behind remote     | `-1`            |
43//! | `\m`  | # of unstaged modified files   | `M1`            |
44//! | `\a`  | # of untracked files           | `?1`            |
45//! | `\d`  | # of unstaged deleted files    | `D1`            |
46//! | `\u`  | # of merge conflicts           | `U1`            |
47//! | `\M`  | # of staged modified files     | `M1`            |
48//! | `\A`  | # of added files               | `A1`            |
49//! | `\R`  | # of renamed files             | `R1`            |
50//! | `\D`  | # of staged deleted files      | `D1`            |
51//! | `\h`  | # of stashed files             | `H1`            |
52//!
53//! You can provide other expressions as arguments to expressions which replace the default prefix
54//! which appears before the result or file count.  For example, `\h('@')` will output `@3`
55//! instead of `H3` if your repository has 3 stashed files.  You can provide an arbitrary number
56//! of valid expressions as a prefix to another named expression.
57//!
58//! ## Group Expressions
59//!
60//! Glitter will surround grouped expressions with parentheses or brackets, and will print nothing
61//! if the group is empty.
62//!
63//! | Macro       | Result                           |
64//! |:------------|:---------------------------------|
65//! | `\[]`       | empty                            |
66//! | `\()`       | empty                            |
67//! | `\<>`       | empty                            |
68//! | `\{}`       | empty                            |
69//! | `\{\b}`     | `{master}`                       |
70//! | `\<\+\->`   | `<+1-1>`                         |
71//! | `\[\M\A\R]` | `[M1A3]` where `\R` is empty     |
72//! | `\[\r\(\a)]`| empty, when `\r`, `\a` are empty |
73//!
74//! ## Format Expressions
75//!
76//! Glitter expressions support ANSI terminal formatting through the following styles:
77//!
78//! | Format               | Meaning                                       |
79//! |:---------------------|:----------------------------------------------|
80//! | `#~(`...`)`          | reset                                         |
81//! | `#_(`...`)`          | underline                                     |
82//! | `#i(`...`)`          | italic text                                   |
83//! | `#*(`...`)`          | bold text                                     |
84//! | `#r(`...`)`          | red text                                      |
85//! | `#g(`...`)`          | green text                                    |
86//! | `#b(`...`)`          | blue text                                     |
87//! | `#m(`...`)`          | magenta/purple text                           |
88//! | `#y(`...`)`          | yellow text                                   |
89//! | `#w(`...`)`          | white text                                    |
90//! | `#k(`...`)`          | bright black text                             |
91//! | `#[01,02,03](`...`)` | 24 bit rgb text color                         |
92//! | `#R(`...`)`          | red background                                |
93//! | `#G(`...`)`          | green background                              |
94//! | `#B(`...`)`          | blue background                               |
95//! | `#M(`...`)`          | magenta/purple background                     |
96//! | `#Y(`...`)`          | yellow background                             |
97//! | `#W(`...`)`          | white background                              |
98//! | `#K(`...`)`          | bright black background                       |
99//! | `#{01,02,03}(`...`)` | 24 bit rgb background color                   |
100//! | `#01(`...`)`         | Fixed terminal color                          |
101//!
102//! Format styles can be combined in a single expression by separating them with semicolons:
103//!
104//! | Format         | Meaning                        |
105//! |:---------------|:-------------------------------|
106//! | `#w;K(`...`)`  | white text, black background   |
107//! | `#r;*(`...`)`  | red bold text                  |
108//! | `#42(`...`)`   | a forest greenish color        |
109//! | `#_;*(`...`)`  | underline bold text            |
110
111extern crate git2;
112extern crate nom;
113#[cfg_attr(test, macro_use)]
114#[cfg(test)]
115extern crate proptest;
116
117pub mod ast;
118mod color;
119pub mod git;
120pub mod interpreter;
121pub mod parser;
122
123pub use git::Stats;
124use std::fmt::{self, Display};
125use std::io;
126
127#[derive(Debug)]
128pub enum Error<'a> {
129    InterpreterError(interpreter::InterpreterErr),
130    ParseError(parser::ParseError<'a>),
131}
132
133impl<'a> Error<'a> {
134    pub fn pretty_print(&self, use_color: bool) -> String {
135        match self {
136            Error::InterpreterError(e) => format!("{:?}", e),
137            Error::ParseError(e) => format!("{}", e.pretty_print(use_color)),
138        }
139    }
140}
141
142impl<'a> From<interpreter::InterpreterErr> for Error<'a> {
143    fn from(e: interpreter::InterpreterErr) -> Self {
144        Error::InterpreterError(e)
145    }
146}
147
148impl<'a> From<parser::ParseError<'a>> for Error<'a> {
149    fn from(e: parser::ParseError<'a>) -> Self {
150        Error::ParseError(e)
151    }
152}
153
154impl<'a> Display for Error<'a> {
155    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
156        use Error::*;
157        match self {
158            InterpreterError(e) => write!(f, "{:?}", e),
159            ParseError(e) => write!(f, "{:?}", e.pretty_print(false)),
160        }
161    }
162}
163
164pub fn glitter<'a, W: io::Write>(
165    stats: Stats,
166    format: &'a str,
167    allow_color: bool,
168    bash_prompt: bool,
169    w: &mut W,
170) -> Result<(), Error<'a>> {
171    let tree = parser::parse(format)?;
172    interpreter::Interpreter::new(stats, allow_color, bash_prompt).evaluate(&tree, w)?;
173    Ok(())
174}