summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDenis Isidoro <denisidoro@users.noreply.github.com>2022-07-28 20:11:42 -0300
committerGitHub <noreply@github.com>2022-07-28 20:11:42 -0300
commitebb02e28ec338d55c89c5b2d321d038f982538c5 (patch)
treeda6f4e367a2e0f8c6866c21d0ea609927de817c0 /src
parentf5759f26aac3299ff391be173bdc6c9286fe93d1 (diff)
Refactor code base (#760)
Diffstat (limited to 'src')
-rw-r--r--src/clients/cheatsh.rs (renamed from src/cheatsh.rs)64
-rw-r--r--src/clients/mod.rs2
-rw-r--r--src/clients/tldr.rs (renamed from src/tldr.rs)37
-rw-r--r--src/commands/core/actor.rs (renamed from src/actor.rs)32
-rw-r--r--src/commands/core/extractor.rs (renamed from src/extractor.rs)8
-rw-r--r--src/commands/core/mod.rs41
-rw-r--r--src/commands/func/map.rs (renamed from src/cheat_variable.rs)7
-rw-r--r--src/commands/func/mod.rs65
-rw-r--r--src/commands/func/widget.rs40
-rw-r--r--src/commands/info.rs48
-rw-r--r--src/commands/mod.rs39
-rw-r--r--src/commands/preview/mod.rs39
-rw-r--r--src/commands/preview/var.rs106
-rwxr-xr-xsrc/commands/preview/var_stdin.rs43
-rw-r--r--src/commands/repo/add.rs (renamed from src/handler/repo_add.rs)43
-rw-r--r--src/commands/repo/browse.rs (renamed from src/handler/repo_browse.rs)20
-rw-r--r--src/commands/repo/mod.rs41
-rw-r--r--src/commands/shell.rs43
-rw-r--r--src/commands/temp.rs64
-rw-r--r--src/common/clipboard.rs (renamed from src/clipboard.rs)4
-rw-r--r--src/common/component.rs.bkp21
-rw-r--r--src/common/deps.rs.bkp7
-rw-r--r--src/common/deser.rs.bkp50
-rw-r--r--src/common/fs.rs (renamed from src/fs.rs)34
-rw-r--r--src/common/git.rs (renamed from src/git.rs)4
-rw-r--r--src/common/hash.rs (renamed from src/hash.rs)0
-rw-r--r--src/common/mod.rs13
-rw-r--r--src/common/prelude.rs29
-rw-r--r--src/common/shell.rs45
-rw-r--r--src/common/system.rs.bkp57
-rw-r--r--src/common/terminal.rs65
-rw-r--r--src/common/tracing.rs.bkp36
-rw-r--r--src/common/url.rs (renamed from src/url.rs)3
-rw-r--r--src/config/cli.rs111
-rw-r--r--src/config/env.rs4
-rw-r--r--src/config/mod.rs29
-rw-r--r--src/config/yaml.rs13
-rw-r--r--src/env_var.rs2
-rw-r--r--src/filesystem.rs102
-rw-r--r--src/finder/mod.rs35
-rw-r--r--src/finder/post.rs6
-rw-r--r--src/finder/structures.rs2
-rw-r--r--src/handler/core.rs51
-rw-r--r--src/handler/func.rs25
-rw-r--r--src/handler/info.rs21
-rw-r--r--src/handler/mod.rs60
-rw-r--r--src/handler/preview.rs27
-rw-r--r--src/handler/preview_var.rs91
-rwxr-xr-xsrc/handler/preview_var_stdin.rs29
-rw-r--r--src/handler/shell.rs15
-rw-r--r--src/lib.rs25
-rw-r--r--src/parser.rs324
-rw-r--r--src/prelude.rs9
-rw-r--r--src/serializer.rs121
-rw-r--r--src/shell.rs86
-rw-r--r--src/structures/cheat.rs13
-rw-r--r--src/structures/fetcher.rs14
-rw-r--r--src/structures/item.rs18
-rw-r--r--src/terminal.rs66
-rw-r--r--src/ui.rs25
-rw-r--r--src/welcome.rs58
-rw-r--r--src/writer.rs52
62 files changed, 1466 insertions, 1118 deletions
diff --git a/src/cheatsh.rs b/src/clients/cheatsh.rs
index d5ac039..f039b0c 100644
--- a/src/cheatsh.rs
+++ b/src/clients/cheatsh.rs
@@ -1,10 +1,8 @@
-use crate::parser;
-use crate::structures::cheat::VariableMap;
+use crate::parser::Parser;
+use crate::prelude::*;
+
use crate::structures::fetcher;
-use anyhow::Context;
-use anyhow::Result;
-use std::collections::HashSet;
-use std::process::{self, Command, Stdio};
+use std::process::{self, Command};
fn map_line(line: &str) -> String {
line.trim().trim_end_matches(':').to_string()
@@ -22,35 +20,6 @@ fn lines(query: &str, markdown: &str) -> impl Iterator<Item = Result<String>> {
.into_iter()
}
-fn read_all(query: &str, cheat: &str, stdin: &mut std::process::ChildStdin) -> Result<Option<VariableMap>> {
- let mut variables = VariableMap::new();
- let mut visited_lines = HashSet::new();
-
- if cheat.starts_with("Unknown topic.") {
- eprintln!(
- "`{}` not found in cheatsh.
-
-Output:
-{}
-",
- query, cheat
- );
- process::exit(35)
- }
-
- parser::read_lines(
- lines(query, cheat),
- "cheat.sh",
- 0,
- &mut variables,
- &mut visited_lines,
- stdin,
- None,
- None,
- )?;
- Ok(Some(variables))
-}
-
pub fn fetch(query: &str) -> Result<String> {
let args = ["-qO-", &format!("cheat.sh/{}", query)];
@@ -109,12 +78,23 @@ impl Fetcher {
}
impl fetcher::Fetcher for Fetcher {
- fn fetch(
- &self,
- stdin: &mut std::process::ChildStdin,
- _files: &mut Vec<String>,
- ) -> Result<Option<VariableMap>> {
- let cheat = fetch(&self.query)?;
- read_all(&self.query, &cheat, stdin)
+ fn fetch(&self, parser: &mut Parser) -> Result<bool> {
+ let cheat = &fetch(&self.query)?;
+
+ if cheat.starts_with("Unknown topic.") {
+ eprintln!(
+ "`{}` not found in cheatsh.
+
+Output:
+{}
+",
+ &self.query, cheat
+ );
+ process::exit(35)
+ }
+
+ parser.read_lines(lines(&self.query, cheat), "cheat.sh", None)?;
+
+ Ok(true)
}
}
diff --git a/src/clients/mod.rs b/src/clients/mod.rs
new file mode 100644
index 0000000..1f0dbcd
--- /dev/null
+++ b/src/clients/mod.rs
@@ -0,0 +1,2 @@
+pub mod cheatsh;
+pub mod tldr;
diff --git a/src/tldr.rs b/src/clients/tldr.rs
index adbf5da..f164534 100644
--- a/src/tldr.rs
+++ b/src/clients/tldr.rs
@@ -1,10 +1,6 @@
-use crate::parser;
-use crate::structures::cheat::VariableMap;
+use crate::parser::Parser;
+use crate::prelude::*;
use crate::structures::fetcher;
-use anyhow::{Context, Result};
-use regex::Regex;
-use std::collections::HashSet;
-
use std::process::{self, Command, Stdio};
lazy_static! {
@@ -58,26 +54,6 @@ fn markdown_lines(query: &str, markdown: &str) -> impl Iterator<Item = Result<St
.into_iter()
}
-fn read_all(
- query: &str,
- markdown: &str,
- stdin: &mut std::process::ChildStdin,
-) -> Result<Option<VariableMap>> {
- let mut variables = VariableMap::new();
- let mut visited_lines = HashSet::new();
- parser::read_lines(
- markdown_lines(query, markdown),
- "markdown",
- 0,
- &mut variables,
- &mut visited_lines,
- stdin,
- None,
- None,
- )?;
- Ok(Some(variables))
-}
-
pub fn fetch(query: &str) -> Result<String> {
let args = [query, "--markdown"];
@@ -148,12 +124,9 @@ impl Fetcher {
}
impl fetcher::Fetcher for Fetcher {
- fn fetch(
- &self,
- stdin: &mut std::process::ChildStdin,
- _files: &mut Vec<String>,
- ) -> Result<Option<VariableMap>> {
+ fn fetch(&self, parser: &mut Parser) -> Result<bool> {
let markdown = fetch(&self.query)?;
- read_all(&self.query, &markdown, stdin)
+ parser.read_lines(markdown_lines(&self.query, &markdown), "markdown", None)?;
+ Ok(true)
}
}
diff --git a/src/actor.rs b/src/commands/core/actor.rs
index 306acce..e423afe 100644
--- a/src/actor.rs
+++ b/src/commands/core/actor.rs
@@ -1,20 +1,15 @@
-use crate::clipboard;
+use super::extractor;
+use crate::common::clipboard;
+use crate::common::fs;
+use crate::common::shell;
+use crate::common::shell::ShellSpawnError;
use crate::config::Action;
-use crate::config::CONFIG;
use crate::env_var;
-use crate::extractor;
use crate::finder::structures::{Opts as FinderOpts, SuggestionType};
-use crate::finder::Finder;
-use crate::fs;
-use crate::shell;
-use crate::shell::ShellSpawnError;
+use crate::prelude::*;
+use crate::serializer;
use crate::structures::cheat::{Suggestion, VariableMap};
-use crate::writer;
-use anyhow::Context;
-use anyhow::Result;
use shell::EOF;
-use std::io::Write;
-use std::path::Path;
use std::process::Stdio;
fn prompt_finder(
@@ -128,13 +123,13 @@ fn prompt_finder(
opts.suggestion_type = SuggestionType::Disabled;
};
- let (output, _, _) = CONFIG
+ let (output, _) = CONFIG
.finder()
- .call(opts, |stdin, _| {
+ .call(opts, |stdin| {
stdin
.write_all(suggestions.as_bytes())
.context("Could not write to finder's stdin")?;
- Ok(None)
+ Ok(())
})
.context("finder was unable to prompt with suggestions")?;
@@ -150,7 +145,10 @@ fn unique_result_count(results: &[&str]) -> usize {
fn replace_variables_from_snippet(snippet: &str, tags: &str, variables: VariableMap) -> Result<String> {
let mut interpolated_snippet = String::from(snippet);
- let variables_found: Vec<&str> = writer::VAR_REGEX.find_iter(snippet).map(|m| m.as_str()).collect();
+ let variables_found: Vec<&str> = serializer::VAR_REGEX
+ .find_iter(snippet)
+ .map(|m| m.as_str())
+ .collect();
let variable_count = unique_result_count(&variables_found);
for bracketed_variable_name in variables_found {
@@ -213,7 +211,7 @@ pub fn act(
)
.context("Failed to replace variables from snippet")?;
s = with_absolute_path(s);
- s = writer::with_new_lines(s);
+ s = serializer::with_new_lines(s);
s
};
diff --git a/src/extractor.rs b/src/commands/core/extractor.rs
index 7b6ed3b..56758e8 100644
--- a/src/extractor.rs
+++ b/src/commands/core/extractor.rs
@@ -1,7 +1,5 @@
-use crate::writer;
-
-use anyhow::Context;
-use anyhow::Result;
+use crate::prelude::*;
+use crate::serializer;
pub type Output<'a> = (&'a str, &'a str, &'a str, &'a str, Option<usize>);
@@ -18,7 +16,7 @@ pub fn extract_from_selections(raw_snippet: &str, is_single: bool) -> Result<Out
let mut parts = lines
.next()
.context("No more parts in `selections`")?
- .split(writer::DELIMITER)
+ .split(serializer::DELIMITER)
.skip(3);
let tags = parts.next().unwrap_or("");
diff --git a/src/commands/core/mod.rs b/src/commands/core/mod.rs
new file mode 100644
index 0000000..f212880
--- /dev/null
+++ b/src/commands/core/mod.rs
@@ -0,0 +1,41 @@
+mod actor;
+mod extractor;
+
+use crate::finder::structures::Opts as FinderOpts;
+use crate::parser::Parser;
+use crate::prelude::*;
+use crate::welcome;
+
+pub fn main() -> Result<()> {
+ let config = &CONFIG;
+ let opts = FinderOpts::snippet_default();
+
+ let (raw_selection, (variables, files)) = config
+ .finder()
+ .call(opts, |writer| {
+ let fetcher = config.fetcher();
+
+ let mut parser = Parser::new(writer, true);
+
+ let found_something = fetcher
+ .fetch(&mut parser)
+ .context("Failed to parse variables intended for finder")?;
+
+ if !found_something {
+ welcome::populate_cheatsheet(&mut parser)?;
+ }
+
+ Ok((Some(parser.variables), fetcher.files()))
+ })
+ .context("Failed getting selection and variables from finder")?;
+
+ let extractions = extractor::extract_from_selections(&raw_selection, config.best_match());
+
+ if extractions.is_err() {
+ return main();
+ }
+
+ actor::act(extractions, files, variables)?;
+
+ Ok(())
+}
diff --git a/src/cheat_variable.rs b/src/commands/func/map.rs
index 3f6399d..89e22c5 100644
--- a/src/cheat_variable.rs
+++ b/src/commands/func/map.rs
@@ -1,8 +1,7 @@
-use crate::shell::{self, ShellSpawnError};
+use crate::common::shell::{self, ShellSpawnError};
+use crate::prelude::*;
-use anyhow::Result;
-
-pub fn map_expand() -> Result<()> {
+pub fn expand() -> Result<()> {
let cmd = r#"sed -e 's/^.*$/"&"/' | tr '\n' ' '"#;
shell::out()
.arg(cmd)
diff --git a/src/commands/func/mod.rs b/src/commands/func/mod.rs
new file mode 100644
index 0000000..383b636
--- /dev/null
+++ b/src/commands/func/mod.rs
@@ -0,0 +1,65 @@
+mod map;
+mod widget;
+
+use super::core;
+use super::temp;
+use crate::common::url;
+use crate::prelude::*;
+use clap::Args;
+use clap::Parser;
+
+const FUNC_POSSIBLE_VALUES: &[&str] = &[
+ "url::open",
+ "welcome",
+ "widget::last_command",
+ "map::expand",
+ "temp",
+];
+
+impl FromStr for Func {
+ type Err = &'static str;
+
+ fn from_str(s: &str) -> Result<Self, Self::Err> {
+ match s {
+ "url::open" => Ok(Func::UrlOpen),
+ "welcome" => Ok(Func::Welcome),
+ "widget::last_command" => Ok(Func::WidgetLastCommand),
+ "map::expand" => Ok(Func::MapExpand),
+ "temp" => Ok(Func::Temp),
+ _ => Err("no match"),
+ }
+ }
+}
+
+#[derive(Debug, Clone, Parser)]
+pub enum Func {
+ UrlOpen,
+ Welcome,
+ WidgetLastCommand,
+ MapExpand,
+ Temp,
+}
+
+#[derive(Debug, Clone, Args)]
+pub struct Input {
+ /// Function name (example: "url::open")
+ #[clap(possible_values = FUNC_POSSIBLE_VALUES, ignore_case = true)]
+ pub func: Func,
+ /// List of arguments (example: "https://google.com")
+ pub args: Vec<String>,
+}
+
+impl Runnable for Input {
+ fn run(&self) -> Result<()> {
+ let func = &self.func;
+ let args = self.args.clone(); // TODO
+
+ match func {
+ Func::UrlOpen => url::open(args),
+ Func::Welcome => core::main(),
+ Func::WidgetLastCommand => widget::last_command(),
+ Func::MapExpand => map::expand(),
+ Func::Temp => temp::main(),
+ }
+ }
+}
diff --git a/src/commands/func/widget.rs b/src/commands/func/widget.rs
new file mode 100644
index 0000000..ff74d74
--- /dev/null
+++ b/src/commands/func/widget.rs
@@ -0,0 +1,40 @@
+use crate::prelude::*;
+use std::io::{self, Read};
+
+pub fn last_command() -> Result<()> {
+ let mut text = String::new();
+ io::stdin().read_to_string(&mut text)?;
+
+ let replacements = vec![("||", "ග"), ("|", "ඛ"), ("&&", "ඝ")];
+
+ let parts = shellwords::split(&text).unwrap_or_else(|_| text.split('|').map(|s| s.to_string()).collect());
+
+ for p in parts {
+ for (pattern, escaped) in replacements.clone() {
+ if p.contains(pattern) && p != pattern && p != format!("{}{}", pattern, pattern) {
+ let replacement = p.replace(pattern, escaped);
+ text = text.replace(&p, &replacement);
+ }
+ }
+ }
+
+ let mut extracted = text.clone();
+
+ for (pattern, _) in replacements.clone() {
+ let mut new_parts = text.rsplit(pattern);
+ if let Some(extracted_attempt) = new_parts.next() {
+ if extracted_attempt.len() <= extracted.len() {
+ extracted = extracted_attempt.to_string();
+ }
+ }
+ }
+
+ for (pattern, escaped) in replacements.clone() {
+ text = text.replace(&escaped, pattern);
+ extracted = extracted.replace(&escaped, pattern);
+ }
+
+ println!("{}", extracted.trim_start());
+
+ Ok(())
+}
diff --git a/src/commands/info.rs b/src/commands/info.rs
new file mode 100644
index 0000000..6b69f80
--- /dev/null
+++ b/src/commands/info.rs
@@ -0,0 +1,48 @@
+use clap::Args;
+
+use crate::filesystem;
+use crate::prelude::*;
+
+const INFO_POSSIBLE_VALUES: &[&str] = &["cheats-example", "cheats-path", "config-path", "config-example"];
+
+impl FromStr for Info {
+ type Err = &'static str;
+
+ fn from_str(s: &str) -> Result<Self, Self::Err> {
+ match s {
+ "cheats-example" => Ok(Info::CheatsExample),
+ "cheats-path" => Ok(Info::CheatsPath),
+ "config-example" => Ok(Info::ConfigExample),
+ "config-path" => Ok(Info::ConfigPath),
+ _ => Err("no match"),
+ }
+ }
+}
+
+#[derive(Debug, Clone, Args)]
+pub struct Input {
+ #[clap(possible_values = INFO_POSSIBLE_VALUES, ignore_case = true)]
+ pub info: Info,
+}
+
+#[derive(Debug, Clone)]
+pub enum Info {
+ CheatsExample,
+ CheatsPath,
+ ConfigPath,
+ ConfigExample,
+}
+
+impl Runnable for Input {
+ fn run(&self) -> Result<()> {
+ let info = &self.info;
+
+ match info {
+ Info::CheatsExample => println!("{}", include_str!("../../docs/cheat_example.cheat")),
+ Info::CheatsPath => println!("{}", &filesystem::default_cheat_pathbuf()?.to_string()),
+ Info::ConfigPath => println!("{}", &filesystem::default_config_pathbuf()?.to_string()),
+ Info::ConfigExample => println!("{}", include_str!("../../docs/config_file_example.yaml")),
+ }
+ Ok(())
+ }
+}
diff --git a/src/commands/mod.rs b/src/commands/mod.rs
new file mode 100644
index 0000000..783cbad
--- /dev/null
+++ b/src/commands/mod.rs
@@ -0,0 +1,39 @@
+pub mod core;
+pub mod func;
+pub mod info;
+pub mod preview;
+pub mod repo;
+pub mod shell;
+pub mod temp;
+
+use crate::commands;
+use crate::prelude::*;
+
+pub fn handle() -> Result<()> {
+ use crate::config::Command::*;
+
+ match CONFIG.cmd() {
+ None => commands::core::main(),
+
+ Some(c) => match c {
+ Preview(input) => input.run(),
+
+ PreviewVarStdin(input) => input.run(),
+
+ PreviewVar(input) => input.run(),
+
+ Widget(input) => input.run().context("Failed to print shell widget code"),
+
+ Fn(input) => input
+ .run()
+ .with_context(|| format!("Failed to execute function `{:#?}`", input.func)),
+
+ Info(input) => input
+ .run()
+ .with_context(|| format!("Failed to fetch info `{:#?}`", input.info)),
+
+ #[cfg(not(feature = "disable-repo-management"))]
+ Repo(input) => input.run(),
+ },
+ }
+}
diff --git a/src/commands/preview/mod.rs b/src/commands/preview/mod.rs
new file mode 100644
index 0000000..11fa1fc
--- /dev/null
+++ b/src/commands/preview/mod.rs
@@ -0,0 +1,39 @@
+use crate::prelude::*;
+use crate::serializer;
+use clap::Args;
+use crossterm::style::{style, Stylize};
+use std::process;
+
+pub mod var;
+pub mod var_stdin;
+
+#[derive(Debug, Clone, Args)]
+pub struct Input {
+ /// Selection line
+ pub line: String,
+}
+
+fn extract_elements(argstr: &str) -> Result<(&str, &str, &str)> {
+ let mut parts = argstr.split(serializer::DELIMITER).skip(3);
+ let tags = parts.next().context("No `tags` element provided.")?;
+ let comment = parts.next().context("No `comment` element provided.")?;
+ let snippet = parts.next().context("No `snippet` element provided.")?;
+ Ok((tags, comment, snippet))
+}
+
+impl Runnable for Input {
+ fn run(&self) -> Result<()> {
+ let line = &self.line;
+
+ let (tags, comment, snippet) = extract_elements(line)?;
+
+ println!(
+ "{comment} {tags} \n{snippet}",
+ comment = style(comment).with(CONFIG.comment_color()),
+ tags = style(format!("[{}]", tags)).with(CONFIG.tag_color()),
+ snippet = style(serializer::fix_newlines(snippet)).with(CONFIG.snippet_color()),
+ );
+
+ process::exit(0)
+ }
+}
diff --git a/src/commands/preview/var.rs b/src/commands/preview/var.rs
new file mode 100644
index 0000000..e99dcce
--- /dev/null
+++ b/src/commands/preview/var.rs
@@ -0,0 +1,106 @@
+use crate::env_var;
+use crate::finder;
+use crate::prelude::*;
+use crate::serializer;
+use clap::Args;
+use crossterm::style::style;
+use crossterm::style::Stylize;
+use std::iter;
+use std::process;
+
+#[derive(Debug, Clone, Args)]
+pub struct Input {
+ /// Selection line
+ pub selection: String,
+ /// Query match
+ pub query: String,
+ /// Typed text
+ pub variable: String,
+}
+
+impl Runnable for Input {
+ fn run(&self) -> Result<()> {
+ let selection = &self.selection;
+ let query = &self.query;
+ let variable = &self.variable;
+
+ let snippet = env_var::must_get(env_var::PREVIEW_INITIAL_SNIPPET);
+ let tags = env_var::must_get(env_var::PREVIEW_TAGS);
+ let comment = env_var::must_get(env_var::PREVIEW_COMMENT);
+ let column = env_var::parse(env_var::PREVIEW_COLUMN);
+ let delimiter = env_var::get(env_var::PREVIEW_DELIMITER).ok();
+ let map = env_var::get(env_var::PREVIEW_MAP).ok();
+
+ let active_color = CONFIG.tag_color();
+ let inactive_color = CONFIG.comment_color();
+
+ let mut colored_snippet = String::from(&snippet);
+ let mut visited_vars: HashSet<&str> = HashSet::new();
+
+ let mut variables = String::from("");
+
+ println!(
+ "{comment} {tags}",
+ comment = style(comment).with(CONFIG.comment_color()),
+ tags = style(format!("[{}]", tags)).with(CONFIG.tag_color()),
+ );
+
+ let bracketed_current_variable = format!("<{}>", variable);
+
+ let bracketed_variables: Vec<&str> = {
+ if snippet.contains(&bracketed_current_variable) {
+ serializer::VAR_REGEX
+ .find_iter(&snippet)
+ .map(|m| m.as_str())
+ .collect()
+ } else {
+ iter::once(&bracketed_current_variable)
+ .map(|s| s.as_str())
+ .collect()
+ }
+ };
+
+ for bracketed_variable_name in bracketed_variables {
+ let variable_name = &bracketed_variable_name[1..bracketed_variable_name.len() - 1];
+
+ if visited_vars.contains(variable_name) {
+ continue;
+ } else {
+ visited_vars.insert(variable_name);
+ }
+
+ let is_current = variable_name == variable;
+ let variable_color = if is_current { active_color } else { inactive_color };
+ let env_variable_name = env_var::escape(variable_name);
+
+ let value = if is_current {
+ let v = selection.trim_matches('\'');