mirror of
https://github.com/denisidoro/navi.git
synced 2026-01-23 02:14:19 +00:00
parent
818ebccdf0
commit
434fc4ac76
20 changed files with 261 additions and 237 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
|
@ -174,7 +174,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
|
||||
[[package]]
|
||||
name = "navi"
|
||||
version = "2.6.0"
|
||||
version = "2.6.1"
|
||||
dependencies = [
|
||||
"anyhow 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "navi"
|
||||
version = "2.6.0"
|
||||
version = "2.6.1"
|
||||
authors = ["Denis Isidoro <denis_isidoro@live.com>"]
|
||||
edition = "2018"
|
||||
description = "An interactive cheatsheet tool for the command-line"
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
source "${HOME}/.bashrc"
|
||||
|
||||
if [ -n "${snippet:-}" ]; then
|
||||
navi alfred suggestions
|
||||
if [ -n "${snippet:-}" ]; then
|
||||
navi alfred suggestions
|
||||
else
|
||||
navi alfred start
|
||||
navi alfred start
|
||||
fi
|
||||
|
|
|
|||
|
|
@ -1,15 +1,9 @@
|
|||
#!/bin/bash
|
||||
|
||||
_interpolate() {
|
||||
local -r snippet="$1"
|
||||
local -r varname="$2"
|
||||
local -r value="${!varname}"
|
||||
source "${HOME}/.bashrc"
|
||||
|
||||
echo "$snippet" | sed "s/<${varname}>/${value}/g"
|
||||
}
|
||||
|
||||
if [ -n "${varname:-}" ]; then
|
||||
echo -n "$(_interpolate "$snippet" "$varname" || echo "")"
|
||||
if [ -n "${varname:-}" ]; then
|
||||
echo -n "$(navi alfred transform)"
|
||||
else
|
||||
echo -n "$snippet"
|
||||
echo -n "$snippet"
|
||||
fi
|
||||
|
|
|
|||
|
|
@ -165,6 +165,19 @@
|
|||
<key>version</key>
|
||||
<integer>1</integer>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>config</key>
|
||||
<dict>
|
||||
<key>triggerid</key>
|
||||
<string>play</string>
|
||||
</dict>
|
||||
<key>type</key>
|
||||
<string>alfred.workflow.trigger.external</string>
|
||||
<key>uid</key>
|
||||
<string>55C46852-4807-4374-95AB-CC055F4ECB7C</string>
|
||||
<key>version</key>
|
||||
<integer>1</integer>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>config</key>
|
||||
<dict>
|
||||
|
|
@ -311,19 +324,6 @@ fi
|
|||
<key>version</key>
|
||||
<integer>3</integer>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>config</key>
|
||||
<dict>
|
||||
<key>triggerid</key>
|
||||
<string>play</string>
|
||||
</dict>
|
||||
<key>type</key>
|
||||
<string>alfred.workflow.trigger.external</string>
|
||||
<key>uid</key>
|
||||
<string>55C46852-4807-4374-95AB-CC055F4ECB7C</string>
|
||||
<key>version</key>
|
||||
<integer>1</integer>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>config</key>
|
||||
<dict>
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@ cargo fmt || true
|
|||
|
||||
header "dot code beautify..."
|
||||
find scripts -type f | xargs -I% dot code beautify % || true
|
||||
dot code beautify "${NAVI_HOME}/alfred/alfred.bash" || true
|
||||
dot code beautify "${NAVI_HOME}/alfred/alfred2.bash" || true
|
||||
dot code beautify "${NAVI_HOME}/tests/core.bash" || true
|
||||
dot code beautify "${NAVI_HOME}/tests/run" || true
|
||||
|
||||
|
|
|
|||
117
src/display.rs
117
src/display.rs
|
|
@ -1,117 +0,0 @@
|
|||
use crate::structures::item::Item;
|
||||
use crate::terminal;
|
||||
use regex::Regex;
|
||||
use std::cmp::max;
|
||||
use termion::color;
|
||||
|
||||
const COMMENT_COLOR: color::LightCyan = color::LightCyan;
|
||||
const TAG_COLOR: color::Blue = color::Blue;
|
||||
const SNIPPET_COLOR: color::White = color::White;
|
||||
|
||||
const NEWLINE_ESCAPE_CHAR: char = '\x15';
|
||||
pub const LINE_SEPARATOR: &str = " \x15 ";
|
||||
pub const DELIMITER: &str = r" ⠀";
|
||||
|
||||
lazy_static! {
|
||||
pub static ref NEWLINE_REGEX: Regex = Regex::new(r"\\\s+").expect("Invalid regex");
|
||||
}
|
||||
|
||||
pub fn get_widths() -> (usize, usize) {
|
||||
let width = terminal::width();
|
||||
let tag_width = max(4, width * 20 / 100);
|
||||
let comment_width = max(4, width * 40 / 100);
|
||||
(usize::from(tag_width), usize::from(comment_width))
|
||||
}
|
||||
|
||||
pub fn variable_prompt(varname: &str) -> String {
|
||||
format!("{}: ", varname)
|
||||
}
|
||||
|
||||
fn fix_newlines(txt: &str) -> String {
|
||||
if txt.contains(NEWLINE_ESCAPE_CHAR) {
|
||||
(*NEWLINE_REGEX)
|
||||
.replace_all(txt.replace(LINE_SEPARATOR, " ").as_str(), "")
|
||||
.to_string()
|
||||
} else {
|
||||
txt.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn preview(comment: &str, tags: &str, snippet: &str) {
|
||||
println!(
|
||||
"{comment_color}{comment} {tag_color}{tags} \n{snippet_color}{snippet}",
|
||||
comment = format!("# {}", comment),
|
||||
tags = format!("[{}]", tags),
|
||||
snippet = fix_newlines(snippet),
|
||||
comment_color = color::Fg(COMMENT_COLOR),
|
||||
tag_color = color::Fg(TAG_COLOR),
|
||||
snippet_color = color::Fg(SNIPPET_COLOR),
|
||||
);
|
||||
}
|
||||
|
||||
fn limit_str(text: &str, length: usize) -> String {
|
||||
if text.len() > length {
|
||||
format!("{}…", text.chars().take(length - 1).collect::<String>())
|
||||
} else {
|
||||
format!("{:width$}", text, width = length)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Writer {
|
||||
fn write(&mut self, item: Item) -> String;
|
||||
}
|
||||
|
||||
pub struct FinderWriter {
|
||||
pub tag_width: usize,
|
||||
pub comment_width: usize,
|
||||
}
|
||||
|
||||
pub struct AlfredWriter {
|
||||
pub is_first: bool,
|
||||
}
|
||||
|
||||
impl Writer for FinderWriter {
|
||||
fn write(&mut self, item: Item) -> String {
|
||||
format!(
|
||||
"{tag_color}{tags_short}{delimiter}{comment_color}{comment_short}{delimiter}{snippet_color}{snippet_short}{delimiter}{tags}{delimiter}{comment}{delimiter}{snippet}{delimiter}\n",
|
||||
tags_short = limit_str(item.tags, self.tag_width),
|
||||
comment_short = limit_str(item.comment, self.comment_width),
|
||||
snippet_short = fix_newlines(item.snippet),
|
||||
comment_color = color::Fg(COMMENT_COLOR),
|
||||
tag_color = color::Fg(TAG_COLOR),
|
||||
snippet_color = color::Fg(SNIPPET_COLOR),
|
||||
tags = item.tags,
|
||||
comment = item.comment,
|
||||
delimiter = DELIMITER,
|
||||
snippet = &item.snippet)
|
||||
}
|
||||
}
|
||||
|
||||
fn escape_for_json(txt: &str) -> String {
|
||||
txt.replace('\\', "\\\\")
|
||||
.replace('"', "\\\"")
|
||||
.replace(NEWLINE_ESCAPE_CHAR, " ")
|
||||
}
|
||||
|
||||
impl Writer for AlfredWriter {
|
||||
fn write(&mut self, item: Item) -> String {
|
||||
let prefix = if self.is_first {
|
||||
self.is_first = false;
|
||||
""
|
||||
} else {
|
||||
","
|
||||
};
|
||||
|
||||
let tags = escape_for_json(item.tags);
|
||||
let comment = escape_for_json(item.comment);
|
||||
let snippet = escape_for_json(item.snippet);
|
||||
|
||||
format!(
|
||||
r#"{prefix}{{"type":"file","title":"{comment}","match":"{comment} {tags} {snippet}","subtitle":"{tags} :: {snippet}","variables":{{"tags":"{tags}","comment":"{comment}","snippet":"{snippet}"}},"icon":{{"path":"navi.png"}}}}"#,
|
||||
prefix = prefix,
|
||||
tags = tags,
|
||||
comment = comment,
|
||||
snippet = snippet
|
||||
)
|
||||
}
|
||||
}
|
||||
76
src/display/alfred.rs
Normal file
76
src/display/alfred.rs
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
use crate::display::{self, Writer};
|
||||
use crate::structures::item::Item;
|
||||
|
||||
pub struct AlfredWriter {
|
||||
is_first: bool,
|
||||
}
|
||||
|
||||
pub fn new_writer() -> AlfredWriter {
|
||||
AlfredWriter { is_first: true }
|
||||
}
|
||||
|
||||
fn escape_for_json(txt: &str) -> String {
|
||||
txt.replace('\\', "\\\\")
|
||||
.replace('"', "\\\"")
|
||||
.replace(display::NEWLINE_ESCAPE_CHAR, " ")
|
||||
}
|
||||
|
||||
pub fn print_items_start(varname: Option<&str>) {
|
||||
print!("{{");
|
||||
|
||||
if let Some(v) = varname {
|
||||
print!(r#""variables": {{"varname": "{varname}"}},"#, varname = v);
|
||||
}
|
||||
|
||||
println!(r#""items": ["#);
|
||||
}
|
||||
|
||||
pub fn print_items_end() {
|
||||
println!(r#"]}}"#);
|
||||
}
|
||||
|
||||
impl Writer for AlfredWriter {
|
||||
fn write(&mut self, item: Item) -> String {
|
||||
let prefix = if self.is_first {
|
||||
self.is_first = false;
|
||||
""
|
||||
} else {
|
||||
","
|
||||
};
|
||||
|
||||
let tags = escape_for_json(item.tags);
|
||||
let comment = escape_for_json(item.comment);
|
||||
let snippet = escape_for_json(item.snippet);
|
||||
|
||||
format!(
|
||||
r#"{prefix}{{"type":"file","title":"{comment}","match":"{comment} {tags} {snippet}","subtitle":"{tags} :: {snippet}","variables":{{"tags":"{tags}","comment":"{comment}","snippet":"{snippet}"}},"icon":{{"path":"navi.png"}}}}"#,
|
||||
prefix = prefix,
|
||||
tags = tags,
|
||||
comment = comment,
|
||||
snippet = snippet
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl AlfredWriter {
|
||||
pub fn write_suggestion(&mut self, snippet: &str, varname: &str, line: &str) {
|
||||
if line.len() < 3 {
|
||||
return;
|
||||
}
|
||||
|
||||
let prefix = if self.is_first {
|
||||
self.is_first = false;
|
||||
""
|
||||
} else {
|
||||
","
|
||||
};
|
||||
|
||||
println!(
|
||||
r#"{prefix}{{"title":"{value}","subtitle":"{snippet}","variables":{{"{varname}":"{value}"}},"icon":{{"path":"navi.png"}}}}"#,
|
||||
prefix = prefix,
|
||||
snippet = snippet,
|
||||
varname = varname,
|
||||
value = line
|
||||
);
|
||||
}
|
||||
}
|
||||
28
src/display/mod.rs
Normal file
28
src/display/mod.rs
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
use crate::structures::item::Item;
|
||||
use regex::Regex;
|
||||
|
||||
pub mod alfred;
|
||||
pub mod terminal;
|
||||
|
||||
const NEWLINE_ESCAPE_CHAR: char = '\x15';
|
||||
pub const LINE_SEPARATOR: &str = " \x15 ";
|
||||
pub const DELIMITER: &str = r" ⠀";
|
||||
|
||||
lazy_static! {
|
||||
pub static ref NEWLINE_REGEX: Regex = Regex::new(r"\\\s+").expect("Invalid regex");
|
||||
pub static ref VAR_REGEX: Regex = Regex::new(r"<(\w[\w\d\-_]*)>").expect("Invalid regex");
|
||||
}
|
||||
|
||||
pub fn fix_newlines(txt: &str) -> String {
|
||||
if txt.contains(NEWLINE_ESCAPE_CHAR) {
|
||||
(*NEWLINE_REGEX)
|
||||
.replace_all(txt.replace(LINE_SEPARATOR, " ").as_str(), "")
|
||||
.to_string()
|
||||
} else {
|
||||
txt.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Writer {
|
||||
fn write(&mut self, item: Item) -> String;
|
||||
}
|
||||
62
src/display/terminal.rs
Normal file
62
src/display/terminal.rs
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
use crate::display::{self, Writer};
|
||||
use crate::structures::item::Item;
|
||||
use crate::terminal_width;
|
||||
use termion::color;
|
||||
|
||||
const COMMENT_COLOR: color::LightCyan = color::LightCyan;
|
||||
const TAG_COLOR: color::Blue = color::Blue;
|
||||
const SNIPPET_COLOR: color::White = color::White;
|
||||
|
||||
pub fn variable_prompt(varname: &str) -> String {
|
||||
format!("{}: ", varname)
|
||||
}
|
||||
|
||||
pub fn preview(comment: &str, tags: &str, snippet: &str) {
|
||||
println!(
|
||||
"{comment_color}{comment} {tag_color}{tags} \n{snippet_color}{snippet}",
|
||||
comment = format!("# {}", comment),
|
||||
tags = format!("[{}]", tags),
|
||||
snippet = display::fix_newlines(snippet),
|
||||
comment_color = color::Fg(COMMENT_COLOR),
|
||||
tag_color = color::Fg(TAG_COLOR),
|
||||
snippet_color = color::Fg(SNIPPET_COLOR),
|
||||
);
|
||||
}
|
||||
|
||||
fn limit_str(text: &str, length: usize) -> String {
|
||||
if text.len() > length {
|
||||
format!("{}…", text.chars().take(length - 1).collect::<String>())
|
||||
} else {
|
||||
format!("{:width$}", text, width = length)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TerminalWriter {
|
||||
tag_width: usize,
|
||||
comment_width: usize,
|
||||
}
|
||||
|
||||
pub fn new_writer() -> TerminalWriter {
|
||||
let (tag_width, comment_width) = terminal_width::get_widths();
|
||||
display::terminal::TerminalWriter {
|
||||
tag_width,
|
||||
comment_width,
|
||||
}
|
||||
}
|
||||
|
||||
impl Writer for TerminalWriter {
|
||||
fn write(&mut self, item: Item) -> String {
|
||||
format!(
|
||||
"{tag_color}{tags_short}{delimiter}{comment_color}{comment_short}{delimiter}{snippet_color}{snippet_short}{delimiter}{tags}{delimiter}{comment}{delimiter}{snippet}{delimiter}\n",
|
||||
tags_short = limit_str(item.tags, self.tag_width),
|
||||
comment_short = limit_str(item.comment, self.comment_width),
|
||||
snippet_short = display::fix_newlines(item.snippet),
|
||||
comment_color = color::Fg(COMMENT_COLOR),
|
||||
tag_color = color::Fg(TAG_COLOR),
|
||||
snippet_color = color::Fg(SNIPPET_COLOR),
|
||||
tags = item.tags,
|
||||
comment = item.comment,
|
||||
delimiter = display::DELIMITER,
|
||||
snippet = &item.snippet)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,31 +1,27 @@
|
|||
use crate::display;
|
||||
use crate::parser;
|
||||
use crate::structures::cheat::Suggestion;
|
||||
|
||||
use crate::structures::{error::command::BashSpawnError, option::Config};
|
||||
use anyhow::Context;
|
||||
use anyhow::Error;
|
||||
use regex::Regex;
|
||||
|
||||
use std::env;
|
||||
|
||||
use std::process::{Command, Stdio};
|
||||
|
||||
lazy_static! {
|
||||
pub static ref VAR_REGEX: Regex = Regex::new(r"<(\w[\w\d\-_]*)>").expect("Invalid regex");
|
||||
}
|
||||
|
||||
pub fn main(config: Config) -> Result<(), Error> {
|
||||
let mut child = Command::new("cat").stdin(Stdio::piped()).spawn().unwrap();
|
||||
let stdin = child.stdin.as_mut().unwrap();
|
||||
let mut child = Command::new("cat")
|
||||
.stdin(Stdio::piped())
|
||||
.spawn()
|
||||
.context("Unable to create child")?;
|
||||
let stdin = child.stdin.as_mut().context("Unable to get stdin")?;
|
||||
|
||||
println!(r#"{{"items": ["#);
|
||||
display::alfred::print_items_start(None);
|
||||
|
||||
parser::read_all(&config, stdin).context("Failed to parse variables intended for finder")?;
|
||||
|
||||
// make sure everything was printed to stdout before attempting to close the items vector
|
||||
let _ = child.wait_with_output().context("Failed to wait for fzf")?;
|
||||
|
||||
println!(r#"]}}"#);
|
||||
|
||||
display::alfred::print_items_end();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
@ -59,26 +55,22 @@ pub fn suggestions(config: Config) -> Result<(), Error> {
|
|||
.stdin(Stdio::piped())
|
||||
.stdout(Stdio::null())
|
||||
.spawn()
|
||||
.unwrap();
|
||||
let stdin = child.stdin.as_mut().unwrap();
|
||||
.context("Unable to create child")?;
|
||||
let stdin = child.stdin.as_mut().context("Unable to get stdin")?;
|
||||
|
||||
let variables = parser::read_all(&config, stdin)
|
||||
.context("Failed to parse variables intended for finder")?;
|
||||
|
||||
let tags = env::var("tags").unwrap();
|
||||
let _comment = env::var("comment").unwrap();
|
||||
let snippet = env::var("snippet").unwrap();
|
||||
let tags = env::var("tags").context(r#"The env var "tags" isn't set"#)?;
|
||||
let snippet = env::var("snippet").context(r#"The env var "snippet" isn't set"#)?;
|
||||
|
||||
let varname = VAR_REGEX.captures_iter(&snippet).next();
|
||||
let varname = display::VAR_REGEX.captures_iter(&snippet).next();
|
||||
|
||||
if let Some(varname) = varname {
|
||||
let varname = &varname[0];
|
||||
let varname = &varname[1..varname.len() - 1];
|
||||
|
||||
println!(
|
||||
r#"{{"variables": {{"varname": "{varname}"}}, "items": ["#,
|
||||
varname = varname
|
||||
);
|
||||
display::alfred::print_items_start(Some(varname));
|
||||
|
||||
let lines = variables
|
||||
.get(&tags, &varname)
|
||||
|
|
@ -87,36 +79,28 @@ pub fn suggestions(config: Config) -> Result<(), Error> {
|
|||
Ok(prompt_with_suggestions(&varname, &config, suggestion).unwrap())
|
||||
})?;
|
||||
|
||||
let mut is_first = true;
|
||||
let mut writer = display::alfred::new_writer();
|
||||
|
||||
for line in lines.split('\n') {
|
||||
if line.len() < 3 {
|
||||
continue;
|
||||
}
|
||||
|
||||
let prefix = if is_first {
|
||||
is_first = false;
|
||||
""
|
||||
} else {
|
||||
","
|
||||
};
|
||||
|
||||
println!(
|
||||
r#"{prefix}{{"title":"{value}","subtitle":"{snippet}","variables":{{"{varname}":"{value}"}},"icon":{{"path":"navi.png"}}}}"#,
|
||||
prefix = prefix,
|
||||
snippet = snippet,
|
||||
varname = varname,
|
||||
value = line
|
||||
);
|
||||
writer.write_suggestion(&snippet, &varname, &line);
|
||||
}
|
||||
} else {
|
||||
println!(r#"{{"items": ["#);
|
||||
display::alfred::print_items_start(None);
|
||||
}
|
||||
|
||||
println!(r#"]}}"#);
|
||||
display::alfred::print_items_end();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn transform(_config: Config) -> Result<(), Error> {
|
||||
pub fn transform() -> Result<(), Error> {
|
||||
let snippet = env::var("snippet").context(r#"The env var "snippet" isn't set"#)?;
|
||||
let varname = env::var("varname").context(r#"The env var "varname" isn't set"#)?;
|
||||
let value = env::var(&varname).context(format!(r#"The env var "{}" isn't set"#, &varname))?;
|
||||
|
||||
let bracketed_varname = format!("<{}>", varname);
|
||||
let interpolated_snippet = snippet.replace(&bracketed_varname, &value);
|
||||
println!("{}", interpolated_snippet);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,16 +10,11 @@ use crate::structures::option;
|
|||
use crate::structures::{error::command::BashSpawnError, option::Config};
|
||||
use anyhow::Context;
|
||||
use anyhow::Error;
|
||||
use regex::Regex;
|
||||
use std::env;
|
||||
use std::fs;
|
||||
use std::io::Write;
|
||||
use std::process::{Command, Stdio};
|
||||
|
||||
lazy_static! {
|
||||
pub static ref VAR_REGEX: Regex = Regex::new(r"<(\w[\w\d\-_]*)>").expect("Invalid regex");
|
||||
}
|
||||
|
||||
pub enum Variant {
|
||||
Core,
|
||||
Filter(String),
|
||||
|
|
@ -71,14 +66,6 @@ fn extract_from_selections(raw_snippet: &str, contains_key: bool) -> (&str, &str
|
|||
(key, tags, snippet)
|
||||
}
|
||||
|
||||
/* fn gen_opts_preview(snippet: &str, variable_name: &str) -> Option<String> {
|
||||
Some(format!(
|
||||
r#"query="{{}}"; [[ "${{#query:-}}" -lt 3 ]] && query="{{q}}"; query="${{query:1:${{#query}}-2}}"; query="$(echo "$query" | sed 's|/|\\/|g')"; echo "{}" | sed "s/<{}>/${{query}}/g" || echo 'Unable to generate command preview'"#,
|
||||
snippet.replace('"', "\\\""),
|
||||
variable_name
|
||||
))
|
||||
} */
|
||||
|
||||
fn prompt_with_suggestions(
|
||||
variable_name: &str,
|
||||
config: &Config,
|
||||
|
|
@ -106,7 +93,7 @@ fn prompt_with_suggestions(
|
|||
let opts = FinderOpts {
|
||||
autoselect: !config.no_autoselect,
|
||||
overrides: config.fzf_overrides_var.clone(),
|
||||
prompt: Some(display::variable_prompt(variable_name)),
|
||||
prompt: Some(display::terminal::variable_prompt(variable_name)),
|
||||
..opts
|
||||
};
|
||||
|
||||
|
|
@ -130,9 +117,8 @@ fn prompt_without_suggestions(
|
|||
) -> Result<String, Error> {
|
||||
let opts = FinderOpts {
|
||||
autoselect: false,
|
||||
prompt: Some(display::variable_prompt(variable_name)),
|
||||
prompt: Some(display::terminal::variable_prompt(variable_name)),
|
||||
suggestion_type: SuggestionType::Disabled,
|
||||
// preview: gen_opts_preview(&snippet, &variable_name),
|
||||
preview_window: Some("up:1".to_string()),
|
||||
..Default::default()
|
||||
};
|
||||
|
|
@ -153,7 +139,7 @@ fn replace_variables_from_snippet(
|
|||
) -> Result<String, Error> {
|
||||
let mut interpolated_snippet = String::from(snippet);
|
||||
|
||||
for captures in VAR_REGEX.captures_iter(snippet) {
|
||||
for captures in display::VAR_REGEX.captures_iter(snippet) {
|
||||
let bracketed_variable_name = &captures[0];
|
||||
let variable_name = &bracketed_variable_name[1..bracketed_variable_name.len() - 1];
|
||||
|
||||
|
|
@ -226,7 +212,7 @@ pub fn main(variant: Variant, config: Config, contains_key: bool) -> Result<(),
|
|||
println!("{}", interpolated_snippet);
|
||||
// save to file
|
||||
} else if let Some(s) = config.save {
|
||||
fs::write(s, interpolated_snippet).context("Unable to save config")?;
|
||||
fs::write(s, interpolated_snippet).context("Unable to save output")?;
|
||||
// call navi (this prevents "failed to read /dev/tty" from finder)
|
||||
} else if interpolated_snippet.starts_with("navi") {
|
||||
let new_config = option::config_from_iter(interpolated_snippet.split(' ').collect());
|
||||
|
|
|
|||
|
|
@ -12,6 +12,6 @@ fn extract_elements(argstr: &str) -> (&str, &str, &str) {
|
|||
|
||||
pub fn main(line: &str) -> Result<(), Error> {
|
||||
let (tags, comment, snippet) = extract_elements(line);
|
||||
display::preview(comment, tags, snippet);
|
||||
display::terminal::preview(comment, tags, snippet);
|
||||
process::exit(0)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ pub fn handle_config(config: Config) -> Result<(), Error> {
|
|||
Alfred { cmd } => match cmd {
|
||||
AlfredCommand::Start => flows::alfred::main(config),
|
||||
AlfredCommand::Suggestions => flows::alfred::suggestions(config),
|
||||
AlfredCommand::Transform => flows::alfred::transform(config),
|
||||
AlfredCommand::Transform => flows::alfred::transform(),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ mod git;
|
|||
mod handler;
|
||||
mod parser;
|
||||
mod structures;
|
||||
mod terminal;
|
||||
mod terminal_width;
|
||||
mod welcome;
|
||||
|
||||
pub use handler::handle_config;
|
||||
|
|
|
|||
|
|
@ -116,7 +116,7 @@ fn write_cmd(
|
|||
tags: &str,
|
||||
comment: &str,
|
||||
snippet: &str,
|
||||
writer: &mut Box<dyn Writer>,
|
||||
writer: &mut dyn Writer,
|
||||
stdin: &mut std::process::ChildStdin,
|
||||
) -> Result<(), Error> {
|
||||
if snippet.len() <= 1 {
|
||||
|
|
@ -137,7 +137,7 @@ fn read_file(
|
|||
path: &str,
|
||||
variables: &mut VariableMap,
|
||||
visited_lines: &mut HashSet<u64>,
|
||||
writer: &mut Box<dyn Writer>,
|
||||
writer: &mut dyn Writer,
|
||||
stdin: &mut std::process::ChildStdin,
|
||||
) -> Result<(), Error> {
|
||||
let mut tags = String::from("");
|
||||
|
|
@ -235,18 +235,14 @@ pub fn read_all(
|
|||
let mut found_something = false;
|
||||
let mut visited_lines = HashSet::new();
|
||||
let mut writer: Box<dyn Writer> = if let Some(Alfred { .. }) = &config.cmd {
|
||||
Box::new(display::AlfredWriter { is_first: true })
|
||||
Box::new(display::alfred::new_writer())
|
||||
} else {
|
||||
let (tag_width, comment_width) = display::get_widths();
|
||||
Box::new(display::FinderWriter {
|
||||
tag_width,
|
||||
comment_width,
|
||||
})
|
||||
Box::new(display::terminal::new_writer())
|
||||
};
|
||||
let paths = filesystem::cheat_paths(config);
|
||||
|
||||
if paths.is_err() {
|
||||
welcome::cheatsheet(&mut writer, stdin);
|
||||
welcome::cheatsheet(&mut *writer, stdin);
|
||||
return Ok(variables);
|
||||
}
|
||||
|
||||
|
|
@ -266,7 +262,7 @@ pub fn read_all(
|
|||
path_str,
|
||||
&mut variables,
|
||||
&mut visited_lines,
|
||||
&mut writer,
|
||||
&mut *writer,
|
||||
stdin,
|
||||
)
|
||||
.is_ok()
|
||||
|
|
@ -280,7 +276,7 @@ pub fn read_all(
|
|||
}
|
||||
|
||||
if !found_something {
|
||||
welcome::cheatsheet(&mut writer, stdin);
|
||||
welcome::cheatsheet(&mut *writer, stdin);
|
||||
}
|
||||
|
||||
Ok(variables)
|
||||
|
|
@ -314,18 +310,19 @@ mod tests {
|
|||
fn test_read_file() {
|
||||
let path = "tests/cheats/ssh.cheat";
|
||||
let mut variables = VariableMap::new();
|
||||
let mut child = Command::new("cat").stdin(Stdio::piped()).spawn().unwrap();
|
||||
let mut child = Command::new("cat")
|
||||
.stdin(Stdio::piped())
|
||||
.stdout(Stdio::null())
|
||||
.spawn()
|
||||
.unwrap();
|
||||
let child_stdin = child.stdin.as_mut().unwrap();
|
||||
let mut visited_lines: HashSet<u64> = HashSet::new();
|
||||
let mut writer: Box<dyn Writer> = Box::new(display::FinderWriter {
|
||||
comment_width: 20,
|
||||
tag_width: 30,
|
||||
});
|
||||
let mut writer: Box<dyn Writer> = Box::new(display::terminal::new_writer());
|
||||
read_file(
|
||||
path,
|
||||
&mut variables,
|
||||
&mut visited_lines,
|
||||
&mut writer,
|
||||
&mut *writer,
|
||||
child_stdin,
|
||||
)
|
||||
.unwrap();
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use thiserror::Error;
|
|||
|
||||
#[derive(Error, Debug)]
|
||||
#[error(
|
||||
"\rHey, listen! Navi encountered a problem.
|
||||
"\rHey, listen! navi encountered a problem.
|
||||
Do you think this is a bug? File an issue at https://github.com/denisidoro/navi."
|
||||
)]
|
||||
pub struct FileAnIssue {
|
||||
|
|
|
|||
|
|
@ -11,7 +11,10 @@ fn parse_finder(src: &str) -> Result<FinderChoice, Error> {
|
|||
}
|
||||
|
||||
#[derive(Debug, StructOpt)]
|
||||
#[structopt(after_help = r#"EXAMPLES:
|
||||
#[structopt(after_help = r#"MORE INFO:
|
||||
Please refer to https://github.com/denisidoro/navi
|
||||
|
||||
EXAMPLES:
|
||||
navi # default behavior
|
||||
navi --print # doesn't execute the snippet
|
||||
navi --path '/some/dir:/other/dir' # uses custom cheats
|
||||
|
|
@ -106,7 +109,8 @@ pub enum Command {
|
|||
/// bash, zsh or fish
|
||||
shell: String,
|
||||
},
|
||||
/// Alfred
|
||||
/// Helper command for Alfred integration
|
||||
#[structopt(setting = AppSettings::Hidden)]
|
||||
Alfred {
|
||||
#[structopt(subcommand)]
|
||||
cmd: AlfredCommand,
|
||||
|
|
@ -126,11 +130,11 @@ pub enum RepoCommand {
|
|||
|
||||
#[derive(Debug, StructOpt)]
|
||||
pub enum AlfredCommand {
|
||||
/// Start
|
||||
/// Outputs a JSON with commands
|
||||
Start,
|
||||
/// Suggestions
|
||||
/// Outputs a JSON with variable suggestions
|
||||
Suggestions,
|
||||
/// Transform
|
||||
/// Transforms the snippet env var with the selected value
|
||||
Transform,
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
use std::cmp::max;
|
||||
use terminal_size::{terminal_size, terminal_size_using_fd, Height, Width};
|
||||
|
||||
fn width_with_shell_out() -> u16 {
|
||||
|
|
@ -53,7 +54,7 @@ fn width_with_fd() -> u16 {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn width() -> u16 {
|
||||
fn width() -> u16 {
|
||||
let size = terminal_size();
|
||||
if let Some((Width(w), Height(_))) = size {
|
||||
w
|
||||
|
|
@ -61,3 +62,10 @@ pub fn width() -> u16 {
|
|||
width_with_fd()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_widths() -> (usize, usize) {
|
||||
let width = width();
|
||||
let tag_width = max(4, width * 20 / 100);
|
||||
let comment_width = max(4, width * 40 / 100);
|
||||
(usize::from(tag_width), usize::from(comment_width))
|
||||
}
|
||||
|
|
@ -6,7 +6,7 @@ fn add_msg(
|
|||
tags: &str,
|
||||
comment: &str,
|
||||
snippet: &str,
|
||||
writer: &mut Box<dyn Writer>,
|
||||
writer: &mut dyn Writer,
|
||||
stdin: &mut std::process::ChildStdin,
|
||||
) {
|
||||
let item = Item {
|
||||
|
|
@ -19,7 +19,7 @@ fn add_msg(
|
|||
.expect("Could not write to fzf's stdin");
|
||||
}
|
||||
|
||||
pub fn cheatsheet(writer: &mut Box<dyn Writer>, stdin: &mut std::process::ChildStdin) {
|
||||
pub fn cheatsheet(writer: &mut dyn Writer, stdin: &mut std::process::ChildStdin) {
|
||||
add_msg(
|
||||
"cheatsheets",
|
||||
"Download default cheatsheets",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue