1// `error_chain!` can recurse deeply
2#![recursion_limit = "1024"]
5extern crate error_chain;
11extern crate lazy_static;
13extern crate ansi_term;
16extern crate directories;
31use std::collections::HashSet;
37use ansi_term::Colour::Green;
40use app::{App, Config, InputFile};
41use assets::{clear_assets, config_dir, HighlightingAssets};
42use controller::Controller;
43use style::{OutputComponent, OutputComponents};
50 SyntectError(::syntect::LoadingError);
51 ParseIntError(::std::num::ParseIntError);
55 pub fn handle_error(error: &Error) {
57 &Error(ErrorKind::Io(ref io_error), _)
58 if io_error.kind() == super::io::ErrorKind::BrokenPipe =>
60 super::process::exit(0);
63 use ansi_term::Colour::Red;
64 eprintln!("{}: {}", Red.paint("[bat error]"), error);
72fn run_cache_subcommand(matches: &clap::ArgMatches) -> Result<()> {
73 if matches.is_present("init") {
74 let source_dir = matches.value_of("source").map(Path::new);
75 let target_dir = matches.value_of("target").map(Path::new);
77 let blank = matches.is_present("blank");
79 let assets = HighlightingAssets::from_files(source_dir, blank)?;
80 assets.save(target_dir)?;
81 } else if matches.is_present("clear") {
83 } else if matches.is_present("config-dir") {
84 writeln!(io::stdout(), "{}", config_dir())?;
90pub fn list_languages(assets: &HighlightingAssets, term_width: usize) -> Result<()> {
91 let mut languages = assets
95 .filter(|syntax| !syntax.hidden && !syntax.file_extensions.is_empty())
97 languages.sort_by_key(|lang| lang.name.to_uppercase());
99 let longest = languages
101 .map(|syntax| syntax.name.len())
103 .unwrap_or(32); // Fallback width if they have no language definitions.
105 let comma_separator = ", ";
107 // Line-wrapping for the possible file extension overflow.
108 let desired_width = term_width - longest - separator.len();
110 let stdout = io::stdout();
111 let mut stdout = stdout.lock();
113 for lang in languages {
114 write!(stdout, "{:width$}{}", lang.name, separator, width = longest)?;
116 // Number of characters on this line so far, wrap before `desired_width`
117 let mut num_chars = 0;
119 let mut extension = lang.file_extensions.iter().peekable();
120 while let Some(word) = extension.next() {
121 // If we can't fit this word in, then create a line break and align it in.
122 let new_chars = word.len() + comma_separator.len();
123 if num_chars + new_chars >= desired_width {
125 write!(stdout, "\n{:width$}{}", "", separator, width = longest)?;
128 num_chars += new_chars;
129 write!(stdout, "{}", Green.paint(&word[..]))?;
130 if extension.peek().is_some() {
131 write!(stdout, "{}", comma_separator)?;
140pub fn list_themes(assets: &HighlightingAssets, cfg: &Config) -> Result<()> {
141 let themes = &assets.theme_set.themes;
142 let mut config = cfg.clone();
143 let mut style = HashSet::new();
144 style.insert(OutputComponent::Plain);
145 config.files = vec![InputFile::ThemePreviewFile];
146 config.output_components = OutputComponents(style);
148 let stdout = io::stdout();
149 let mut stdout = stdout.lock();
151 for (theme, _) in themes.iter() {
155 Style::new().bold().paint(theme.to_string())
157 config.theme = theme.to_string();
158 let _controller = Controller::new(&config, &assets).run();
165/// Returns `Err(..)` upon fatal errors. Otherwise, returns `Some(true)` on full success and
166/// `Some(false)` if any intermediate errors occurred (were printed).
167fn run() -> Result<bool> {
168 let app = App::new();
170 match app.matches.subcommand() {
171 ("cache", Some(cache_matches)) => {
172 run_cache_subcommand(cache_matches)?;
176 let config = app.config()?;
177 let assets = HighlightingAssets::new();
179 if app.matches.is_present("list-languages") {
180 list_languages(&assets, config.term_width)?;
183 } else if app.matches.is_present("list-themes") {
184 list_themes(&assets, &config)?;
188 let controller = Controller::new(&config, &assets);
200 handle_error(&error);
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list