Skip to content

Commit 9affc43

Browse files
committed
Adding reserved commands
Adding some utility commands that will be reserved for tome's core functionality: - commands - exec - help - tome These help provide some utility functionality as laid out in docs/proposals/0001-cli-design.md.
1 parent 9312153 commit 9affc43

File tree

12 files changed

+163
-31
lines changed

12 files changed

+163
-31
lines changed

Cargo.lock

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ license = "MIT"
77

88
[dependencies]
99
clap = { version = "3.0.7", features = ["derive"]}
10+
lazy_static = {}
1011

1112

1213

example/file_example

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,5 @@ import sys
1313
if len(sys.argv) > 1 and sys.argv[1] == "--complete":
1414
sys.stdout.write("file autocomplete example")
1515
else:
16-
print("hello")
16+
sys.stdout.write("file autocomplete example")
17+
# print("hello")

src/commands/builtins.rs

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
use super::help::help;
2+
use std::collections::HashMap;
3+
4+
pub struct Command {
5+
pub func: fn(&str, &[String]) -> Result<String, String>,
6+
pub help_text: &'static str,
7+
}
8+
9+
lazy_static! {
10+
pub static ref BUILTIN_COMMANDS: HashMap<String, Command> = {
11+
let mut m = HashMap::new();
12+
m.insert(
13+
"commands".to_owned(),
14+
Command {
15+
func: help_command as fn(&str, &[String]) -> Result<String, String>,
16+
help_text: "print all commands",
17+
},
18+
);
19+
m.insert(
20+
"exec".to_owned(),
21+
Command {
22+
func: noop_command as fn(&str, &[String]) -> Result<String, String>,
23+
help_text: "execute a command",
24+
},
25+
);
26+
m.insert(
27+
"help".to_owned(),
28+
Command {
29+
func: help_command as fn(&str, &[String]) -> Result<String, String>,
30+
help_text: "print help for the command",
31+
},
32+
);
33+
m.insert(
34+
"tome".to_owned(),
35+
Command {
36+
func: noop_command as fn(&str, &[String]) -> Result<String, String>,
37+
help_text: "currently a no-op. reserved namespace for future tome commands",
38+
},
39+
);
40+
m
41+
};
42+
}
43+
44+
fn help_command(root: &str, _: &[String]) -> Result<String, String> {
45+
help(root)
46+
}
47+
48+
fn noop_command(_: &str, _: &[String]) -> Result<String, String> {
49+
Ok("".to_owned())
50+
}

src/commands/complete.rs

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use super::super::{
22
directory, script,
33
types::{CommandType, TargetType},
44
};
5+
use super::builtins::BUILTIN_COMMANDS;
56
use std::{fs, io, path::PathBuf};
67

78
pub fn complete(command_directory_path: &str, args: &[String]) -> Result<String, String> {
@@ -32,30 +33,37 @@ pub fn complete(command_directory_path: &str, args: &[String]) -> Result<String,
3233
let remaining_args: Vec<_> = args_peekable.collect();
3334
return match target_type {
3435
TargetType::Directory => {
35-
let mut result = vec![];
36-
let paths_raw: io::Result<_> = fs::read_dir(target.to_str().unwrap_or(""));
37-
// TODO(zph) deftly fix panics when this code path is triggered with empty string: ie sc dir_example bar<TAB>
38-
// current implementation avoids the panic but is crude.
36+
let paths_raw: io::Result<_> = fs::read_dir(target.to_str().unwrap());
3937
let mut paths: Vec<_> = match paths_raw {
4038
Err(_a) => return Err("Invalid argument to completion".to_string()),
4139
Ok(a) => a,
4240
}
43-
.map(|r| r.unwrap())
44-
.collect();
45-
paths.sort_by_key(|f| f.path());
46-
for path_buf in paths {
47-
let path = path_buf.path();
48-
if path.is_dir() && !directory::is_tome_script_directory(&path) {
49-
continue;
41+
.filter_map(|r| match r {
42+
Ok(path_buf) => {
43+
let path = path_buf.path();
44+
if path.is_dir() && !directory::is_tome_script_directory(&path) {
45+
return None;
46+
}
47+
if path.is_file()
48+
&& !script::is_tome_script(
49+
path_buf.file_name().to_str().unwrap_or_default(),
50+
)
51+
{
52+
return None;
53+
}
54+
Some(path.file_name().unwrap().to_str().unwrap_or("").to_owned())
5055
}
51-
if path.is_file()
52-
&& !script::is_tome_script(path_buf.file_name().to_str().unwrap_or_default())
53-
{
54-
continue;
56+
Err(_) => None,
57+
})
58+
.collect();
59+
// if this is the root directory, add the builtin commands
60+
if target.to_str().unwrap() == command_directory_path {
61+
for command in BUILTIN_COMMANDS.keys() {
62+
paths.push(command.to_owned());
5563
}
56-
result.push(path.file_name().unwrap().to_str().unwrap_or("").to_owned());
5764
}
58-
Ok(result.join(" "))
65+
paths.sort_by_key(|f| f.to_owned());
66+
Ok(paths.join(" "))
5967
}
6068
TargetType::File => match script::Script::load(target.to_str().unwrap_or_default()) {
6169
Ok(script) => script.get_execution_body(CommandType::Completion, &remaining_args),

src/commands/execute.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use super::super::{
22
script,
33
types::{CommandType, TargetType},
44
};
5-
use super::help;
5+
use super::{builtins::BUILTIN_COMMANDS, help};
66
use std::path::PathBuf;
77

88
pub fn execute(command_directory_path: &str, args: &[String]) -> Result<String, String> {
@@ -16,6 +16,16 @@ pub fn execute(command_directory_path: &str, args: &[String]) -> Result<String,
1616
if args_peekable.peek().is_none() {
1717
return help::help(command_directory_path);
1818
}
19+
// special handling for root subcommmand for reserved
20+
// commands
21+
match args_peekable.peek() {
22+
Some(&command_name) => match BUILTIN_COMMANDS.get(command_name) {
23+
Some(command) => return (command.func)(command_directory_path, args),
24+
None => {}
25+
},
26+
None => {}
27+
}
28+
// generic handling
1929
while let Some(arg) = args_peekable.peek() {
2030
target.push(arg);
2131
if target.is_file() {

src/commands/help.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,30 @@
11
use super::super::directory::scan_directory;
2+
use super::builtins::BUILTIN_COMMANDS;
23

34
macro_rules! help_template {
45
() => {
56
r#"echo -e
67
'This is an instance of tome, running against the directory {}.
78
\nThe commands are namespaced by the directory structure.
9+
\nBuiltin commands available to all instance of tome are:
10+
\n {}
811
\nFull list of commands available are:
912
\n {}
1013
';"#
1114
};
1215
}
1316

1417
pub fn help(root: &str) -> Result<String, String> {
18+
let mut builtins_with_help = vec![];
19+
// print builtins first
20+
for (command, command_struct) in BUILTIN_COMMANDS.iter() {
21+
builtins_with_help.push(format!(
22+
" {}: {}",
23+
escape_slashes(&command),
24+
escape_slashes(&command_struct.help_text),
25+
))
26+
}
27+
1528
let mut commands_with_help = vec![];
1629
let commands_and_scripts = match scan_directory(root, &mut vec![]) {
1730
Ok(result) => result,
@@ -24,10 +37,12 @@ pub fn help(root: &str) -> Result<String, String> {
2437
escape_slashes(&script.summary_string)
2538
))
2639
}
40+
2741
Ok(format!(
2842
help_template!(),
2943
root,
30-
commands_with_help.join("\\n")
44+
builtins_with_help.join("\\n"),
45+
commands_with_help.join("\\n"),
3146
))
3247
}
3348

src/commands/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
pub mod builtins;
12
pub mod complete;
23
pub mod execute;
34
pub mod help;

src/directory.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ pub fn scan_directory(
99
previous_commands: &mut Vec<String>,
1010
) -> io::Result<Vec<(String, Script)>> {
1111
let mut result = vec![];
12-
let mut paths: Vec<_> = read_dir(root).unwrap().map(|r| r.unwrap()).collect();
13-
paths.sort_by_key(|f| f.path());
12+
let paths: Vec<_> = read_dir(root).unwrap().map(|r| r.unwrap()).collect();
13+
// paths.sort_by_key(|f| f.path());
1414
for entry in paths {
1515
let path = entry.path();
1616
previous_commands.push(

src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
use clap::Parser;
22

3+
#[macro_use]
4+
extern crate lazy_static;
5+
36
pub mod cli;
47
pub mod commands;
58
pub mod directory;

0 commit comments

Comments
 (0)