Skip to content

Commit

Permalink
Implement syntax mapping
Browse files Browse the repository at this point in the history
This adds a `-m`/`--map-syntax` option that allows users to (re)map
certain file extensions or file names to an existing syntax.

For example:
```
bat --map-syntax .config:json
```

The option can be use multiple times. Note that you can easily make
these mappings permanent by using `bat`s new configuration file.

closes #169
  • Loading branch information
sharkdp committed Oct 17, 2018
1 parent e43d97d commit 8441f8b
Show file tree
Hide file tree
Showing 6 changed files with 80 additions and 3 deletions.
19 changes: 19 additions & 0 deletions src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ use errors::*;
use inputfile::InputFile;
use line_range::LineRange;
use style::{OutputComponent, OutputComponents, OutputWrap};
use syntax_mapping::SyntaxMapping;
use util::transpose;

#[derive(Debug, Clone, Copy, PartialEq)]
Expand Down Expand Up @@ -66,6 +67,9 @@ pub struct Config<'a> {

/// The syntax highlighting theme
pub theme: String,

/// File extension/name mappings
pub syntax_mapping: SyntaxMapping,
}

fn is_truecolor_terminal() -> bool {
Expand Down Expand Up @@ -146,6 +150,20 @@ impl App {
}
};

let mut syntax_mapping = SyntaxMapping::new();

if let Some(values) = self.matches.values_of("map-syntax") {
for from_to in values {
let parts: Vec<_> = from_to.split(":").collect();

if parts.len() != 2 {
return Err("Invalid syntax mapping. The format of the -m/--map-syntax option is 'from:to'.".into());
}

syntax_mapping.insert(parts[0].into(), parts[1].into());
}
}

Ok(Config {
true_color: is_truecolor_terminal(),
language: self.matches.value_of("language"),
Expand Down Expand Up @@ -202,6 +220,7 @@ impl App {
.unwrap_or(String::from(BAT_THEME_DEFAULT)),
line_range: transpose(self.matches.value_of("line-range").map(LineRange::from))?,
output_components,
syntax_mapping,
})
}

Expand Down
10 changes: 8 additions & 2 deletions src/assets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use dirs::PROJECT_DIRS;

use errors::*;
use inputfile::{InputFile, InputFileReader};
use syntax_mapping::SyntaxMapping;

pub const BAT_THEME_DEFAULT: &str = "Monokai Extended";

Expand Down Expand Up @@ -167,17 +168,22 @@ impl HighlightingAssets {
language: Option<&str>,
filename: InputFile,
reader: &mut InputFileReader,
mapping: &SyntaxMapping,
) -> &SyntaxReference {
let syntax = match (language, filename) {
(Some(language), _) => self.syntax_set.find_syntax_by_token(language),
(None, InputFile::Ordinary(filename)) => {
let path = Path::new(filename);
let file_name = path.file_name().and_then(|n| n.to_str()).unwrap_or("");
let extension = path.extension().and_then(|x| x.to_str()).unwrap_or("");

let file_name = mapping.replace(file_name);
let extension = mapping.replace(extension);

let ext_syntax = self
.syntax_set
.find_syntax_by_extension(file_name)
.or_else(|| self.syntax_set.find_syntax_by_extension(extension));
.find_syntax_by_extension(&file_name)
.or_else(|| self.syntax_set.find_syntax_by_extension(&extension));
let line_syntax = if ext_syntax.is_none() {
String::from_utf8(reader.first_line.clone())
.ok()
Expand Down
16 changes: 16 additions & 0 deletions src/clap_app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,22 @@ pub fn build_app(interactive_output: bool) -> ClapApp<'static, 'static> {
.help("Display all supported languages.")
.long_help("Display a list of supported languages for syntax highlighting."),
)
.arg(
Arg::with_name("map-syntax")
.short("m")
.long("map-syntax")
.multiple(true)
.takes_value(true)
.value_name("from:to")
.help("Map a file extension or name to an existing syntax")
.long_help(
"Map a file extension or file name to an existing syntax. For example, \
to highlight *.conf files with the INI syntax, use '-m conf:ini'. \
To highlight files named '.myignore' with the Git Ignore syntax, use \
'-m .myignore:gitignore'.",
)
.takes_value(true),
)
.arg(
Arg::with_name("theme")
.long("theme")
Expand Down
1 change: 1 addition & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ mod output;
mod preprocessor;
mod printer;
mod style;
mod syntax_mapping;
mod terminal;
mod util;

Expand Down
2 changes: 1 addition & 1 deletion src/printer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ impl<'a> InteractivePrinter<'a> {
};

// Determine the type of syntax for highlighting
let syntax = assets.get_syntax(config.language, file, reader);
let syntax = assets.get_syntax(config.language, file, reader, &config.syntax_mapping);
Some(HighlightLines::new(syntax, theme))
};

Expand Down
35 changes: 35 additions & 0 deletions src/syntax_mapping.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
use std::borrow::Cow;
use std::collections::HashMap;

#[derive(Debug, Clone)]
pub struct SyntaxMapping(HashMap<String, String>);

impl SyntaxMapping {
pub fn new() -> SyntaxMapping {
SyntaxMapping(HashMap::new())
}

pub fn insert(&mut self, from: String, to: String) -> Option<String> {
self.0.insert(from, to)
}

pub fn replace<'a>(&self, input: &'a str) -> Cow<'a, str> {
let mut out = Cow::from(input);
if let Some(value) = self.0.get(input) {
out = Cow::from(value.clone())
}
out
}
}

#[test]
fn basic() {
let mut map = SyntaxMapping::new();
map.insert("Cargo.lock".into(), "toml".into());
map.insert(".ignore".into(), ".gitignore".into());

assert_eq!("toml", map.replace("Cargo.lock"));
assert_eq!("other.lock", map.replace("other.lock"));

assert_eq!(".gitignore", map.replace(".ignore"));
}

0 comments on commit 8441f8b

Please sign in to comment.