Copy path View file
@@ -1,4 +1,4 @@
// Copyright 2014-2016 The Rust Project Developers. See the COPYRIGHT
// Copyright 2014-2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
@@ -20,7 +20,7 @@
//! other then HTML), then you should implement the `Writer` trait and use a
//! `Classifier`.

use html::escape::Escape;
use escape::Escape;

use std::fmt::Display;
use std::io;
@@ -31,42 +31,8 @@ use syntax::parse::lexer::{self, TokenAndSpan};
use syntax::parse::token;
use syntax::parse;
use syntax_pos::Span;

/// Highlights `src`, returning the HTML output.
pub fn render_with_highlighting(src: &str, class: Option<&str>, id: Option<&str>,
extension: Option<&str>) -> String {
debug!("highlighting: ================\n{}\n==============", src);
let sess = parse::ParseSess::new();
let fm = sess.codemap().new_filemap("<stdin>".to_string(), None, src.to_string());

let mut out = Vec::new();
write_header(class, id, &mut out).unwrap();

let mut classifier = Classifier::new(lexer::StringReader::new(&sess, fm), sess.codemap());
if let Err(_) = classifier.write_source(&mut out) {
return format!("<pre>{}</pre>", src);
}

if let Some(extension) = extension {
write!(out, "{}", extension).unwrap();
}
write_footer(&mut out).unwrap();
String::from_utf8_lossy(&out[..]).into_owned()
}

/// Highlights `src`, returning the HTML output. Returns only the inner html to
/// be inserted into an element. C.f., `render_with_highlighting` which includes
/// an enclosing `<pre>` block.
pub fn render_inner_with_highlighting(src: &str) -> io::Result<String> {
let sess = parse::ParseSess::new();
let fm = sess.codemap().new_filemap("<stdin>".to_string(), None, src.to_string());

let mut out = Vec::new();
let mut classifier = Classifier::new(lexer::StringReader::new(&sess, fm), sess.codemap());
classifier.write_source(&mut out)?;

Ok(String::from_utf8_lossy(&out).into_owned())
}
use term::{color, Terminal, stdout, Attr};
use term::Attr::{ForegroundColor, Bold, Dim, Underline};

/// Processes a program (nested in the internal `lexer`), classifying strings of
/// text by highlighting category (`Class`). Calls out to a `Writer` to write
@@ -131,30 +97,11 @@ pub trait Writer {
/// ```
/// The latter can be thought of as a shorthand for the former, which is
/// more flexible.
fn string<T: Display>(&mut self, T, Class, Option<&TokenAndSpan>) -> io::Result<()>;
}

// Implement `Writer` for anthing that can be written to, this just implements
// the default rustdoc behaviour.
impl<U: Write> Writer for U {
fn string<T: Display>(&mut self,
text: T,
klass: Class,
_tas: Option<&TokenAndSpan>)
-> io::Result<()> {
match klass {
Class::None => write!(self, "{}", text),
klass => write!(self, "<span class='{}'>{}</span>", klass.rustdoc_class(), text),
}
}

fn enter_span(&mut self, klass: Class) -> io::Result<()> {
write!(self, "<span class='{}'>", klass.rustdoc_class())
}

fn exit_span(&mut self) -> io::Result<()> {
write!(self, "</span>")
}
-> io::Result<()>;
}

impl<'a> Classifier<'a> {
@@ -175,7 +122,7 @@ impl<'a> Classifier<'a> {
/// is used. All source code emission is done as slices from the source map,
/// not from the tokens themselves, in order to stay true to the original
/// source.
pub fn write_source<W: Writer>(&mut self,
pub fn write_source<W: Writer + Write>(&mut self,
out: &mut W)
-> io::Result<()> {
loop {
@@ -202,13 +149,13 @@ impl<'a> Classifier<'a> {
}

// Handles an individual token from the lexer.
fn write_token<W: Writer>(&mut self,
fn write_token<W: Writer + Write>(&mut self,
out: &mut W,
tas: TokenAndSpan)
-> io::Result<()> {
let klass = match tas.tok {
token::Shebang(s) => {
out.string(Escape(&s.as_str()), Class::None, Some(&tas))?;
out.string(&s.as_str(), Class::None, Some(&tas))?;
return Ok(());
},

@@ -320,7 +267,7 @@ impl<'a> Classifier<'a> {

// Anything that didn't return above is the simple case where we the
// class just spans a single token, so we can use the `string` method.
out.string(Escape(&self.snip(tas.sp)), klass, Some(&tas))
out.string(&self.snip(tas.sp), klass, Some(&tas))
}

// Helper function to get a snippet from the codemap.
@@ -353,19 +300,141 @@ impl Class {
Class::QuestionMark => "question-mark"
}
}

pub fn term_style(self) -> Vec<Attr> {
match self {
Class::None => vec![],
Class::Comment => vec![ForegroundColor(color::GREEN)],
Class::DocComment => vec![ForegroundColor(color::MAGENTA)],
Class::Attribute => vec![Bold],
Class::KeyWord => vec![Dim, ForegroundColor(color::YELLOW)],
Class::RefKeyWord => vec![Dim, ForegroundColor(color::MAGENTA)],
Class::Self_ => vec![ForegroundColor(color::CYAN)],
Class::Op => vec![ForegroundColor(color::YELLOW)],
Class::Macro => vec![ForegroundColor(color::MAGENTA)],
Class::MacroNonTerminal => vec![ForegroundColor(color::MAGENTA), Bold],
Class::String => vec![Underline(true)],
Class::Number => vec![ForegroundColor(color::CYAN)],
Class::Bool => vec![ForegroundColor(color::CYAN)],
Class::Ident => vec![],
Class::Lifetime => vec![Dim, ForegroundColor(color::MAGENTA)],
Class::PreludeTy => vec![ForegroundColor(color::GREEN)],
Class::PreludeVal => vec![ForegroundColor(color::CYAN)],
Class::QuestionMark => vec![Bold, ForegroundColor(color::GREEN)],
}

}
}

// You can implement `Writer` for anthing that can be written to, this just implements
// the default rustdoc behaviour for HTML output.
impl Writer for Vec<u8> {
fn string<T: Display>(&mut self,
text: T,
klass: Class,
_tas: Option<&TokenAndSpan>)
-> io::Result<()> {
match klass {
Class::None => write!(self, "{}", text),
klass => write!(self,
"<span class='{}'>{}</span>",
klass.rustdoc_class(),
Escape(&format!("{}", text))),
}
}

fn enter_span(&mut self, klass: Class) -> io::Result<()> {
write!(self, "<span class='{}'>", klass.rustdoc_class())
}

fn exit_span(&mut self) -> io::Result<()> {
write!(self, "</span>")
}
}

// This implements behaviour for terminal output.
impl Writer for Box<Terminal<Output=io::Stdout> + Send> {
fn string<T: Display>(&mut self,
text: T,
klass: Class,
_tas: Option<&TokenAndSpan>)
-> io::Result<()> {
for attr in klass.term_style() {
self.attr(attr)?;
}
write!(self, "{}", text)?;
let _ = self.reset();
Ok(())
}

fn enter_span(&mut self, klass: Class) -> io::Result<()> {
for attr in klass.term_style() {
self.attr(attr)?;
}
Ok(())
}

fn exit_span(&mut self) -> io::Result<()> {
let _ = self.reset();
Ok(())
}
}

fn render_maybe_with_highlighting(src: String, class: Option<&str>, id: Option<&str>,
extension: Option<&str>, enclose: bool) -> io::Result<String> {
debug!("html highlighting: ================\n{}\n==============", src);
let mut out = Vec::new();

if enclose {
write!(out, "<pre ")?;
if let Some(id) = id {
write!(out, "id='{}' ", id)?;
}
write!(out, "class='rust {}'>\n", class.unwrap_or(""))?;
}

let sess = parse::ParseSess::new();
let fm = sess.codemap().new_filemap("<stdin>".to_string(), None, src);
let mut classifier = Classifier::new(lexer::StringReader::new(&sess, fm), sess.codemap());
classifier.write_source(&mut out)?;

if let Some(extension) = extension {
write!(out, "{}", extension)?;
}

if enclose {
write!(out, "</pre>\n")?;
}

Ok(String::from_utf8_lossy(&out[..]).to_string())
}

fn write_header(class: Option<&str>,
id: Option<&str>,
out: &mut Write)
-> io::Result<()> {
write!(out, "<pre ")?;
if let Some(id) = id {
write!(out, "id='{}' ", id)?;
/// Highlights `src`, returning the HTML output. Returns only the inner html to
/// be inserted into an element. C.f., `render_with_highlighting` which includes
/// an enclosing `<pre>` block.
pub fn render_inner_with_highlighting(src: &str) -> io::Result<String> {
render_maybe_with_highlighting(src.to_string(), None, None, None, false)
}

/// Highlights `src`, returning the HTML output.
pub fn render_with_highlighting(src: &str,
class: Option<&str>,
id: Option<&str>,
extension: Option<&str>)
-> String {
match render_maybe_with_highlighting(src.to_string(), class, id, extension, true) {
Ok(s) => s,
Err(_) => src.to_string(),
}
write!(out, "class='rust {}'>\n", class.unwrap_or(""))
}

fn write_footer(out: &mut Write) -> io::Result<()> {
write!(out, "</pre>\n")
/// Highlights `src` and prints it out to stderr.
pub fn render_to_stdout_with_highlighting(src: String) {
debug!("term highlighting: ================\n{}\n==============", src);
let mut t = stdout().unwrap();

let sess = parse::ParseSess::new();
let fm = sess.codemap().new_filemap("<stdin>".to_string(), None, src);
let mut classifier = Classifier::new(lexer::StringReader::new(&sess, fm), sess.codemap());
let _ = classifier.write_source(&mut t);
}
Copy path View file
@@ -0,0 +1,30 @@
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![crate_name = "rustc_highlight"]
#![unstable(feature = "rustc_highlight", issue = "9999")]
#![crate_type = "dylib"]
#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
html_root_url = "https://doc.rust-lang.org/nightly/",
html_playground_url = "https://play.rust-lang.org/")]
#![deny(warnings)]

#![feature(rustc_private)]
#![feature(staged_api)]

#[macro_use] extern crate syntax;
extern crate syntax_pos;
#[macro_use] extern crate log;
extern crate term;

pub mod highlight;
pub mod escape;
Copy path View file
@@ -21,6 +21,7 @@ rustc_lint = { path = "../librustc_lint" }
rustc_metadata = { path = "../librustc_metadata" }
rustc_resolve = { path = "../librustc_resolve" }
rustc_trans = { path = "../librustc_trans" }
rustc_highlight = { path = "../librustc_highlight" }
serialize = { path = "../libserialize" }
syntax = { path = "../libsyntax" }
syntax_pos = { path = "../libsyntax_pos" }
Copy path View file
@@ -27,6 +27,7 @@
#![feature(staged_api)]
#![feature(test)]
#![feature(unicode)]
#![feature(rustc_highlight)]

extern crate arena;
extern crate getopts;
@@ -40,6 +41,7 @@ extern crate rustc_resolve;
extern crate rustc_lint;
extern crate rustc_back;
extern crate rustc_metadata;
extern crate rustc_highlight;
extern crate serialize;
#[macro_use] extern crate syntax;
extern crate syntax_pos;
@@ -73,8 +75,8 @@ pub mod core;
pub mod doctree;
pub mod fold;
pub mod html {
pub mod highlight;
pub mod escape;
pub use rustc_highlight::highlight;
pub use rustc_highlight::escape;
pub mod item_type;
pub mod format;
pub mod layout;