From 000b50c211a783b1da5457ff621a480b18694009 Mon Sep 17 00:00:00 2001 From: iff Date: Sun, 8 Dec 2024 13:21:14 +0100 Subject: [PATCH] refactor: rearrange in workspaces --- Cargo.toml | 49 +--- pay-respects-parser/.gitignore | 2 + pay-respects-parser/.rustfmt.toml | 1 + pay-respects-parser/Cargo.toml | 23 ++ pay-respects-parser/src/lib.rs | 220 +++++++++++++++ pay-respects-parser/src/replaces.rs | 259 ++++++++++++++++++ pay-respects/Cargo.toml | 38 +++ {rules => pay-respects/rules}/c_typo.toml | 0 {rules => pay-respects/rules}/cargo.toml | 0 {rules => pay-respects/rules}/cat.toml | 0 {rules => pay-respects/rules}/cd.toml | 0 {rules => pay-respects/rules}/cp.toml | 0 {rules => pay-respects/rules}/git.toml | 0 {rules => pay-respects/rules}/mkdir.toml | 0 {rules => pay-respects/rules}/mv.toml | 0 {rules => pay-respects/rules}/npm.toml | 0 {rules => pay-respects/rules}/pacman.toml | 0 {rules => pay-respects/rules}/pr_general.toml | 0 .../rules}/pr_privilege.toml | 0 {rules => pay-respects/rules}/rm.toml | 0 {rules => pay-respects/rules}/touch.toml | 0 {rules => pay-respects/rules}/yarn.toml | 0 {src => pay-respects/src}/args.rs | 0 {src => pay-respects/src}/files.rs | 0 {src => pay-respects/src}/main.rs | 0 {src => pay-respects/src}/modes.rs | 0 {src => pay-respects/src}/replaces.rs | 0 {src => pay-respects/src}/requests.rs | 0 {src => pay-respects/src}/rules.rs | 0 {src => pay-respects/src}/runtime_rules.rs | 0 {src => pay-respects/src}/shell.rs | 0 {src => pay-respects/src}/style.rs | 0 {src => pay-respects/src}/suggestions.rs | 0 {src => pay-respects/src}/system.rs | 0 rules | 1 + 35 files changed, 554 insertions(+), 39 deletions(-) create mode 100644 pay-respects-parser/.gitignore create mode 100644 pay-respects-parser/.rustfmt.toml create mode 100644 pay-respects-parser/Cargo.toml create mode 100644 pay-respects-parser/src/lib.rs create mode 100644 pay-respects-parser/src/replaces.rs create mode 100644 pay-respects/Cargo.toml rename {rules => pay-respects/rules}/c_typo.toml (100%) rename {rules => pay-respects/rules}/cargo.toml (100%) rename {rules => pay-respects/rules}/cat.toml (100%) rename {rules => pay-respects/rules}/cd.toml (100%) rename {rules => pay-respects/rules}/cp.toml (100%) rename {rules => pay-respects/rules}/git.toml (100%) rename {rules => pay-respects/rules}/mkdir.toml (100%) rename {rules => pay-respects/rules}/mv.toml (100%) rename {rules => pay-respects/rules}/npm.toml (100%) rename {rules => pay-respects/rules}/pacman.toml (100%) rename {rules => pay-respects/rules}/pr_general.toml (100%) rename {rules => pay-respects/rules}/pr_privilege.toml (100%) rename {rules => pay-respects/rules}/rm.toml (100%) rename {rules => pay-respects/rules}/touch.toml (100%) rename {rules => pay-respects/rules}/yarn.toml (100%) rename {src => pay-respects/src}/args.rs (100%) rename {src => pay-respects/src}/files.rs (100%) rename {src => pay-respects/src}/main.rs (100%) rename {src => pay-respects/src}/modes.rs (100%) rename {src => pay-respects/src}/replaces.rs (100%) rename {src => pay-respects/src}/requests.rs (100%) rename {src => pay-respects/src}/rules.rs (100%) rename {src => pay-respects/src}/runtime_rules.rs (100%) rename {src => pay-respects/src}/shell.rs (100%) rename {src => pay-respects/src}/style.rs (100%) rename {src => pay-respects/src}/suggestions.rs (100%) rename {src => pay-respects/src}/system.rs (100%) create mode 120000 rules diff --git a/Cargo.toml b/Cargo.toml index 0bb0543..775652a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,44 +1,15 @@ -[package] -name = "pay-respects" -authors = ["iff "] -version = "0.5.15" -edition = "2021" - -# for crates.io -description = "Terminal command suggestion, alternative to thefuck written in Rust with AI support" -homepage = "https://codeberg.org/iff/pay-respects" -repository = "https://github.com/iffse/pay-respects" -keywords = ["cli", "terminal", "utility", "shell"] -categories = ["command-line-utilities"] -license = "AGPL-3.0" -include = ["**/*.rs", "**/*.toml"] - -[dependencies] -colored = "2" -sys-locale = "0.3" -rust-i18n = "3" -regex-lite = "0.1" - -toml = { version = "0.8", optional = true } -serde_json = { version = "1.0", optional = true } -serde = { version = "1.0", features = ["derive"], optional = true } -curl = { version = "0.4", optional = true } -textwrap = { version = "0.16", features = ["terminal_size"], optional = true } - -inquire = "0.7.5" - -pay-respects-parser = "0.3.2" -# pay-respects-parser = { path = "../pay-respects-parser" } - -[features] -runtime-rules = ["dep:serde", "dep:toml"] -request-ai = ["dep:serde", "dep:serde_json", "dep:textwrap"] - -# linking to libcurl dynamically requires openssl when compiling and -# complicates cross compilation -libcurl = ["dep:curl"] +[workspace] +resolver = "2" +members = [ + "pay-respects", + "pay-respects-parser", + # optional modules + # "pay-respects-module-runtime-rules", + # "pay-respects-module-request-ai" +] [profile.release] strip = true codegen-units = 1 lto = true + diff --git a/pay-respects-parser/.gitignore b/pay-respects-parser/.gitignore new file mode 100644 index 0000000..4fffb2f --- /dev/null +++ b/pay-respects-parser/.gitignore @@ -0,0 +1,2 @@ +/target +/Cargo.lock diff --git a/pay-respects-parser/.rustfmt.toml b/pay-respects-parser/.rustfmt.toml new file mode 100644 index 0000000..218e203 --- /dev/null +++ b/pay-respects-parser/.rustfmt.toml @@ -0,0 +1 @@ +hard_tabs = true diff --git a/pay-respects-parser/Cargo.toml b/pay-respects-parser/Cargo.toml new file mode 100644 index 0000000..689b7a2 --- /dev/null +++ b/pay-respects-parser/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "pay-respects-parser" +version = "0.3.2" +edition = "2021" + +# for crates.io +description = "Compile time rule parser for pay-respects" +repository = "https://github.com/iffse/pay-respects" +license = "AGPL-3.0" +include = [ + "**/*.rs", + "**/*.toml", +] + +[lib] +proc-macro = true + +[dependencies] +syn = "1.0" +quote = "1.0" +proc-macro2 = "1.0" +toml = "0.8" +serde = { version = "1.0", features = ["derive"] } diff --git a/pay-respects-parser/src/lib.rs b/pay-respects-parser/src/lib.rs new file mode 100644 index 0000000..12c1700 --- /dev/null +++ b/pay-respects-parser/src/lib.rs @@ -0,0 +1,220 @@ +// pay-respects-parser: Compile time rule parser for pay-respects +// Copyright (C) 2023 iff + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published +// by the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. + +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +use std::path::Path; + +use proc_macro::TokenStream; +use proc_macro2::TokenStream as TokenStream2; +use quote::quote; + +mod replaces; + +#[proc_macro] +pub fn parse_rules(input: TokenStream) -> TokenStream { + let directory = input.to_string().trim_matches('"').to_owned(); + let rules = get_rules(directory); + + gen_match_rules(rules) +} + +#[derive(serde::Deserialize)] +struct Rule { + command: String, + match_err: Vec, +} + +#[derive(serde::Deserialize)] +struct MatchError { + pattern: Vec, + suggest: Vec, +} + +fn get_rules(directory: String) -> Vec { + let files = std::fs::read_dir(directory).expect("Failed to read directory."); + + let mut rules = Vec::new(); + for file in files { + let file = file.expect("Failed to read file."); + let path = file.path(); + let path = path.to_str().expect("Failed to convert path to string."); + + let rule_file = parse_file(Path::new(path)); + rules.push(rule_file); + } + rules +} + +fn gen_match_rules(rules: Vec) -> TokenStream { + let command = rules + .iter() + .map(|x| x.command.to_owned()) + .collect::>(); + let command_matches = rules + .iter() + .map(|x| { + x.match_err + .iter() + .map(|x| { + let pattern = x + .pattern + .iter() + .map(|x| x.to_lowercase()) + .collect::>(); + let suggests = x + .suggest + .iter() + .map(|x| x.to_string()) + .collect::>(); + (pattern, suggests) + }) + .collect::, Vec)>>() + }) + .collect::, Vec)>>>(); + + let mut matches_tokens = Vec::new(); + + for match_err in command_matches { + let mut suggestion_tokens = Vec::new(); + let mut patterns_tokens = Vec::new(); + for (pattern, suggests) in match_err { + // let mut match_condition = Vec::new(); + let mut pattern_suggestions = Vec::new(); + for suggest in suggests { + let (suggestion_no_condition, conditions) = parse_conditions(&suggest); + let suggest = eval_suggest(&suggestion_no_condition); + let suggestion = quote! { + if #(#conditions)&&* { + #suggest; + }; + }; + pattern_suggestions.push(suggestion); + } + let match_tokens = quote! { + #(#pattern_suggestions)* + }; + + suggestion_tokens.push(match_tokens); + + let string_patterns = pattern.join("\", \""); + let string_patterns: TokenStream2 = + format!("[\"{}\"]", string_patterns).parse().unwrap(); + patterns_tokens.push(string_patterns); + } + + matches_tokens.push(quote! { + #( + for pattern in #patterns_tokens { + if error_msg.contains(pattern) { + let split = split_command(&last_command); + #suggestion_tokens; + }; + })* + }) + } + quote! { + let mut last_command = last_command.to_string(); + match executable { + #( + #command => { + #matches_tokens + } + )* + _ => {} + }; + } + .into() +} + +fn parse_file(file: &Path) -> Rule { + let file = std::fs::read_to_string(file).expect("Failed to read file."); + toml::from_str(&file).expect("Failed to parse toml.") +} + +fn parse_conditions(suggest: &str) -> (String, Vec) { + let mut eval_conditions = Vec::new(); + if suggest.starts_with('#') { + let mut lines = suggest.lines().collect::>(); + let mut conditions = String::new(); + for (i, line) in lines[0..].iter().enumerate() { + conditions.push_str(line); + if line.ends_with(']') { + lines = lines[i + 1..].to_vec(); + break; + } + } + let conditions = conditions + .trim_start_matches(['#', '[']) + .trim_end_matches(']') + .split(',') + .collect::>(); + + for condition in conditions { + let (mut condition, arg) = condition.split_once('(').unwrap(); + condition = condition.trim(); + let arg = arg.trim_start_matches('(').trim_end_matches(')'); + let reverse = match condition.starts_with('!') { + true => { + condition = condition.trim_start_matches('!'); + true + } + false => false, + }; + let evaluated_condition = eval_condition(condition, arg); + + eval_conditions.push(quote! {#evaluated_condition == !#reverse}); + } + let suggest = lines.join("\n"); + return (suggest, eval_conditions); + } + (suggest.to_owned(), vec![quote! {true}]) +} + +fn eval_condition(condition: &str, arg: &str) -> TokenStream2 { + match condition { + "executable" => quote! {data.has_executable(#arg)}, + "err_contains" => quote! {error_msg.contains(#arg)}, + "cmd_contains" => quote! {last_command.contains(#arg)}, + "min_length" => quote! {(split.len() >= #arg.parse::().unwrap())}, + "length" => quote! {(split.len() == #arg.parse::().unwrap())}, + "max_length" => quote! {(split.len() <= #arg.parse::().unwrap() + 1)}, + "shell" => quote! {(shell == #arg)}, + _ => unreachable!("Unknown condition when evaluation condition: {}", condition), + } +} + +fn eval_suggest(suggest: &str) -> TokenStream2 { + let mut suggest = suggest.to_owned(); + if suggest.contains("{{command}}") { + suggest = suggest.replace("{{command}}", "{last_command}"); + } + + let mut replace_list = Vec::new(); + let mut opt_list = Vec::new(); + let mut cmd_list = Vec::new(); + + replaces::opts(&mut suggest, &mut replace_list, &mut opt_list); + replaces::cmd_reg(&mut suggest, &mut replace_list); + replaces::err(&mut suggest, &mut replace_list); + replaces::command(&mut suggest, &mut replace_list); + replaces::shell(&mut suggest, &mut cmd_list); + replaces::typo(&mut suggest, &mut replace_list); + replaces::shell_tag(&mut suggest, &mut replace_list, cmd_list); + + quote! { + #(#opt_list)* + data.add_candidate(&format!{#suggest, #(#replace_list),*}); + } +} diff --git a/pay-respects-parser/src/replaces.rs b/pay-respects-parser/src/replaces.rs new file mode 100644 index 0000000..090b9d9 --- /dev/null +++ b/pay-respects-parser/src/replaces.rs @@ -0,0 +1,259 @@ +use proc_macro2::TokenStream as TokenStream2; +use quote::quote; + +fn rtag(name: &str, x: i32, y: String) -> TokenStream2 { + format!("{}{} = {}", name, x, y).parse().unwrap() +} + +fn tag(name: &str, x: i32) -> String { + format!("{{{}{}}}", name, x) +} + +fn eval_placeholder( + string: &str, + start: &str, + end: &str, +) -> (std::ops::Range, std::ops::Range) { + let start_index = string.find(start).unwrap(); + let end_index = string[start_index..].find(end).unwrap() + start_index + end.len(); + + let placeholder = start_index..end_index; + + let args = start_index + start.len()..end_index - end.len(); + + (placeholder, args) +} + +pub fn opts( + suggest: &mut String, + replace_list: &mut Vec, + opt_list: &mut Vec, +) { + let mut replace_tag = 0; + let tag_name = "opts"; + while suggest.contains(" {{opt::") { + let (placeholder, args) = eval_placeholder(suggest, " {{opt::", "}}"); + + let opt = &suggest[args.to_owned()]; + let regex = opt.trim(); + let current_tag = tag(tag_name, replace_tag); + let token_tag: TokenStream2 = format!("{}{}", tag_name, replace_tag).parse().unwrap(); + let command = quote! { + let #token_tag = opt_regex(#regex, &mut last_command); + }; + opt_list.push(command); + + replace_list.push(rtag(tag_name, replace_tag, current_tag.to_owned())); + suggest.replace_range(placeholder, ¤t_tag); + replace_tag += 1; + } + if replace_tag > 0 { + let split = quote! { + let split = split_command(&last_command); + }; + opt_list.push(split); + } +} + +pub fn cmd_reg(suggest: &mut String, replace_list: &mut Vec) { + let mut replace_tag = 0; + let tag_name = "cmd"; + + while suggest.contains("{{cmd::") { + let (placeholder, args) = eval_placeholder(suggest, "{{cmd::", "}}"); + + let regex = suggest[args.to_owned()].trim(); + + let command = format!("cmd_regex(r###\"{}\"###, &last_command)", regex); + + replace_list.push(rtag(tag_name, replace_tag, command)); + suggest.replace_range(placeholder, &tag(tag_name, replace_tag)); + replace_tag += 1; + } +} + +pub fn err(suggest: &mut String, replace_list: &mut Vec) { + let mut replace_tag = 0; + let tag_name = "err"; + + while suggest.contains("{{err::") { + let (placeholder, args) = eval_placeholder(suggest, "{{err::", "}}"); + + let regex = suggest[args.to_owned()].trim(); + + let command = format!("err_regex(r###\"{}\"###, error_msg)", regex); + + replace_list.push(rtag(tag_name, replace_tag, command)); + suggest.replace_range(placeholder, &tag(tag_name, replace_tag)); + replace_tag += 1; + } +} + +pub fn command(suggest: &mut String, replace_list: &mut Vec) { + let mut replace_tag = 0; + let tag_name = "command"; + while suggest.contains("{{command") { + let (placeholder, args) = eval_placeholder(suggest, "{{command", "}}"); + + let range = suggest[args.to_owned()].trim_matches(|c| c == '[' || c == ']'); + if let Some((start, end)) = range.split_once(':') { + let mut start_string = start.to_string(); + let start = start.parse::().unwrap_or(0); + if start < 0 { + start_string = format!("split.len() {}", start); + }; + let end_string; + let parsed_end = end.parse::(); + if parsed_end.is_err() { + end_string = String::from("split.len()"); + } else { + let end = parsed_end.clone().unwrap(); + if end < 0 { + end_string = format!("split.len() {}", end + 1); + } else { + end_string = (end + 1).to_string(); + } + }; + + let command = format! {r#"split[{}..{}].join(" ")"#, start_string, end_string}; + + replace_list.push(rtag(tag_name, replace_tag, command)); + suggest.replace_range(placeholder, &tag(tag_name, replace_tag)); + } else { + let range = range.parse::().unwrap_or(0); + let command = if range < 0 { + format!("split[std::cmp::max(split.len() {}, 0)]", range) + } else { + format!("split[{}]", range) + }; + + replace_list.push(rtag(tag_name, replace_tag, command)); + suggest.replace_range(placeholder, &tag(tag_name, replace_tag)); + } + replace_tag += 1; + } +} + +pub fn typo(suggest: &mut String, replace_list: &mut Vec) { + let mut replace_tag = 0; + let tag_name = "typo"; + + while suggest.contains("{{typo") { + let (placeholder, args) = eval_placeholder(suggest, "{{typo", "}}"); + + let string_index = if suggest.contains('[') { + let split = suggest[args.to_owned()] + .split(&['[', ']']) + .collect::>(); + let command_index = split[1]; + if !command_index.contains(':') { + let command_index = command_index.parse::().unwrap(); + + let index = if command_index < 0 { + format!("split.len() {}", command_index) + } else { + command_index.to_string() + }; + format!("{}..{} + 1", index, index) + } else { + let (start, end) = command_index.split_once(':').unwrap(); + let start = start.parse::().unwrap_or(0); + let start_string = if start < 0 { + format!("split.len() {}", start) + } else { + start.to_string() + }; + let end = end.parse::(); + let end_string = if end.is_err() { + String::from("split.len()") + } else { + let end = end.unwrap(); + if end < 0 { + format!("split.len() {}", end + 1) + } else { + (end + 1).to_string() + } + }; + + format!("{}..{}", start_string, end_string) + } + } else { + unreachable!("Typo suggestion must have a command index"); + }; + let match_list = if suggest.contains('(') { + let split = suggest[args.to_owned()] + .split_once("(") + .unwrap() + .1 + .rsplit_once(")") + .unwrap() + .0; + split.split(',').collect::>() + } else { + unreachable!("Typo suggestion must have a match list"); + }; + + let match_list = match_list + .iter() + .map(|s| s.trim().to_string()) + .collect::>(); + + let command = if match_list[0].starts_with("eval_shell_command(") { + let function = match_list.join(","); + // add a " after first comma, and a " before last ) + let function = format!( + "{}\"{}{}", + &function[..function.find(',').unwrap() + 1], + &function[function.find(',').unwrap() + 1..function.len() - 1], + "\")" + ); + format!("suggest_typo(&split[{}], {}, executables)", string_index, function) + } else { + let string_match_list = match_list.join("\".to_string(), \""); + let string_match_list = format!("\"{}\".to_string()", string_match_list); + format!( + "suggest_typo(&split[{}], vec![{}], executables)", + string_index, string_match_list + ) + }; + + replace_list.push(rtag(tag_name, replace_tag, command)); + suggest.replace_range(placeholder, &tag(tag_name, replace_tag)); + replace_tag += 1; + } +} + +pub fn shell(suggest: &mut String, cmd_list: &mut Vec) { + while suggest.contains("{{shell") { + let (placeholder, args) = eval_placeholder(suggest, "{{shell", "}}"); + let range = suggest[args.to_owned()].trim_matches(|c| c == '(' || c == ')'); + + let command = format!("eval_shell_command(shell, {})", range); + + suggest.replace_range(placeholder, &command); + cmd_list.push(command); + } +} + +pub fn shell_tag( + suggest: &mut String, + replace_list: &mut Vec, + cmd_list: Vec, +) { + let mut replace_tag = 0; + let tag_name = "shell"; + + for command in cmd_list { + if suggest.contains(&command) { + *suggest = suggest.replace(&command, &tag(tag_name, replace_tag)); + + let split = command.split_once(',').unwrap(); + let argument = split.1.trim_end_matches(')').trim(); + let argument = format!("\"{}\"", argument); + let function = format!("{}, {}).join(\"\")", split.0, argument); + // let function = format!("\"{}, {}\"", split.0, split.1); + replace_list.push(rtag(tag_name, replace_tag, function)); + replace_tag += 1; + } + } +} diff --git a/pay-respects/Cargo.toml b/pay-respects/Cargo.toml new file mode 100644 index 0000000..ab2e87f --- /dev/null +++ b/pay-respects/Cargo.toml @@ -0,0 +1,38 @@ +[package] +name = "pay-respects" +authors = ["iff "] +version = "0.5.15" +edition = "2021" + +# for crates.io +description = "Terminal command suggestion, alternative to thefuck written in Rust with AI support" +homepage = "https://codeberg.org/iff/pay-respects" +repository = "https://github.com/iffse/pay-respects" +keywords = ["cli", "terminal", "utility", "shell"] +categories = ["command-line-utilities"] +license = "AGPL-3.0" +include = ["**/*.rs", "**/*.toml"] + +[dependencies] +colored = "2" +sys-locale = "0.3" +rust-i18n = "3" +regex-lite = "0.1" + +toml = { version = "0.8", optional = true } +serde_json = { version = "1.0", optional = true } +serde = { version = "1.0", features = ["derive"], optional = true } +curl = { version = "0.4", optional = true } +textwrap = { version = "0.16", features = ["terminal_size"], optional = true } + +inquire = "0.7.5" + +pay-respects-parser = { version = "0.3.2", path = "../pay-respects-parser" } + +[features] +runtime-rules = ["dep:serde", "dep:toml"] +request-ai = ["dep:serde", "dep:serde_json", "dep:textwrap"] + +# linking to libcurl dynamically requires openssl when compiling and +# complicates cross compilation +libcurl = ["dep:curl"] diff --git a/rules/c_typo.toml b/pay-respects/rules/c_typo.toml similarity index 100% rename from rules/c_typo.toml rename to pay-respects/rules/c_typo.toml diff --git a/rules/cargo.toml b/pay-respects/rules/cargo.toml similarity index 100% rename from rules/cargo.toml rename to pay-respects/rules/cargo.toml diff --git a/rules/cat.toml b/pay-respects/rules/cat.toml similarity index 100% rename from rules/cat.toml rename to pay-respects/rules/cat.toml diff --git a/rules/cd.toml b/pay-respects/rules/cd.toml similarity index 100% rename from rules/cd.toml rename to pay-respects/rules/cd.toml diff --git a/rules/cp.toml b/pay-respects/rules/cp.toml similarity index 100% rename from rules/cp.toml rename to pay-respects/rules/cp.toml diff --git a/rules/git.toml b/pay-respects/rules/git.toml similarity index 100% rename from rules/git.toml rename to pay-respects/rules/git.toml diff --git a/rules/mkdir.toml b/pay-respects/rules/mkdir.toml similarity index 100% rename from rules/mkdir.toml rename to pay-respects/rules/mkdir.toml diff --git a/rules/mv.toml b/pay-respects/rules/mv.toml similarity index 100% rename from rules/mv.toml rename to pay-respects/rules/mv.toml diff --git a/rules/npm.toml b/pay-respects/rules/npm.toml similarity index 100% rename from rules/npm.toml rename to pay-respects/rules/npm.toml diff --git a/rules/pacman.toml b/pay-respects/rules/pacman.toml similarity index 100% rename from rules/pacman.toml rename to pay-respects/rules/pacman.toml diff --git a/rules/pr_general.toml b/pay-respects/rules/pr_general.toml similarity index 100% rename from rules/pr_general.toml rename to pay-respects/rules/pr_general.toml diff --git a/rules/pr_privilege.toml b/pay-respects/rules/pr_privilege.toml similarity index 100% rename from rules/pr_privilege.toml rename to pay-respects/rules/pr_privilege.toml diff --git a/rules/rm.toml b/pay-respects/rules/rm.toml similarity index 100% rename from rules/rm.toml rename to pay-respects/rules/rm.toml diff --git a/rules/touch.toml b/pay-respects/rules/touch.toml similarity index 100% rename from rules/touch.toml rename to pay-respects/rules/touch.toml diff --git a/rules/yarn.toml b/pay-respects/rules/yarn.toml similarity index 100% rename from rules/yarn.toml rename to pay-respects/rules/yarn.toml diff --git a/src/args.rs b/pay-respects/src/args.rs similarity index 100% rename from src/args.rs rename to pay-respects/src/args.rs diff --git a/src/files.rs b/pay-respects/src/files.rs similarity index 100% rename from src/files.rs rename to pay-respects/src/files.rs diff --git a/src/main.rs b/pay-respects/src/main.rs similarity index 100% rename from src/main.rs rename to pay-respects/src/main.rs diff --git a/src/modes.rs b/pay-respects/src/modes.rs similarity index 100% rename from src/modes.rs rename to pay-respects/src/modes.rs diff --git a/src/replaces.rs b/pay-respects/src/replaces.rs similarity index 100% rename from src/replaces.rs rename to pay-respects/src/replaces.rs diff --git a/src/requests.rs b/pay-respects/src/requests.rs similarity index 100% rename from src/requests.rs rename to pay-respects/src/requests.rs diff --git a/src/rules.rs b/pay-respects/src/rules.rs similarity index 100% rename from src/rules.rs rename to pay-respects/src/rules.rs diff --git a/src/runtime_rules.rs b/pay-respects/src/runtime_rules.rs similarity index 100% rename from src/runtime_rules.rs rename to pay-respects/src/runtime_rules.rs diff --git a/src/shell.rs b/pay-respects/src/shell.rs similarity index 100% rename from src/shell.rs rename to pay-respects/src/shell.rs diff --git a/src/style.rs b/pay-respects/src/style.rs similarity index 100% rename from src/style.rs rename to pay-respects/src/style.rs diff --git a/src/suggestions.rs b/pay-respects/src/suggestions.rs similarity index 100% rename from src/suggestions.rs rename to pay-respects/src/suggestions.rs diff --git a/src/system.rs b/pay-respects/src/system.rs similarity index 100% rename from src/system.rs rename to pay-respects/src/system.rs diff --git a/rules b/rules new file mode 120000 index 0000000..1c65a51 --- /dev/null +++ b/rules @@ -0,0 +1 @@ +pay-respects/rules \ No newline at end of file