mirror of
https://github.com/nushell/nushell.git
synced 2025-08-11 09:24:51 +02:00
Extract core stuff into own crates
This commit extracts five new crates: - nu-source, which contains the core source-code handling logic in Nu, including Text, Span, and also the pretty.rs-based debug logic - nu-parser, which is the parser and expander logic - nu-protocol, which is the bulk of the types and basic conveniences used by plugins - nu-errors, which contains ShellError, ParseError and error handling conveniences - nu-textview, which is the textview plugin extracted into a crate One of the major consequences of this refactor is that it's no longer possible to `impl X for Spanned<Y>` outside of the `nu-source` crate, so a lot of types became more concrete (Value became a concrete type instead of Spanned<Value>, for example). This also turned a number of inherent methods in the main nu crate into plain functions (impl Value {} became a bunch of functions in the `value` namespace in `crate::data::value`).
This commit is contained in:
@ -1,6 +1,7 @@
|
||||
use nu::{
|
||||
serve_plugin, CallInfo, CoerceInto, Plugin, Primitive, ReturnSuccess, ReturnValue, ShellError,
|
||||
Signature, UntaggedValue, Value,
|
||||
use nu::{serve_plugin, value, Plugin};
|
||||
use nu_errors::{CoerceInto, ShellError};
|
||||
use nu_protocol::{
|
||||
CallInfo, Primitive, ReturnSuccess, ReturnValue, Signature, UntaggedValue, Value,
|
||||
};
|
||||
use nu_source::TaggedItem;
|
||||
|
||||
@ -26,7 +27,7 @@ impl Average {
|
||||
value: UntaggedValue::Primitive(Primitive::Int(j)),
|
||||
tag,
|
||||
}) => {
|
||||
self.total = Some(UntaggedValue::int(i + j).into_value(tag));
|
||||
self.total = Some(value::int(i + j).into_value(tag));
|
||||
self.count += 1;
|
||||
Ok(())
|
||||
}
|
||||
@ -46,7 +47,7 @@ impl Average {
|
||||
value: UntaggedValue::Primitive(Primitive::Bytes(j)),
|
||||
tag,
|
||||
}) => {
|
||||
self.total = Some(UntaggedValue::bytes(b + j).into_value(tag));
|
||||
self.total = Some(value::bytes(b + j).into_value(tag));
|
||||
self.count += 1;
|
||||
Ok(())
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crossterm::{cursor, terminal, Attribute, RawScreen};
|
||||
use nu::{
|
||||
outln, serve_plugin, CallInfo, Plugin, Primitive, ShellError, Signature, UntaggedValue, Value,
|
||||
};
|
||||
use nu::{serve_plugin, Plugin};
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{outln, CallInfo, Primitive, Signature, UntaggedValue, Value};
|
||||
use nu_source::AnchorLocation;
|
||||
use pretty_hex::*;
|
||||
|
||||
|
@ -50,7 +50,7 @@ fn process_docker_output(cmd_output: &str, tag: Tag) -> Result<Vec<Value>, Shell
|
||||
for (i, v) in values.iter().enumerate() {
|
||||
dict.insert(
|
||||
header[i].to_string(),
|
||||
UntaggedValue::string(v.trim().to_string()),
|
||||
value::string(v.trim().to_string()),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,8 @@
|
||||
use nu::{
|
||||
serve_plugin, CallInfo, ColumnPath, Plugin, Primitive, ReturnSuccess, ReturnValue, ShellError,
|
||||
Signature, SpannedTypeName, SyntaxShape, UntaggedValue, Value,
|
||||
use nu::{serve_plugin, Plugin, ValueExt};
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{
|
||||
CallInfo, ColumnPath, Primitive, ReturnSuccess, ReturnValue, Signature, SpannedTypeName,
|
||||
SyntaxShape, UntaggedValue, Value,
|
||||
};
|
||||
use nu_source::Tagged;
|
||||
|
||||
|
@ -1,9 +1,11 @@
|
||||
#[macro_use]
|
||||
extern crate indexmap;
|
||||
|
||||
use nu::{
|
||||
serve_plugin, CallInfo, Plugin, Primitive, ReturnSuccess, ReturnValue, ShellError, Signature,
|
||||
SpannedTypeName, SyntaxShape, UntaggedValue, Value,
|
||||
use nu::{serve_plugin, value, Plugin};
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{
|
||||
CallInfo, Primitive, ReturnSuccess, ReturnValue, Signature, SpannedTypeName, SyntaxShape,
|
||||
UntaggedValue, Value,
|
||||
};
|
||||
use nu_source::Tag;
|
||||
|
||||
@ -56,11 +58,11 @@ impl Plugin for Embed {
|
||||
}
|
||||
|
||||
fn end_filter(&mut self) -> Result<Vec<ReturnValue>, ShellError> {
|
||||
let row = UntaggedValue::row(indexmap! {
|
||||
let row = value::row(indexmap! {
|
||||
match &self.field {
|
||||
Some(key) => key.clone(),
|
||||
None => "root".into(),
|
||||
} => UntaggedValue::table(&self.values).into_value(Tag::unknown()),
|
||||
} => value::table(&self.values).into_value(Tag::unknown()),
|
||||
})
|
||||
.into_untagged_value();
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
use nu::{
|
||||
serve_plugin, CallInfo, Plugin, Primitive, ReturnSuccess, ReturnValue, ShellError, Signature,
|
||||
SyntaxShape, UntaggedValue, Value,
|
||||
use nu::{serve_plugin, value, Plugin};
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{
|
||||
CallInfo, Primitive, ReturnSuccess, ReturnValue, Signature, SyntaxShape, UntaggedValue, Value,
|
||||
};
|
||||
|
||||
use nom::{
|
||||
@ -114,7 +115,7 @@ impl Plugin for Format {
|
||||
}
|
||||
|
||||
return Ok(vec![ReturnSuccess::value(
|
||||
UntaggedValue::string(output).into_untagged_value(),
|
||||
value::string(output).into_untagged_value(),
|
||||
)]);
|
||||
}
|
||||
_ => {}
|
||||
|
@ -1,6 +1,8 @@
|
||||
use nu::{
|
||||
did_you_mean, serve_plugin, CallInfo, ColumnPath, Plugin, Primitive, ReturnSuccess,
|
||||
ReturnValue, ShellError, ShellTypeName, Signature, SyntaxShape, UntaggedValue, Value,
|
||||
use nu::{did_you_mean, serve_plugin, value, Plugin, ValueExt};
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{
|
||||
CallInfo, ColumnPath, Primitive, ReturnSuccess, ReturnValue, ShellTypeName, Signature,
|
||||
SyntaxShape, UntaggedValue, Value,
|
||||
};
|
||||
use nu_source::{span_for_spanned_list, HasSpan, SpannedItem, Tagged};
|
||||
|
||||
@ -35,7 +37,7 @@ impl Inc {
|
||||
Some(Action::SemVerAction(act_on)) => {
|
||||
let mut ver = match semver::Version::parse(&input) {
|
||||
Ok(parsed_ver) => parsed_ver,
|
||||
Err(_) => return Ok(UntaggedValue::string(input.to_string())),
|
||||
Err(_) => return Ok(value::string(input.to_string())),
|
||||
};
|
||||
|
||||
match act_on {
|
||||
@ -44,11 +46,11 @@ impl Inc {
|
||||
SemVerAction::Patch => ver.increment_patch(),
|
||||
}
|
||||
|
||||
UntaggedValue::string(ver.to_string())
|
||||
value::string(ver.to_string())
|
||||
}
|
||||
Some(Action::Default) | None => match input.parse::<u64>() {
|
||||
Ok(v) => UntaggedValue::string(format!("{}", v + 1)),
|
||||
Err(_) => UntaggedValue::string(input),
|
||||
Ok(v) => value::string(format!("{}", v + 1)),
|
||||
Err(_) => value::string(input),
|
||||
},
|
||||
};
|
||||
|
||||
@ -78,10 +80,10 @@ impl Inc {
|
||||
fn inc(&self, value: Value) -> Result<Value, ShellError> {
|
||||
match &value.value {
|
||||
UntaggedValue::Primitive(Primitive::Int(i)) => {
|
||||
Ok(UntaggedValue::int(i + 1).into_value(value.tag()))
|
||||
Ok(value::int(i + 1).into_value(value.tag()))
|
||||
}
|
||||
UntaggedValue::Primitive(Primitive::Bytes(b)) => {
|
||||
Ok(UntaggedValue::bytes(b + 1 as u64).into_value(value.tag()))
|
||||
Ok(value::bytes(b + 1 as u64).into_value(value.tag()))
|
||||
}
|
||||
UntaggedValue::Primitive(Primitive::String(ref s)) => {
|
||||
Ok(self.apply(&s)?.into_value(value.tag()))
|
||||
@ -224,9 +226,10 @@ mod tests {
|
||||
|
||||
use super::{Inc, SemVerAction};
|
||||
use indexmap::IndexMap;
|
||||
use nu::{
|
||||
CallInfo, EvaluatedArgs, PathMember, Plugin, ReturnSuccess, TaggedDictBuilder,
|
||||
UnspannedPathMember, UntaggedValue, Value,
|
||||
use nu::{value, Plugin, TaggedDictBuilder};
|
||||
use nu_protocol::{
|
||||
CallInfo, EvaluatedArgs, PathMember, ReturnSuccess, UnspannedPathMember, UntaggedValue,
|
||||
Value,
|
||||
};
|
||||
use nu_source::{Span, Tag};
|
||||
|
||||
@ -246,7 +249,7 @@ mod tests {
|
||||
fn with_long_flag(&mut self, name: &str) -> &mut Self {
|
||||
self.flags.insert(
|
||||
name.to_string(),
|
||||
UntaggedValue::boolean(true).into_value(Tag::unknown()),
|
||||
value::boolean(true).into_value(Tag::unknown()),
|
||||
);
|
||||
self
|
||||
}
|
||||
@ -260,7 +263,7 @@ mod tests {
|
||||
.collect();
|
||||
|
||||
self.positionals
|
||||
.push(UntaggedValue::column_path(fields).into_untagged_value());
|
||||
.push(value::column_path(fields).into_untagged_value());
|
||||
self
|
||||
}
|
||||
|
||||
@ -274,7 +277,7 @@ mod tests {
|
||||
|
||||
fn cargo_sample_record(with_version: &str) -> Value {
|
||||
let mut package = TaggedDictBuilder::new(Tag::unknown());
|
||||
package.insert_untagged("version", UntaggedValue::string(with_version));
|
||||
package.insert_untagged("version", value::string(with_version));
|
||||
package.into_value()
|
||||
}
|
||||
|
||||
@ -357,21 +360,21 @@ mod tests {
|
||||
fn incs_major() {
|
||||
let mut inc = Inc::new();
|
||||
inc.for_semver(SemVerAction::Major);
|
||||
assert_eq!(inc.apply("0.1.3").unwrap(), UntaggedValue::string("1.0.0"));
|
||||
assert_eq!(inc.apply("0.1.3").unwrap(), value::string("1.0.0"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn incs_minor() {
|
||||
let mut inc = Inc::new();
|
||||
inc.for_semver(SemVerAction::Minor);
|
||||
assert_eq!(inc.apply("0.1.3").unwrap(), UntaggedValue::string("0.2.0"));
|
||||
assert_eq!(inc.apply("0.1.3").unwrap(), value::string("0.2.0"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn incs_patch() {
|
||||
let mut inc = Inc::new();
|
||||
inc.for_semver(SemVerAction::Patch);
|
||||
assert_eq!(inc.apply("0.1.3").unwrap(), UntaggedValue::string("0.1.4"));
|
||||
assert_eq!(inc.apply("0.1.3").unwrap(), value::string("0.1.4"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -396,7 +399,7 @@ mod tests {
|
||||
..
|
||||
}) => assert_eq!(
|
||||
*o.get_data(&String::from("version")).borrow(),
|
||||
UntaggedValue::string(String::from("1.0.0")).into_untagged_value()
|
||||
value::string(String::from("1.0.0")).into_untagged_value()
|
||||
),
|
||||
_ => {}
|
||||
}
|
||||
@ -424,7 +427,7 @@ mod tests {
|
||||
..
|
||||
}) => assert_eq!(
|
||||
*o.get_data(&String::from("version")).borrow(),
|
||||
UntaggedValue::string(String::from("0.2.0")).into_untagged_value()
|
||||
value::string(String::from("0.2.0")).into_untagged_value()
|
||||
),
|
||||
_ => {}
|
||||
}
|
||||
@ -453,7 +456,7 @@ mod tests {
|
||||
..
|
||||
}) => assert_eq!(
|
||||
*o.get_data(&field).borrow(),
|
||||
UntaggedValue::string(String::from("0.1.4")).into_untagged_value()
|
||||
value::string(String::from("0.1.4")).into_untagged_value()
|
||||
),
|
||||
_ => {}
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
use nu::{
|
||||
serve_plugin, CallInfo, ColumnPath, Plugin, Primitive, ReturnSuccess, ReturnValue, ShellError,
|
||||
ShellTypeName, Signature, SpannedTypeName, SyntaxShape, UntaggedValue, Value,
|
||||
use nu::{serve_plugin, Plugin, ValueExt};
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{
|
||||
CallInfo, ColumnPath, Primitive, ReturnSuccess, ReturnValue, ShellTypeName, Signature,
|
||||
SpannedTypeName, SyntaxShape, UntaggedValue, Value,
|
||||
};
|
||||
use nu_source::SpannedItem;
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
use nu::{
|
||||
serve_plugin, CallInfo, Plugin, Primitive, ReturnSuccess, ReturnValue, ShellError, Signature,
|
||||
SyntaxShape, UntaggedValue, Value,
|
||||
use nu::{serve_plugin, Plugin};
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{
|
||||
CallInfo, Primitive, ReturnSuccess, ReturnValue, Signature, SyntaxShape, UntaggedValue, Value,
|
||||
};
|
||||
|
||||
use regex::Regex;
|
||||
|
@ -1,6 +1,7 @@
|
||||
use nu::{
|
||||
serve_plugin, CallInfo, Plugin, Primitive, ReturnSuccess, ReturnValue, ShellError, Signature,
|
||||
SyntaxShape, TaggedDictBuilder, UntaggedValue, Value,
|
||||
use nu::{serve_plugin, value, Plugin, TaggedDictBuilder};
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{
|
||||
CallInfo, Primitive, ReturnSuccess, ReturnValue, Signature, SyntaxShape, UntaggedValue, Value,
|
||||
};
|
||||
|
||||
use nom::{
|
||||
@ -139,10 +140,7 @@ impl Plugin for Parse {
|
||||
let mut dict = TaggedDictBuilder::new(tag);
|
||||
|
||||
for (idx, column_name) in self.column_names.iter().enumerate() {
|
||||
dict.insert_untagged(
|
||||
column_name,
|
||||
UntaggedValue::string(&cap[idx + 1].to_string()),
|
||||
);
|
||||
dict.insert_untagged(column_name, value::string(&cap[idx + 1].to_string()));
|
||||
}
|
||||
|
||||
results.push(ReturnSuccess::value(dict.into_value()));
|
||||
|
@ -5,10 +5,9 @@ use heim::process::{self as process, Process, ProcessResult};
|
||||
use heim::units::{ratio, Ratio};
|
||||
use std::usize;
|
||||
|
||||
use nu::{
|
||||
serve_plugin, CallInfo, Plugin, ReturnSuccess, ReturnValue, ShellError, Signature,
|
||||
TaggedDictBuilder, UntaggedValue, Value,
|
||||
};
|
||||
use nu::{serve_plugin, value, Plugin, TaggedDictBuilder};
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{CallInfo, ReturnSuccess, ReturnValue, Signature, Value};
|
||||
use nu_source::Tag;
|
||||
|
||||
use std::time::Duration;
|
||||
@ -43,14 +42,14 @@ async fn ps(tag: Tag) -> Vec<Value> {
|
||||
while let Some(res) = processes.next().await {
|
||||
if let Ok((process, usage)) = res {
|
||||
let mut dict = TaggedDictBuilder::new(&tag);
|
||||
dict.insert_untagged("pid", UntaggedValue::int(process.pid()));
|
||||
dict.insert_untagged("pid", value::int(process.pid()));
|
||||
if let Ok(name) = process.name().await {
|
||||
dict.insert_untagged("name", UntaggedValue::string(name));
|
||||
dict.insert_untagged("name", value::string(name));
|
||||
}
|
||||
if let Ok(status) = process.status().await {
|
||||
dict.insert_untagged("status", UntaggedValue::string(format!("{:?}", status)));
|
||||
dict.insert_untagged("status", value::string(format!("{:?}", status)));
|
||||
}
|
||||
dict.insert_untagged("cpu", UntaggedValue::number(usage.get::<ratio::percent>()));
|
||||
dict.insert_untagged("cpu", value::number(usage.get::<ratio::percent>()));
|
||||
output.push(dict.into_value());
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
use nu::{
|
||||
serve_plugin, CallInfo, CoerceInto, Plugin, Primitive, ReturnSuccess, ReturnValue, ShellError,
|
||||
Signature, SyntaxShape, UntaggedValue, Value,
|
||||
use nu::{serve_plugin, Plugin};
|
||||
use nu_errors::{CoerceInto, ShellError};
|
||||
use nu_protocol::{
|
||||
CallInfo, Primitive, ReturnSuccess, ReturnValue, Signature, SyntaxShape, UntaggedValue, Value,
|
||||
};
|
||||
use nu_source::TaggedItem;
|
||||
|
||||
|
@ -1,6 +1,8 @@
|
||||
use nu::{
|
||||
did_you_mean, serve_plugin, CallInfo, ColumnPath, Plugin, Primitive, ReturnSuccess,
|
||||
ReturnValue, ShellError, ShellTypeName, Signature, SyntaxShape, UntaggedValue, Value,
|
||||
use nu::{did_you_mean, serve_plugin, value, Plugin, ValueExt};
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{
|
||||
CallInfo, ColumnPath, Primitive, ReturnSuccess, ReturnValue, ShellTypeName, Signature,
|
||||
SyntaxShape, UntaggedValue, Value,
|
||||
};
|
||||
use nu_source::{span_for_spanned_list, Tagged};
|
||||
|
||||
@ -33,15 +35,15 @@ impl Str {
|
||||
|
||||
fn apply(&self, input: &str) -> Result<UntaggedValue, ShellError> {
|
||||
let applied = match self.action.as_ref() {
|
||||
Some(Action::Downcase) => UntaggedValue::string(input.to_ascii_lowercase()),
|
||||
Some(Action::Upcase) => UntaggedValue::string(input.to_ascii_uppercase()),
|
||||
Some(Action::Downcase) => value::string(input.to_ascii_lowercase()),
|
||||
Some(Action::Upcase) => value::string(input.to_ascii_uppercase()),
|
||||
Some(Action::Substring(s, e)) => {
|
||||
let end: usize = cmp::min(*e, input.len());
|
||||
let start: usize = *s;
|
||||
if start > input.len() - 1 {
|
||||
UntaggedValue::string("")
|
||||
value::string("")
|
||||
} else {
|
||||
UntaggedValue::string(
|
||||
value::string(
|
||||
&input
|
||||
.chars()
|
||||
.skip(start)
|
||||
@ -52,11 +54,11 @@ impl Str {
|
||||
}
|
||||
Some(Action::ToInteger) => match input.trim() {
|
||||
other => match other.parse::<i64>() {
|
||||
Ok(v) => UntaggedValue::int(v),
|
||||
Err(_) => UntaggedValue::string(input),
|
||||
Ok(v) => value::int(v),
|
||||
Err(_) => value::string(input),
|
||||
},
|
||||
},
|
||||
None => UntaggedValue::string(input),
|
||||
None => value::string(input),
|
||||
};
|
||||
|
||||
Ok(applied)
|
||||
@ -267,9 +269,10 @@ fn main() {
|
||||
mod tests {
|
||||
use super::{Action, Str};
|
||||
use indexmap::IndexMap;
|
||||
use nu::{
|
||||
CallInfo, EvaluatedArgs, Plugin, Primitive, ReturnSuccess, TaggedDictBuilder,
|
||||
UnspannedPathMember, UntaggedValue, Value,
|
||||
use nu::{value, Plugin, TaggedDictBuilder};
|
||||
use nu_protocol::{
|
||||
CallInfo, EvaluatedArgs, Primitive, ReturnSuccess, UnspannedPathMember, UntaggedValue,
|
||||
Value,
|
||||
};
|
||||
use nu_source::Tag;
|
||||
use num_bigint::BigInt;
|
||||
@ -290,7 +293,7 @@ mod tests {
|
||||
fn with_named_parameter(&mut self, name: &str, value: &str) -> &mut Self {
|
||||
self.flags.insert(
|
||||
name.to_string(),
|
||||
UntaggedValue::string(value).into_value(Tag::unknown()),
|
||||
value::string(value).into_value(Tag::unknown()),
|
||||
);
|
||||
self
|
||||
}
|
||||
@ -298,7 +301,7 @@ mod tests {
|
||||
fn with_long_flag(&mut self, name: &str) -> &mut Self {
|
||||
self.flags.insert(
|
||||
name.to_string(),
|
||||
UntaggedValue::boolean(true).into_value(Tag::unknown()),
|
||||
value::boolean(true).into_value(Tag::unknown()),
|
||||
);
|
||||
self
|
||||
}
|
||||
@ -306,7 +309,7 @@ mod tests {
|
||||
fn with_parameter(&mut self, name: &str) -> &mut Self {
|
||||
let fields: Vec<Value> = name
|
||||
.split(".")
|
||||
.map(|s| UntaggedValue::string(s.to_string()).into_value(Tag::unknown()))
|
||||
.map(|s| value::string(s.to_string()).into_value(Tag::unknown()))
|
||||
.collect();
|
||||
|
||||
self.positionals
|
||||
@ -324,12 +327,12 @@ mod tests {
|
||||
|
||||
fn structured_sample_record(key: &str, value: &str) -> Value {
|
||||
let mut record = TaggedDictBuilder::new(Tag::unknown());
|
||||
record.insert_untagged(key.clone(), UntaggedValue::string(value));
|
||||
record.insert_untagged(key.clone(), value::string(value));
|
||||
record.into_value()
|
||||
}
|
||||
|
||||
fn unstructured_sample_record(value: &str) -> Value {
|
||||
UntaggedValue::string(value).into_value(Tag::unknown())
|
||||
value::string(value).into_value(Tag::unknown())
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -416,30 +419,21 @@ mod tests {
|
||||
fn str_downcases() {
|
||||
let mut strutils = Str::new();
|
||||
strutils.for_downcase();
|
||||
assert_eq!(
|
||||
strutils.apply("ANDRES").unwrap(),
|
||||
UntaggedValue::string("andres")
|
||||
);
|
||||
assert_eq!(strutils.apply("ANDRES").unwrap(), value::string("andres"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn str_upcases() {
|
||||
let mut strutils = Str::new();
|
||||
strutils.for_upcase();
|
||||
assert_eq!(
|
||||
strutils.apply("andres").unwrap(),
|
||||
UntaggedValue::string("ANDRES")
|
||||
);
|
||||
assert_eq!(strutils.apply("andres").unwrap(), value::string("ANDRES"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn str_to_int() {
|
||||
let mut strutils = Str::new();
|
||||
strutils.for_to_int();
|
||||
assert_eq!(
|
||||
strutils.apply("9999").unwrap(),
|
||||
UntaggedValue::int(9999 as i64)
|
||||
);
|
||||
assert_eq!(strutils.apply("9999").unwrap(), value::int(9999 as i64));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -464,7 +458,7 @@ mod tests {
|
||||
..
|
||||
}) => assert_eq!(
|
||||
*o.get_data(&String::from("name")).borrow(),
|
||||
UntaggedValue::string(String::from("JOTANDREHUDA")).into_untagged_value()
|
||||
value::string(String::from("JOTANDREHUDA")).into_untagged_value()
|
||||
),
|
||||
_ => {}
|
||||
}
|
||||
@ -512,7 +506,7 @@ mod tests {
|
||||
..
|
||||
}) => assert_eq!(
|
||||
*o.get_data(&String::from("name")).borrow(),
|
||||
UntaggedValue::string(String::from("jotandrehuda")).into_untagged_value()
|
||||
value::string(String::from("jotandrehuda")).into_untagged_value()
|
||||
),
|
||||
_ => {}
|
||||
}
|
||||
@ -560,7 +554,7 @@ mod tests {
|
||||
..
|
||||
}) => assert_eq!(
|
||||
*o.get_data(&String::from("Nu_birthday")).borrow(),
|
||||
UntaggedValue::int(10).into_untagged_value()
|
||||
value::int(10).into_untagged_value()
|
||||
),
|
||||
_ => {}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
use nu::{
|
||||
serve_plugin, CallInfo, Plugin, Primitive, ReturnSuccess, ReturnValue, ShellError, Signature,
|
||||
UntaggedValue, Value,
|
||||
use nu::{serve_plugin, value, Plugin};
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{
|
||||
CallInfo, Primitive, ReturnSuccess, ReturnValue, Signature, UntaggedValue, Value,
|
||||
};
|
||||
|
||||
struct Sum {
|
||||
@ -21,7 +22,7 @@ impl Sum {
|
||||
tag,
|
||||
}) => {
|
||||
//TODO: handle overflow
|
||||
self.total = Some(UntaggedValue::int(i + j).into_value(tag));
|
||||
self.total = Some(value::int(i + j).into_value(tag));
|
||||
Ok(())
|
||||
}
|
||||
None => {
|
||||
@ -42,7 +43,7 @@ impl Sum {
|
||||
tag,
|
||||
}) => {
|
||||
//TODO: handle overflow
|
||||
self.total = Some(UntaggedValue::bytes(b + j).into_value(tag));
|
||||
self.total = Some(value::bytes(b + j).into_value(tag));
|
||||
Ok(())
|
||||
}
|
||||
None => {
|
||||
|
@ -4,10 +4,9 @@ use futures::executor::block_on;
|
||||
use futures::stream::StreamExt;
|
||||
use heim::units::{frequency, information, thermodynamic_temperature, time};
|
||||
use heim::{disk, host, memory, net, sensors};
|
||||
use nu::{
|
||||
serve_plugin, CallInfo, Plugin, Primitive, ReturnSuccess, ReturnValue, ShellError, Signature,
|
||||
TaggedDictBuilder, UntaggedValue, Value,
|
||||
};
|
||||
use nu::{primitive, serve_plugin, value, Plugin, TaggedDictBuilder};
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{CallInfo, ReturnSuccess, ReturnValue, Signature, UntaggedValue, Value};
|
||||
use nu_source::Tag;
|
||||
|
||||
struct Sys;
|
||||
@ -21,26 +20,26 @@ async fn cpu(tag: Tag) -> Option<Value> {
|
||||
match futures::future::try_join(heim::cpu::logical_count(), heim::cpu::frequency()).await {
|
||||
Ok((num_cpu, cpu_speed)) => {
|
||||
let mut cpu_idx = TaggedDictBuilder::with_capacity(tag, 4);
|
||||
cpu_idx.insert_untagged("cores", Primitive::number(num_cpu));
|
||||
cpu_idx.insert_untagged("cores", primitive::number(num_cpu));
|
||||
|
||||
let current_speed =
|
||||
(cpu_speed.current().get::<frequency::hertz>() as f64 / 1_000_000_000.0 * 100.0)
|
||||
.round()
|
||||
/ 100.0;
|
||||
cpu_idx.insert_untagged("current ghz", Primitive::number(current_speed));
|
||||
cpu_idx.insert_untagged("current ghz", primitive::number(current_speed));
|
||||
|
||||
if let Some(min_speed) = cpu_speed.min() {
|
||||
let min_speed =
|
||||
(min_speed.get::<frequency::hertz>() as f64 / 1_000_000_000.0 * 100.0).round()
|
||||
/ 100.0;
|
||||
cpu_idx.insert_untagged("min ghz", Primitive::number(min_speed));
|
||||
cpu_idx.insert_untagged("min ghz", primitive::number(min_speed));
|
||||
}
|
||||
|
||||
if let Some(max_speed) = cpu_speed.max() {
|
||||
let max_speed =
|
||||
(max_speed.get::<frequency::hertz>() as f64 / 1_000_000_000.0 * 100.0).round()
|
||||
/ 100.0;
|
||||
cpu_idx.insert_untagged("max ghz", Primitive::number(max_speed));
|
||||
cpu_idx.insert_untagged("max ghz", primitive::number(max_speed));
|
||||
}
|
||||
|
||||
Some(cpu_idx.into_value())
|
||||
@ -58,22 +57,22 @@ async fn mem(tag: Tag) -> Value {
|
||||
if let Ok(memory) = memory_result {
|
||||
dict.insert_untagged(
|
||||
"total",
|
||||
UntaggedValue::bytes(memory.total().get::<information::byte>()),
|
||||
value::bytes(memory.total().get::<information::byte>()),
|
||||
);
|
||||
dict.insert_untagged(
|
||||
"free",
|
||||
UntaggedValue::bytes(memory.free().get::<information::byte>()),
|
||||
value::bytes(memory.free().get::<information::byte>()),
|
||||
);
|
||||
}
|
||||
|
||||
if let Ok(swap) = swap_result {
|
||||
dict.insert_untagged(
|
||||
"swap total",
|
||||
UntaggedValue::bytes(swap.total().get::<information::byte>()),
|
||||
value::bytes(swap.total().get::<information::byte>()),
|
||||
);
|
||||
dict.insert_untagged(
|
||||
"swap free",
|
||||
UntaggedValue::bytes(swap.free().get::<information::byte>()),
|
||||
value::bytes(swap.free().get::<information::byte>()),
|
||||
);
|
||||
}
|
||||
|
||||
@ -88,13 +87,10 @@ async fn host(tag: Tag) -> Value {
|
||||
|
||||
// OS
|
||||
if let Ok(platform) = platform_result {
|
||||
dict.insert_untagged("name", UntaggedValue::string(platform.system()));
|
||||
dict.insert_untagged("release", UntaggedValue::string(platform.release()));
|
||||
dict.insert_untagged("hostname", UntaggedValue::string(platform.hostname()));
|
||||
dict.insert_untagged(
|
||||
"arch",
|
||||
UntaggedValue::string(platform.architecture().as_str()),
|
||||
);
|
||||
dict.insert_untagged("name", value::string(platform.system()));
|
||||
dict.insert_untagged("release", value::string(platform.release()));
|
||||
dict.insert_untagged("hostname", value::string(platform.hostname()));
|
||||
dict.insert_untagged("arch", value::string(platform.architecture().as_str()));
|
||||
}
|
||||
|
||||
// Uptime
|
||||
@ -107,10 +103,10 @@ async fn host(tag: Tag) -> Value {
|
||||
let minutes = (uptime - days * 60 * 60 * 24 - hours * 60 * 60) / 60;
|
||||
let seconds = uptime % 60;
|
||||
|
||||
uptime_dict.insert_untagged("days", UntaggedValue::int(days));
|
||||
uptime_dict.insert_untagged("hours", UntaggedValue::int(hours));
|
||||
uptime_dict.insert_untagged("mins", UntaggedValue::int(minutes));
|
||||
uptime_dict.insert_untagged("secs", UntaggedValue::int(seconds));
|
||||
uptime_dict.insert_untagged("days", value::int(days));
|
||||
uptime_dict.insert_untagged("hours", value::int(hours));
|
||||
uptime_dict.insert_untagged("mins", value::int(minutes));
|
||||
uptime_dict.insert_untagged("secs", value::int(seconds));
|
||||
|
||||
dict.insert_value("uptime", uptime_dict);
|
||||
}
|
||||
@ -121,7 +117,7 @@ async fn host(tag: Tag) -> Value {
|
||||
while let Some(user) = users.next().await {
|
||||
if let Ok(user) = user {
|
||||
user_vec.push(Value {
|
||||
value: UntaggedValue::string(user.username()),
|
||||
value: value::string(user.username()),
|
||||
tag: tag.clone(),
|
||||
});
|
||||
}
|
||||
@ -140,31 +136,28 @@ async fn disks(tag: Tag) -> Option<UntaggedValue> {
|
||||
let mut dict = TaggedDictBuilder::with_capacity(&tag, 6);
|
||||
dict.insert_untagged(
|
||||
"device",
|
||||
UntaggedValue::string(
|
||||
value::string(
|
||||
part.device()
|
||||
.unwrap_or_else(|| OsStr::new("N/A"))
|
||||
.to_string_lossy(),
|
||||
),
|
||||
);
|
||||
|
||||
dict.insert_untagged("type", UntaggedValue::string(part.file_system().as_str()));
|
||||
dict.insert_untagged(
|
||||
"mount",
|
||||
UntaggedValue::string(part.mount_point().to_string_lossy()),
|
||||
);
|
||||
dict.insert_untagged("type", value::string(part.file_system().as_str()));
|
||||
dict.insert_untagged("mount", value::string(part.mount_point().to_string_lossy()));
|
||||
|
||||
if let Ok(usage) = disk::usage(part.mount_point().to_path_buf()).await {
|
||||
dict.insert_untagged(
|
||||
"total",
|
||||
UntaggedValue::bytes(usage.total().get::<information::byte>()),
|
||||
value::bytes(usage.total().get::<information::byte>()),
|
||||
);
|
||||
dict.insert_untagged(
|
||||
"used",
|
||||
UntaggedValue::bytes(usage.used().get::<information::byte>()),
|
||||
value::bytes(usage.used().get::<information::byte>()),
|
||||
);
|
||||
dict.insert_untagged(
|
||||
"free",
|
||||
UntaggedValue::bytes(usage.free().get::<information::byte>()),
|
||||
value::bytes(usage.free().get::<information::byte>()),
|
||||
);
|
||||
}
|
||||
|
||||
@ -188,28 +181,24 @@ async fn battery(tag: Tag) -> Option<UntaggedValue> {
|
||||
if let Ok(battery) = battery {
|
||||
let mut dict = TaggedDictBuilder::new(&tag);
|
||||
if let Some(vendor) = battery.vendor() {
|
||||
dict.insert_untagged("vendor", UntaggedValue::string(vendor));
|
||||
dict.insert_untagged("vendor", value::string(vendor));
|
||||
}
|
||||
if let Some(model) = battery.model() {
|
||||
dict.insert_untagged("model", UntaggedValue::string(model));
|
||||
dict.insert_untagged("model", value::string(model));
|
||||
}
|
||||
if let Some(cycles) = battery.cycle_count() {
|
||||
dict.insert_untagged("cycles", UntaggedValue::int(cycles));
|
||||
dict.insert_untagged("cycles", value::int(cycles));
|
||||
}
|
||||
if let Some(time_to_full) = battery.time_to_full() {
|
||||
dict.insert_untagged(
|
||||
"mins to full",
|
||||
UntaggedValue::number(
|
||||
time_to_full.get::<battery::units::time::minute>(),
|
||||
),
|
||||
value::number(time_to_full.get::<battery::units::time::minute>()),
|
||||
);
|
||||
}
|
||||
if let Some(time_to_empty) = battery.time_to_empty() {
|
||||
dict.insert_untagged(
|
||||
"mins to empty",
|
||||
UntaggedValue::number(
|
||||
time_to_empty.get::<battery::units::time::minute>(),
|
||||
),
|
||||
value::number(time_to_empty.get::<battery::units::time::minute>()),
|
||||
);
|
||||
}
|
||||
output.push(dict.into_value());
|
||||
@ -232,13 +221,13 @@ async fn temp(tag: Tag) -> Option<UntaggedValue> {
|
||||
while let Some(sensor) = sensors.next().await {
|
||||
if let Ok(sensor) = sensor {
|
||||
let mut dict = TaggedDictBuilder::new(&tag);
|
||||
dict.insert_untagged("unit", UntaggedValue::string(sensor.unit()));
|
||||
dict.insert_untagged("unit", value::string(sensor.unit()));
|
||||
if let Some(label) = sensor.label() {
|
||||
dict.insert_untagged("label", UntaggedValue::string(label));
|
||||
dict.insert_untagged("label", value::string(label));
|
||||
}
|
||||
dict.insert_untagged(
|
||||
"temp",
|
||||
UntaggedValue::number(
|
||||
value::number(
|
||||
sensor
|
||||
.current()
|
||||
.get::<thermodynamic_temperature::degree_celsius>(),
|
||||
@ -247,15 +236,13 @@ async fn temp(tag: Tag) -> Option<UntaggedValue> {
|
||||
if let Some(high) = sensor.high() {
|
||||
dict.insert_untagged(
|
||||
"high",
|
||||
UntaggedValue::number(high.get::<thermodynamic_temperature::degree_celsius>()),
|
||||
value::number(high.get::<thermodynamic_temperature::degree_celsius>()),
|
||||
);
|
||||
}
|
||||
if let Some(critical) = sensor.critical() {
|
||||
dict.insert_untagged(
|
||||
"critical",
|
||||
UntaggedValue::number(
|
||||
critical.get::<thermodynamic_temperature::degree_celsius>(),
|
||||
),
|
||||
value::number(critical.get::<thermodynamic_temperature::degree_celsius>()),
|
||||
);
|
||||
}
|
||||
|
||||
@ -276,14 +263,14 @@ async fn net(tag: Tag) -> Option<UntaggedValue> {
|
||||
while let Some(nic) = io_counters.next().await {
|
||||
if let Ok(nic) = nic {
|
||||
let mut network_idx = TaggedDictBuilder::with_capacity(&tag, 3);
|
||||
network_idx.insert_untagged("name", UntaggedValue::string(nic.interface()));
|
||||
network_idx.insert_untagged("name", value::string(nic.interface()));
|
||||
network_idx.insert_untagged(
|
||||
"sent",
|
||||
UntaggedValue::bytes(nic.bytes_sent().get::<information::byte>()),
|
||||
value::bytes(nic.bytes_sent().get::<information::byte>()),
|
||||
);
|
||||
network_idx.insert_untagged(
|
||||
"recv",
|
||||
UntaggedValue::bytes(nic.bytes_recv().get::<information::byte>()),
|
||||
value::bytes(nic.bytes_recv().get::<information::byte>()),
|
||||
);
|
||||
output.push(network_idx.into_value());
|
||||
}
|
||||
|
@ -1,293 +0,0 @@
|
||||
use crossterm::{cursor, terminal, RawScreen};
|
||||
use crossterm::{InputEvent, KeyEvent};
|
||||
use nu::{
|
||||
outln, serve_plugin, CallInfo, Plugin, Primitive, ShellError, Signature, UntaggedValue, Value,
|
||||
};
|
||||
use nu_source::AnchorLocation;
|
||||
|
||||
use syntect::easy::HighlightLines;
|
||||
use syntect::highlighting::{Style, ThemeSet};
|
||||
use syntect::parsing::SyntaxSet;
|
||||
|
||||
use std::io::Write;
|
||||
use std::path::Path;
|
||||
|
||||
enum DrawCommand {
|
||||
DrawString(Style, String),
|
||||
NextLine,
|
||||
}
|
||||
|
||||
struct TextView;
|
||||
|
||||
impl TextView {
|
||||
fn new() -> TextView {
|
||||
TextView
|
||||
}
|
||||
}
|
||||
|
||||
impl Plugin for TextView {
|
||||
fn config(&mut self) -> Result<Signature, ShellError> {
|
||||
Ok(Signature::build("textview").desc("Autoview of text data."))
|
||||
}
|
||||
|
||||
fn sink(&mut self, _call_info: CallInfo, input: Vec<Value>) {
|
||||
view_text_value(&input[0]);
|
||||
}
|
||||
}
|
||||
|
||||
fn paint_textview(
|
||||
draw_commands: &Vec<DrawCommand>,
|
||||
starting_row: usize,
|
||||
use_color_buffer: bool,
|
||||
) -> usize {
|
||||
let terminal = terminal();
|
||||
let cursor = cursor();
|
||||
|
||||
let size = terminal.terminal_size();
|
||||
|
||||
// render
|
||||
let mut pos = 0;
|
||||
let width = size.0 as usize;
|
||||
let height = size.1 as usize - 1;
|
||||
let mut frame_buffer = vec![];
|
||||
|
||||
for command in draw_commands {
|
||||
match command {
|
||||
DrawCommand::DrawString(style, string) => {
|
||||
for chr in string.chars() {
|
||||
if chr == '\t' {
|
||||
for _ in 0..8 {
|
||||
frame_buffer.push((
|
||||
' ',
|
||||
style.foreground.r,
|
||||
style.foreground.g,
|
||||
style.foreground.b,
|
||||
));
|
||||
}
|
||||
pos += 8;
|
||||
} else {
|
||||
frame_buffer.push((
|
||||
chr,
|
||||
style.foreground.r,
|
||||
style.foreground.g,
|
||||
style.foreground.b,
|
||||
));
|
||||
pos += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
DrawCommand::NextLine => {
|
||||
for _ in 0..(width - pos % width) {
|
||||
frame_buffer.push((' ', 0, 0, 0));
|
||||
}
|
||||
pos += width - pos % width;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let num_frame_buffer_rows = frame_buffer.len() / width;
|
||||
let buffer_needs_scrolling = num_frame_buffer_rows > height;
|
||||
|
||||
// display
|
||||
let mut ansi_strings = vec![];
|
||||
let mut normal_chars = vec![];
|
||||
|
||||
for c in
|
||||
&frame_buffer[starting_row * width..std::cmp::min(pos, (starting_row + height) * width)]
|
||||
{
|
||||
if use_color_buffer {
|
||||
ansi_strings.push(ansi_term::Colour::RGB(c.1, c.2, c.3).paint(format!("{}", c.0)));
|
||||
} else {
|
||||
normal_chars.push(c.0);
|
||||
}
|
||||
}
|
||||
|
||||
if buffer_needs_scrolling {
|
||||
let _ = cursor.goto(0, 0);
|
||||
}
|
||||
|
||||
if use_color_buffer {
|
||||
print!("{}", ansi_term::ANSIStrings(&ansi_strings));
|
||||
} else {
|
||||
let s: String = normal_chars.into_iter().collect();
|
||||
print!("{}", s);
|
||||
}
|
||||
|
||||
if buffer_needs_scrolling {
|
||||
let _ = cursor.goto(0, size.1);
|
||||
print!(
|
||||
"{}",
|
||||
ansi_term::Colour::Blue.paint("[ESC to quit, arrow keys to move]")
|
||||
);
|
||||
}
|
||||
|
||||
let _ = std::io::stdout().flush();
|
||||
|
||||
num_frame_buffer_rows
|
||||
}
|
||||
|
||||
fn scroll_view_lines_if_needed(draw_commands: Vec<DrawCommand>, use_color_buffer: bool) {
|
||||
let mut starting_row = 0;
|
||||
|
||||
if let Ok(_raw) = RawScreen::into_raw_mode() {
|
||||
let terminal = terminal();
|
||||
let mut size = terminal.terminal_size();
|
||||
let height = size.1 as usize - 1;
|
||||
|
||||
let mut max_bottom_line = paint_textview(&draw_commands, starting_row, use_color_buffer);
|
||||
|
||||
// Only scroll if needed
|
||||
if max_bottom_line > height as usize {
|
||||
let cursor = cursor();
|
||||
let _ = cursor.hide();
|
||||
|
||||
let input = crossterm::input();
|
||||
let mut sync_stdin = input.read_sync();
|
||||
|
||||
loop {
|
||||
if let Some(ev) = sync_stdin.next() {
|
||||
match ev {
|
||||
InputEvent::Keyboard(k) => match k {
|
||||
KeyEvent::Esc => {
|
||||
break;
|
||||
}
|
||||
KeyEvent::Up | KeyEvent::Char('k') => {
|
||||
if starting_row > 0 {
|
||||
starting_row -= 1;
|
||||
max_bottom_line = paint_textview(
|
||||
&draw_commands,
|
||||
starting_row,
|
||||
use_color_buffer,
|
||||
);
|
||||
}
|
||||
}
|
||||
KeyEvent::Down | KeyEvent::Char('j') => {
|
||||
if starting_row < (max_bottom_line - height) {
|
||||
starting_row += 1;
|
||||
}
|
||||
max_bottom_line =
|
||||
paint_textview(&draw_commands, starting_row, use_color_buffer);
|
||||
}
|
||||
KeyEvent::PageUp | KeyEvent::Ctrl('b') => {
|
||||
starting_row -= std::cmp::min(height, starting_row);
|
||||
max_bottom_line =
|
||||
paint_textview(&draw_commands, starting_row, use_color_buffer);
|
||||
}
|
||||
KeyEvent::PageDown | KeyEvent::Ctrl('f') | KeyEvent::Char(' ') => {
|
||||
if starting_row < (max_bottom_line - height) {
|
||||
starting_row += height;
|
||||
|
||||
if starting_row > (max_bottom_line - height) {
|
||||
starting_row = max_bottom_line - height;
|
||||
}
|
||||
}
|
||||
max_bottom_line =
|
||||
paint_textview(&draw_commands, starting_row, use_color_buffer);
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
let new_size = terminal.terminal_size();
|
||||
if size != new_size {
|
||||
size = new_size;
|
||||
let _ = terminal.clear(crossterm::ClearType::All);
|
||||
max_bottom_line =
|
||||
paint_textview(&draw_commands, starting_row, use_color_buffer);
|
||||
}
|
||||
}
|
||||
let _ = cursor.show();
|
||||
|
||||
let _ = RawScreen::disable_raw_mode();
|
||||
}
|
||||
}
|
||||
|
||||
outln!("");
|
||||
}
|
||||
|
||||
fn scroll_view(s: &str) {
|
||||
let mut v = vec![];
|
||||
for line in s.lines() {
|
||||
v.push(DrawCommand::DrawString(Style::default(), line.to_string()));
|
||||
v.push(DrawCommand::NextLine);
|
||||
}
|
||||
scroll_view_lines_if_needed(v, false);
|
||||
}
|
||||
|
||||
fn view_text_value(value: &Value) {
|
||||
let value_anchor = value.anchor();
|
||||
match &value.value {
|
||||
UntaggedValue::Primitive(Primitive::String(ref s)) => {
|
||||
if let Some(source) = value_anchor {
|
||||
let extension: Option<String> = match source {
|
||||
AnchorLocation::File(file) => {
|
||||
let path = Path::new(&file);
|
||||
path.extension().map(|x| x.to_string_lossy().to_string())
|
||||
}
|
||||
AnchorLocation::Url(url) => {
|
||||
let url = url::Url::parse(&url);
|
||||
if let Ok(url) = url {
|
||||
let url = url.clone();
|
||||
if let Some(mut segments) = url.path_segments() {
|
||||
if let Some(file) = segments.next_back() {
|
||||
let path = Path::new(file);
|
||||
path.extension().map(|x| x.to_string_lossy().to_string())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
//FIXME: this probably isn't correct
|
||||
AnchorLocation::Source(_source) => None,
|
||||
};
|
||||
|
||||
match extension {
|
||||
Some(extension) => {
|
||||
// Load these once at the start of your program
|
||||
let ps: SyntaxSet = syntect::dumps::from_binary(include_bytes!(
|
||||
"../../assets/syntaxes.bin"
|
||||
));
|
||||
|
||||
if let Some(syntax) = ps.find_syntax_by_extension(&extension) {
|
||||
let ts: ThemeSet = syntect::dumps::from_binary(include_bytes!(
|
||||
"../../assets/themes.bin"
|
||||
));
|
||||
let mut h = HighlightLines::new(syntax, &ts.themes["OneHalfDark"]);
|
||||
|
||||
let mut v = vec![];
|
||||
for line in s.lines() {
|
||||
let ranges: Vec<(Style, &str)> = h.highlight(line, &ps);
|
||||
|
||||
for range in ranges {
|
||||
v.push(DrawCommand::DrawString(range.0, range.1.to_string()));
|
||||
}
|
||||
|
||||
v.push(DrawCommand::NextLine);
|
||||
}
|
||||
scroll_view_lines_if_needed(v, true);
|
||||
} else {
|
||||
scroll_view(s);
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
scroll_view(s);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
scroll_view(s);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
serve_plugin(&mut TextView::new());
|
||||
}
|
Reference in New Issue
Block a user