Fix 'help commands'; Add 'is_custom' column (#420)

* Fix fetching commands; Add is_custom column

* Remove old comment
This commit is contained in:
Jakub Žádník 2021-12-03 20:45:29 +02:00 committed by GitHub
parent f3c8d35eb7
commit 405a4e58c7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 89 additions and 37 deletions

View File

@ -85,19 +85,19 @@ fn help(
let find: Option<Spanned<String>> = call.get_flag(engine_state, stack, "find")?; let find: Option<Spanned<String>> = call.get_flag(engine_state, stack, "find")?;
let rest: Vec<Spanned<String>> = call.rest(engine_state, stack, 0)?; let rest: Vec<Spanned<String>> = call.rest(engine_state, stack, 0)?;
let full_commands = engine_state.get_signatures_with_examples(); let full_commands = engine_state.get_signatures_with_examples(false);
if let Some(f) = find { if let Some(f) = find {
let search_string = f.item; let search_string = f.item;
let mut found_cmds_vec = Vec::new(); let mut found_cmds_vec = Vec::new();
for cmd in full_commands { for (sig, _, is_plugin, is_custom) in full_commands {
let mut cols = vec![]; let mut cols = vec![];
let mut vals = vec![]; let mut vals = vec![];
let key = cmd.0.name.clone(); let key = sig.name.clone();
let c = cmd.0.usage.clone(); let c = sig.usage.clone();
let e = cmd.0.extra_usage.clone(); let e = sig.extra_usage.clone();
if key.to_lowercase().contains(&search_string) if key.to_lowercase().contains(&search_string)
|| c.to_lowercase().contains(&search_string) || c.to_lowercase().contains(&search_string)
|| e.to_lowercase().contains(&search_string) || e.to_lowercase().contains(&search_string)
@ -110,13 +110,19 @@ fn help(
cols.push("category".into()); cols.push("category".into());
vals.push(Value::String { vals.push(Value::String {
val: cmd.0.category.to_string(), val: sig.category.to_string(),
span: head, span: head,
}); });
cols.push("is_plugin".into()); cols.push("is_plugin".into());
vals.push(Value::Bool { vals.push(Value::Bool {
val: cmd.2, val: is_plugin,
span: head,
});
cols.push("is_custom".into());
vals.push(Value::Bool {
val: is_custom,
span: head, span: head,
}); });
@ -143,13 +149,13 @@ fn help(
let mut found_cmds_vec = Vec::new(); let mut found_cmds_vec = Vec::new();
if rest[0].item == "commands" { if rest[0].item == "commands" {
for cmd in full_commands { for (sig, _, is_plugin, is_custom) in full_commands {
let mut cols = vec![]; let mut cols = vec![];
let mut vals = vec![]; let mut vals = vec![];
let key = cmd.0.name.clone(); let key = sig.name.clone();
let c = cmd.0.usage.clone(); let c = sig.usage.clone();
let e = cmd.0.extra_usage.clone(); let e = sig.extra_usage.clone();
cols.push("name".into()); cols.push("name".into());
vals.push(Value::String { vals.push(Value::String {
@ -159,13 +165,19 @@ fn help(
cols.push("category".into()); cols.push("category".into());
vals.push(Value::String { vals.push(Value::String {
val: cmd.0.category.to_string(), val: sig.category.to_string(),
span: head, span: head,
}); });
cols.push("is_plugin".into()); cols.push("is_plugin".into());
vals.push(Value::Bool { vals.push(Value::Bool {
val: cmd.2, val: is_plugin,
span: head,
});
cols.push("is_custom".into());
vals.push(Value::Bool {
val: is_custom,
span: head, span: head,
}); });
@ -197,8 +209,8 @@ fn help(
let output = full_commands let output = full_commands
.iter() .iter()
.filter(|(signature, _, _)| signature.name == name) .filter(|(signature, _, _, _)| signature.name == name)
.map(|(signature, examples, _)| get_full_help(signature, examples, engine_state)) .map(|(signature, examples, _, _)| get_full_help(signature, examples, engine_state))
.collect::<Vec<String>>(); .collect::<Vec<String>>();
if !output.is_empty() { if !output.is_empty() {

View File

@ -64,7 +64,7 @@ fn generate_doc(name: &str, engine_state: &EngineState) -> (Vec<String>, Vec<Val
// generate_docs gets the documentation from each command and returns a Table as output // generate_docs gets the documentation from each command and returns a Table as output
pub fn generate_docs(engine_state: &EngineState) -> Value { pub fn generate_docs(engine_state: &EngineState) -> Value {
let signatures = engine_state.get_signatures(); let signatures = engine_state.get_signatures(true);
// cmap will map parent commands to it's subcommands e.g. to -> [to csv, to yaml, to bson] // cmap will map parent commands to it's subcommands e.g. to -> [to csv, to yaml, to bson]
let mut cmap: HashMap<String, Vec<String>> = HashMap::new(); let mut cmap: HashMap<String, Vec<String>> = HashMap::new();
@ -160,7 +160,7 @@ pub fn get_documentation(
let mut subcommands = vec![]; let mut subcommands = vec![];
if !config.no_subcommands { if !config.no_subcommands {
let signatures = engine_state.get_signatures(); let signatures = engine_state.get_signatures(true);
for sig in signatures { for sig in signatures {
if sig.name.starts_with(&format!("{} ", cmd_name)) { if sig.name.starts_with(&format!("{} ", cmd_name)) {
subcommands.push(format!(" {} - {}", sig.name, sig.usage)); subcommands.push(format!(" {} - {}", sig.name, sig.usage));

View File

@ -602,6 +602,12 @@ pub fn eval_variable(
span, span,
}); });
cols.push("is_custom".to_string());
vals.push(Value::Bool {
val: decl.get_block_id().is_some(),
span,
});
cols.push("creates_scope".to_string()); cols.push("creates_scope".to_string());
vals.push(Value::Bool { vals.push(Value::Bool {
val: signature.creates_scope, val: signature.creates_scope,

View File

@ -440,37 +440,71 @@ impl EngineState {
} }
} }
pub fn get_signatures(&self) -> Vec<Signature> { /// Get all IDs of all commands within scope, sorted by the commads' names
let mut output = vec![]; pub fn get_decl_ids_sorted(&self, include_hidden: bool) -> impl Iterator<Item = DeclId> {
for decl in self.decls.iter() { let mut decls_map = HashMap::new();
if decl.get_block_id().is_none() {
let mut signature = (*decl).signature();
signature.usage = decl.usage().to_string();
signature.extra_usage = decl.extra_usage().to_string();
output.push(signature); for frame in &self.scope {
} let frame_decls = if include_hidden {
frame.decls.clone()
} else {
frame
.decls
.clone()
.into_iter()
.filter(|(_, id)| frame.visibility.is_decl_id_visible(id))
.collect()
};
decls_map.extend(frame_decls);
} }
output let mut decls: Vec<(Vec<u8>, DeclId)> = decls_map.into_iter().collect();
decls.sort_by(|a, b| a.0.cmp(&b.0));
decls.into_iter().map(|(_, id)| id)
} }
pub fn get_signatures_with_examples(&self) -> Vec<(Signature, Vec<Example>, bool)> { /// Get signatures of all commands within scope.
let mut output = vec![]; pub fn get_signatures(&self, include_hidden: bool) -> Vec<Signature> {
for decl in self.decls.iter() { self.get_decl_ids_sorted(include_hidden)
if decl.get_block_id().is_none() { .map(|id| {
let decl = self.get_decl(id);
let mut signature = (*decl).signature(); let mut signature = (*decl).signature();
signature.usage = decl.usage().to_string(); signature.usage = decl.usage().to_string();
signature.extra_usage = decl.extra_usage().to_string(); signature.extra_usage = decl.extra_usage().to_string();
output.push((signature, decl.examples(), decl.is_plugin().is_some())); signature
} })
} .collect()
}
output.sort_by(|a, b| a.0.name.cmp(&b.0.name)); /// Get signatures of all commands within scope.
output.dedup_by(|a, b| a.0.name.cmp(&b.0.name).is_eq()); ///
/// In addition to signatures, it returns whether each command is:
/// a) a plugin
/// b) custom
pub fn get_signatures_with_examples(
&self,
include_hidden: bool,
) -> Vec<(Signature, Vec<Example>, bool, bool)> {
self.get_decl_ids_sorted(include_hidden)
.map(|id| {
let decl = self.get_decl(id);
output let mut signature = (*decl).signature();
signature.usage = decl.usage().to_string();
signature.extra_usage = decl.extra_usage().to_string();
(
signature,
decl.examples(),
decl.is_plugin().is_some(),
decl.get_block_id().is_some(),
)
})
.collect()
} }
pub fn get_block(&self, block_id: BlockId) -> &Block { pub fn get_block(&self, block_id: BlockId) -> &Block {