forked from extern/nushell
Add syntect (and borrow bat's theme file)
This commit is contained in:
parent
d5d4da0bf8
commit
27dbc1cb9a
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -1689,6 +1689,7 @@ dependencies = [
|
|||||||
"serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_yaml 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_yaml 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"subprocess 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
"subprocess 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"syntect 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"sys-info 0.5.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"sys-info 0.5.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"sysinfo 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"sysinfo 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -76,6 +76,7 @@ tempfile = "3.1.0"
|
|||||||
image = "0.21.2"
|
image = "0.21.2"
|
||||||
semver = "0.9.0"
|
semver = "0.9.0"
|
||||||
uuid = {version = "0.7.4", features = [ "v4", "serde" ]}
|
uuid = {version = "0.7.4", features = [ "v4", "serde" ]}
|
||||||
|
syntect = "3.2.0"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
pretty_assertions = "0.6.1"
|
pretty_assertions = "0.6.1"
|
||||||
|
BIN
assets/themes.bin
Normal file
BIN
assets/themes.bin
Normal file
Binary file not shown.
@ -494,7 +494,7 @@ fn classify_command(
|
|||||||
Ok(ClassifiedCommand::Internal(InternalCommand {
|
Ok(ClassifiedCommand::Internal(InternalCommand {
|
||||||
command,
|
command,
|
||||||
name_span: Some(head.span().clone()),
|
name_span: Some(head.span().clone()),
|
||||||
span_sources: context.span_sources.clone(),
|
source_map: context.source_map.clone(),
|
||||||
args,
|
args,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
use crate::commands::command::SinkCommandArgs;
|
use crate::commands::command::SinkCommandArgs;
|
||||||
|
use crate::context::{SourceMap, SpanSource};
|
||||||
use crate::errors::ShellError;
|
use crate::errors::ShellError;
|
||||||
use crate::format::GenericView;
|
use crate::format::GenericView;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
pub fn autoview(args: SinkCommandArgs) -> Result<(), ShellError> {
|
pub fn autoview(args: SinkCommandArgs) -> Result<(), ShellError> {
|
||||||
if args.input.len() > 0 {
|
if args.input.len() > 0 {
|
||||||
@ -11,6 +13,8 @@ pub fn autoview(args: SinkCommandArgs) -> Result<(), ShellError> {
|
|||||||
} = args.input[0]
|
} = args.input[0]
|
||||||
{
|
{
|
||||||
args.ctx.get_sink("binaryview").run(args)?;
|
args.ctx.get_sink("binaryview").run(args)?;
|
||||||
|
} else if is_single_text_value(&args.input) {
|
||||||
|
view_text_value(&args.input[0], &args.source_map);
|
||||||
} else if equal_shapes(&args.input) {
|
} else if equal_shapes(&args.input) {
|
||||||
args.ctx.get_sink("table").run(args)?;
|
args.ctx.get_sink("table").run(args)?;
|
||||||
} else {
|
} else {
|
||||||
@ -44,3 +48,76 @@ fn equal_shapes(input: &Vec<Spanned<Value>>) -> bool {
|
|||||||
|
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_single_text_value(input: &Vec<Spanned<Value>>) -> bool {
|
||||||
|
if input.len() != 1 {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if let Spanned {
|
||||||
|
item: Value::Primitive(Primitive::String(_)),
|
||||||
|
..
|
||||||
|
} = input[0]
|
||||||
|
{
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn view_text_value(value: &Spanned<Value>, source_map: &SourceMap) {
|
||||||
|
match value {
|
||||||
|
Spanned {
|
||||||
|
item: Value::Primitive(Primitive::String(s)),
|
||||||
|
span,
|
||||||
|
} => {
|
||||||
|
let source = span.source.map(|x| source_map.get(&x)).flatten();
|
||||||
|
|
||||||
|
if let Some(source) = source {
|
||||||
|
match source {
|
||||||
|
SpanSource::File(file) => {
|
||||||
|
let path = Path::new(file);
|
||||||
|
match path.extension() {
|
||||||
|
Some(extension) => {
|
||||||
|
use syntect::easy::HighlightLines;
|
||||||
|
use syntect::highlighting::{Style, ThemeSet};
|
||||||
|
use syntect::parsing::SyntaxSet;
|
||||||
|
use syntect::util::{as_24_bit_terminal_escaped, LinesWithEndings};
|
||||||
|
|
||||||
|
// Load these once at the start of your program
|
||||||
|
let ps = SyntaxSet::load_defaults_newlines();
|
||||||
|
|
||||||
|
if let Some(syntax) =
|
||||||
|
ps.find_syntax_by_extension(extension.to_str().unwrap())
|
||||||
|
{
|
||||||
|
let ts: ThemeSet = syntect::dumps::from_binary(include_bytes!(
|
||||||
|
"../../assets/themes.bin"
|
||||||
|
));
|
||||||
|
let mut h =
|
||||||
|
HighlightLines::new(syntax, &ts.themes["OneHalfDark"]);
|
||||||
|
|
||||||
|
for line in LinesWithEndings::from(s) {
|
||||||
|
let ranges: Vec<(Style, &str)> = h.highlight(line, &ps);
|
||||||
|
let escaped =
|
||||||
|
as_24_bit_terminal_escaped(&ranges[..], false);
|
||||||
|
print!("{}", escaped);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
println!("{}", s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
println!("{}", s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
println!("{}", s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
println!("{}", s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,16 +1,14 @@
|
|||||||
use crate::commands::command::Sink;
|
use crate::commands::command::Sink;
|
||||||
use crate::context::SpanSource;
|
use crate::context::SourceMap;
|
||||||
use crate::parser::{registry::Args, Span, Spanned, TokenNode};
|
use crate::parser::{registry::Args, Span, Spanned, TokenNode};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use bytes::{BufMut, BytesMut};
|
use bytes::{BufMut, BytesMut};
|
||||||
use futures::stream::StreamExt;
|
use futures::stream::StreamExt;
|
||||||
use futures_codec::{Decoder, Encoder, Framed};
|
use futures_codec::{Decoder, Encoder, Framed};
|
||||||
use log::{log_enabled, trace};
|
use log::{log_enabled, trace};
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::io::{Error, ErrorKind};
|
use std::io::{Error, ErrorKind};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use subprocess::Exec;
|
use subprocess::Exec;
|
||||||
use uuid::Uuid;
|
|
||||||
|
|
||||||
/// A simple `Codec` implementation that splits up data into lines.
|
/// A simple `Codec` implementation that splits up data into lines.
|
||||||
pub struct LinesCodec {}
|
pub struct LinesCodec {}
|
||||||
@ -119,7 +117,7 @@ impl SinkCommand {
|
|||||||
crate struct InternalCommand {
|
crate struct InternalCommand {
|
||||||
crate command: Arc<dyn Command>,
|
crate command: Arc<dyn Command>,
|
||||||
crate name_span: Option<Span>,
|
crate name_span: Option<Span>,
|
||||||
crate span_sources: HashMap<Uuid, SpanSource>,
|
crate source_map: SourceMap,
|
||||||
crate args: Args,
|
crate args: Args,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,7 +139,7 @@ impl InternalCommand {
|
|||||||
let result = context.run_command(
|
let result = context.run_command(
|
||||||
self.command,
|
self.command,
|
||||||
self.name_span.clone(),
|
self.name_span.clone(),
|
||||||
self.span_sources,
|
self.source_map,
|
||||||
self.args,
|
self.args,
|
||||||
objects,
|
objects,
|
||||||
)?;
|
)?;
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
use crate::context::SourceMap;
|
||||||
use crate::context::SpanSource;
|
use crate::context::SpanSource;
|
||||||
use crate::errors::ShellError;
|
use crate::errors::ShellError;
|
||||||
use crate::object::Value;
|
use crate::object::Value;
|
||||||
@ -8,7 +9,6 @@ use crate::parser::{
|
|||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use getset::Getters;
|
use getset::Getters;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
@ -18,7 +18,7 @@ pub struct CommandArgs {
|
|||||||
pub host: Arc<Mutex<dyn Host + Send>>,
|
pub host: Arc<Mutex<dyn Host + Send>>,
|
||||||
pub env: Arc<Mutex<Environment>>,
|
pub env: Arc<Mutex<Environment>>,
|
||||||
pub name_span: Option<Span>,
|
pub name_span: Option<Span>,
|
||||||
pub span_sources: HashMap<Uuid, SpanSource>,
|
pub source_map: SourceMap,
|
||||||
pub args: Args,
|
pub args: Args,
|
||||||
pub input: InputStream,
|
pub input: InputStream,
|
||||||
}
|
}
|
||||||
@ -53,7 +53,7 @@ impl CommandArgs {
|
|||||||
pub struct SinkCommandArgs {
|
pub struct SinkCommandArgs {
|
||||||
pub ctx: Context,
|
pub ctx: Context,
|
||||||
pub name_span: Option<Span>,
|
pub name_span: Option<Span>,
|
||||||
pub span_sources: HashMap<Uuid, SpanSource>,
|
pub source_map: SourceMap,
|
||||||
pub args: Args,
|
pub args: Args,
|
||||||
pub input: Vec<Spanned<Value>>,
|
pub input: Vec<Spanned<Value>>,
|
||||||
}
|
}
|
||||||
|
@ -17,11 +17,29 @@ pub enum SpanSource {
|
|||||||
Url(String),
|
Url(String),
|
||||||
File(String),
|
File(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
|
pub struct SourceMap(HashMap<Uuid, SpanSource>);
|
||||||
|
|
||||||
|
impl SourceMap {
|
||||||
|
pub fn insert(&mut self, uuid: Uuid, span_source: SpanSource) {
|
||||||
|
self.0.insert(uuid, span_source);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get(&self, uuid: &Uuid) -> Option<&SpanSource> {
|
||||||
|
self.0.get(uuid)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new() -> SourceMap {
|
||||||
|
SourceMap(HashMap::new())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Context {
|
pub struct Context {
|
||||||
commands: IndexMap<String, Arc<dyn Command>>,
|
commands: IndexMap<String, Arc<dyn Command>>,
|
||||||
sinks: IndexMap<String, Arc<dyn Sink>>,
|
sinks: IndexMap<String, Arc<dyn Sink>>,
|
||||||
crate span_sources: HashMap<Uuid, SpanSource>,
|
crate source_map: SourceMap,
|
||||||
crate host: Arc<Mutex<dyn Host + Send>>,
|
crate host: Arc<Mutex<dyn Host + Send>>,
|
||||||
crate env: Arc<Mutex<Environment>>,
|
crate env: Arc<Mutex<Environment>>,
|
||||||
}
|
}
|
||||||
@ -31,7 +49,7 @@ impl Context {
|
|||||||
Ok(Context {
|
Ok(Context {
|
||||||
commands: indexmap::IndexMap::new(),
|
commands: indexmap::IndexMap::new(),
|
||||||
sinks: indexmap::IndexMap::new(),
|
sinks: indexmap::IndexMap::new(),
|
||||||
span_sources: HashMap::new(),
|
source_map: SourceMap::new(),
|
||||||
host: Arc::new(Mutex::new(crate::env::host::BasicHost)),
|
host: Arc::new(Mutex::new(crate::env::host::BasicHost)),
|
||||||
env: Arc::new(Mutex::new(Environment::basic()?)),
|
env: Arc::new(Mutex::new(Environment::basic()?)),
|
||||||
})
|
})
|
||||||
@ -50,7 +68,7 @@ impl Context {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_span_source(&mut self, uuid: Uuid, span_source: SpanSource) {
|
pub fn add_span_source(&mut self, uuid: Uuid, span_source: SpanSource) {
|
||||||
self.span_sources.insert(uuid, span_source);
|
self.source_map.insert(uuid, span_source);
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn has_sink(&self, name: &str) -> bool {
|
crate fn has_sink(&self, name: &str) -> bool {
|
||||||
@ -71,7 +89,7 @@ impl Context {
|
|||||||
let command_args = SinkCommandArgs {
|
let command_args = SinkCommandArgs {
|
||||||
ctx: self.clone(),
|
ctx: self.clone(),
|
||||||
name_span,
|
name_span,
|
||||||
span_sources: self.span_sources.clone(),
|
source_map: self.source_map.clone(),
|
||||||
args,
|
args,
|
||||||
input,
|
input,
|
||||||
};
|
};
|
||||||
@ -95,7 +113,7 @@ impl Context {
|
|||||||
&mut self,
|
&mut self,
|
||||||
command: Arc<dyn Command>,
|
command: Arc<dyn Command>,
|
||||||
name_span: Option<Span>,
|
name_span: Option<Span>,
|
||||||
span_sources: HashMap<Uuid, SpanSource>,
|
source_map: SourceMap,
|
||||||
args: Args,
|
args: Args,
|
||||||
input: InputStream,
|
input: InputStream,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
@ -103,7 +121,7 @@ impl Context {
|
|||||||
host: self.host.clone(),
|
host: self.host.clone(),
|
||||||
env: self.env.clone(),
|
env: self.env.clone(),
|
||||||
name_span,
|
name_span,
|
||||||
span_sources,
|
source_map,
|
||||||
args,
|
args,
|
||||||
input,
|
input,
|
||||||
};
|
};
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#![feature(bind_by_move_pattern_guards)]
|
#![feature(bind_by_move_pattern_guards)]
|
||||||
#![feature(box_syntax)]
|
#![feature(box_syntax)]
|
||||||
#![feature(type_ascription)]
|
#![feature(type_ascription)]
|
||||||
|
#![feature(option_flattening)]
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod prelude;
|
mod prelude;
|
||||||
|
@ -9,8 +9,8 @@ use log::LevelFilter;
|
|||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn Error>> {
|
fn main() -> Result<(), Box<dyn Error>> {
|
||||||
let matches = App::new("nu shell")
|
let matches = App::new("nushell")
|
||||||
.version("0.5")
|
.version("0.1.3")
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("loglevel")
|
Arg::with_name("loglevel")
|
||||||
.short("l")
|
.short("l")
|
||||||
|
Loading…
Reference in New Issue
Block a user