Change the usage misnomer to "description" (#13598)

# Description
    
The meaning of the word usage is specific to describing how a command
function is *used* and not a synonym for general description. Usage can
be used to describe the SYNOPSIS or EXAMPLES sections of a man page
where the permitted argument combinations are shown or example *uses*
are given.
Let's not confuse people and call it what it is a description.

Our `help` command already creates its own *Usage* section based on the
available arguments and doesn't refer to the description with usage.

# User-Facing Changes

`help commands` and `scope commands` will now use `description` or
`extra_description`
`usage`-> `description`
`extra_usage` -> `extra_description`

Breaking change in the plugin protocol:

In the signature record communicated with the engine.
`usage`-> `description`
`extra_usage` -> `extra_description`

The same rename also takes place for the methods on
`SimplePluginCommand` and `PluginCommand`

# Tests + Formatting
- Updated plugin protocol specific changes
# After Submitting
- [ ] update plugin protocol doc
This commit is contained in:
Stefan Holderbach
2024-08-22 12:02:08 +02:00
committed by GitHub
parent 3ab9f0b90a
commit 95b78eee25
597 changed files with 1085 additions and 1039 deletions

View File

@ -15,8 +15,8 @@ pub struct Alias {
/// Wrapped inner [`Command`]. `None` if alias of external call
pub command: Option<Box<dyn Command>>,
pub wrapped_call: Expression,
pub usage: String,
pub extra_usage: String,
pub description: String,
pub extra_description: String,
}
impl Command for Alias {
@ -32,12 +32,12 @@ impl Command for Alias {
}
}
fn usage(&self) -> &str {
&self.usage
fn description(&self) -> &str {
&self.description
}
fn extra_usage(&self) -> &str {
&self.extra_usage
fn extra_description(&self) -> &str {
&self.extra_description
}
fn run(

View File

@ -31,9 +31,15 @@ pub trait Command: Send + Sync + CommandClone {
fn signature(&self) -> Signature;
fn usage(&self) -> &str;
/// Short preferably single sentence description for the command.
///
/// Will be shown with the completions etc.
fn description(&self) -> &str;
fn extra_usage(&self) -> &str {
/// Longer documentation description, if necessary.
///
/// Will be shown below `description`
fn extra_description(&self) -> &str {
""
}

View File

@ -1,16 +1,16 @@
use crate::{ModuleId, Span};
use std::collections::HashMap;
/// Organizes usage messages for various primitives
/// Organizes documentation comments for various primitives
#[derive(Debug, Clone)]
pub(super) struct Usage {
// TODO: Move decl usages here
pub(super) struct Doccomments {
// TODO: Move decl doccomments here
module_comments: HashMap<ModuleId, Vec<Span>>,
}
impl Usage {
impl Doccomments {
pub fn new() -> Self {
Usage {
Doccomments {
module_comments: HashMap::new(),
}
}
@ -24,24 +24,24 @@ impl Usage {
}
/// Overwrite own values with the other
pub fn merge_with(&mut self, other: Usage) {
pub fn merge_with(&mut self, other: Doccomments) {
self.module_comments.extend(other.module_comments);
}
}
impl Default for Usage {
impl Default for Doccomments {
fn default() -> Self {
Self::new()
}
}
pub(super) fn build_usage(comment_lines: &[&[u8]]) -> (String, String) {
let mut usage = String::new();
pub(super) fn build_desc(comment_lines: &[&[u8]]) -> (String, String) {
let mut description = String::new();
let mut num_spaces = 0;
let mut first = true;
// Use the comments to build the usage
// Use the comments to build the item/command description
for contents in comment_lines {
let comment_line = if first {
// Count the number of spaces still at the front, skipping the '#'
@ -75,17 +75,17 @@ pub(super) fn build_usage(comment_lines: &[&[u8]]) -> (String, String) {
String::from_utf8_lossy(&contents[pos..]).to_string()
};
if !usage.is_empty() {
usage.push('\n');
if !description.is_empty() {
description.push('\n');
}
usage.push_str(&comment_line);
description.push_str(&comment_line);
}
if let Some((brief_usage, extra_usage)) = usage.split_once("\r\n\r\n") {
(brief_usage.to_string(), extra_usage.to_string())
} else if let Some((brief_usage, extra_usage)) = usage.split_once("\n\n") {
(brief_usage.to_string(), extra_usage.to_string())
if let Some((brief_desc, extra_desc)) = description.split_once("\r\n\r\n") {
(brief_desc.to_string(), extra_desc.to_string())
} else if let Some((brief_desc, extra_desc)) = description.split_once("\n\n") {
(brief_desc.to_string(), extra_desc.to_string())
} else {
(usage, String::default())
(description, String::default())
}
}

View File

@ -2,7 +2,7 @@ use crate::{
ast::Block,
debugger::{Debugger, NoopDebugger},
engine::{
usage::{build_usage, Usage},
description::{build_desc, Doccomments},
CachedFile, Command, CommandType, EnvVars, OverlayFrame, ScopeFrame, Stack, StateDelta,
Variable, Visibility, DEFAULT_OVERLAY_NAME,
},
@ -84,7 +84,7 @@ pub struct EngineState {
pub(super) blocks: Arc<Vec<Arc<Block>>>,
pub(super) modules: Arc<Vec<Arc<Module>>>,
pub spans: Vec<Span>,
usage: Usage,
doccomments: Doccomments,
pub scope: ScopeFrame,
signals: Signals,
pub signal_handlers: Option<Handlers>,
@ -140,7 +140,7 @@ impl EngineState {
DEFAULT_OVERLAY_NAME.as_bytes().to_vec(),
))]),
spans: vec![Span::unknown()],
usage: Usage::new(),
doccomments: Doccomments::new(),
// make sure we have some default overlay:
scope: ScopeFrame::with_empty_overlay(
DEFAULT_OVERLAY_NAME.as_bytes().to_vec(),
@ -209,7 +209,7 @@ impl EngineState {
self.virtual_paths.extend(delta.virtual_paths);
self.vars.extend(delta.vars);
self.spans.extend(delta.spans);
self.usage.merge_with(delta.usage);
self.doccomments.merge_with(delta.doccomments);
// Avoid potentially cloning the Arcs if we aren't adding anything
if !delta.decls.is_empty() {
@ -644,7 +644,7 @@ impl EngineState {
}
pub fn get_module_comments(&self, module_id: ModuleId) -> Option<&[Span]> {
self.usage.get_module_comments(module_id)
self.doccomments.get_module_comments(module_id)
}
#[cfg(feature = "plugin")]
@ -715,7 +715,7 @@ impl EngineState {
}
output.push((
decl.0.clone(),
Some(command.usage().to_string()),
Some(command.description().to_string()),
command.command_type(),
));
}
@ -897,17 +897,17 @@ impl EngineState {
self.config_path.get(key)
}
pub fn build_usage(&self, spans: &[Span]) -> (String, String) {
pub fn build_desc(&self, spans: &[Span]) -> (String, String) {
let comment_lines: Vec<&[u8]> = spans
.iter()
.map(|span| self.get_span_contents(*span))
.collect();
build_usage(&comment_lines)
build_desc(&comment_lines)
}
pub fn build_module_usage(&self, module_id: ModuleId) -> Option<(String, String)> {
pub fn build_module_desc(&self, module_id: ModuleId) -> Option<(String, String)> {
self.get_module_comments(module_id)
.map(|comment_spans| self.build_usage(comment_spans))
.map(|comment_spans| self.build_desc(comment_spans))
}
/// Returns the current working directory, which is guaranteed to be canonicalized.

View File

@ -5,6 +5,7 @@ mod call;
mod call_info;
mod capture_block;
mod command;
mod description;
mod engine_state;
mod error_handler;
mod overlay;
@ -14,7 +15,6 @@ mod stack;
mod stack_out_dest;
mod state_delta;
mod state_working_set;
mod usage;
mod variable;
pub use cached_file::CachedFile;

View File

@ -1,8 +1,8 @@
use crate::{
ast::Block,
engine::{
usage::Usage, CachedFile, Command, EngineState, OverlayFrame, ScopeFrame, Variable,
VirtualPath,
description::Doccomments, CachedFile, Command, EngineState, OverlayFrame, ScopeFrame,
Variable, VirtualPath,
},
Module, Span,
};
@ -22,7 +22,7 @@ pub struct StateDelta {
pub blocks: Vec<Arc<Block>>, // indexed by BlockId
pub(super) modules: Vec<Arc<Module>>, // indexed by ModuleId
pub spans: Vec<Span>, // indexed by SpanId
pub(super) usage: Usage,
pub(super) doccomments: Doccomments,
pub scope: Vec<ScopeFrame>,
#[cfg(feature = "plugin")]
pub(super) plugins: Vec<Arc<dyn RegisteredPlugin>>,
@ -48,7 +48,7 @@ impl StateDelta {
modules: vec![],
spans: vec![],
scope: vec![scope_frame],
usage: Usage::new(),
doccomments: Doccomments::new(),
#[cfg(feature = "plugin")]
plugins: vec![],
#[cfg(feature = "plugin")]

View File

@ -1,7 +1,7 @@
use crate::{
ast::Block,
engine::{
usage::build_usage, CachedFile, Command, CommandType, EngineState, OverlayFrame,
description::build_desc, CachedFile, Command, CommandType, EngineState, OverlayFrame,
StateDelta, Variable, VirtualPath, Visibility,
},
BlockId, Category, CompileError, Config, DeclId, FileId, GetSpan, Module, ModuleId, ParseError,
@ -278,7 +278,9 @@ impl<'a> StateWorkingSet<'a> {
let module_id = self.num_modules() - 1;
if !comments.is_empty() {
self.delta.usage.add_module_comments(module_id, comments);
self.delta
.doccomments
.add_module_comments(module_id, comments);
}
self.last_overlay_mut().modules.insert(name, module_id);
@ -288,7 +290,7 @@ impl<'a> StateWorkingSet<'a> {
pub fn get_module_comments(&self, module_id: ModuleId) -> Option<&[Span]> {
self.delta
.usage
.doccomments
.get_module_comments(module_id)
.or_else(|| self.permanent_state.get_module_comments(module_id))
}
@ -727,7 +729,7 @@ impl<'a> StateWorkingSet<'a> {
}
output.push((
decl.0.clone(),
Some(command.usage().to_string()),
Some(command.description().to_string()),
command.command_type(),
));
}
@ -952,12 +954,12 @@ impl<'a> StateWorkingSet<'a> {
self.delta
}
pub fn build_usage(&self, spans: &[Span]) -> (String, String) {
pub fn build_desc(&self, spans: &[Span]) -> (String, String) {
let comment_lines: Vec<&[u8]> = spans
.iter()
.map(|span| self.get_span_contents(*span))
.collect();
build_usage(&comment_lines)
build_desc(&comment_lines)
}
pub fn find_block_by_span(&self, span: Span) -> Option<Arc<Block>> {

View File

@ -45,7 +45,7 @@ fn bar_plugin() -> PluginRegistryItem {
},
commands: vec![PluginSignature {
sig: Signature::new("bar")
.usage("overwrites files with random data")
.description("overwrites files with random data")
.switch("force", "ignore errors", Some('f'))
.required(
"path",

View File

@ -109,8 +109,8 @@ impl std::fmt::Display for Category {
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Signature {
pub name: String,
pub usage: String,
pub extra_usage: String,
pub description: String,
pub extra_description: String,
pub search_terms: Vec<String>,
pub required_positional: Vec<PositionalArg>,
pub optional_positional: Vec<PositionalArg>,
@ -128,7 +128,7 @@ pub struct Signature {
impl PartialEq for Signature {
fn eq(&self, other: &Self) -> bool {
self.name == other.name
&& self.usage == other.usage
&& self.description == other.description
&& self.required_positional == other.required_positional
&& self.optional_positional == other.optional_positional
&& self.rest_positional == other.rest_positional
@ -142,8 +142,8 @@ impl Signature {
pub fn new(name: impl Into<String>) -> Signature {
Signature {
name: name.into(),
usage: String::new(),
extra_usage: String::new(),
description: String::new(),
extra_description: String::new(),
search_terms: vec![],
required_positional: vec![],
optional_positional: vec![],
@ -220,14 +220,19 @@ impl Signature {
}
/// Add a description to the signature
pub fn usage(mut self, msg: impl Into<String>) -> Signature {
self.usage = msg.into();
///
/// This should be a single sentence as it is the part shown for example in the completion
/// menu.
pub fn description(mut self, msg: impl Into<String>) -> Signature {
self.description = msg.into();
self
}
/// Add an extra description to the signature
pub fn extra_usage(mut self, msg: impl Into<String>) -> Signature {
self.extra_usage = msg.into();
/// Add an extra description to the signature.
///
/// Here additional documentation can be added
pub fn extra_description(mut self, msg: impl Into<String>) -> Signature {
self.extra_description = msg.into();
self
}
@ -244,8 +249,8 @@ impl Signature {
.into_iter()
.map(|term| term.to_string())
.collect();
self.extra_usage = command.extra_usage().to_string();
self.usage = command.usage().to_string();
self.extra_description = command.extra_description().to_string();
self.description = command.description().to_string();
self
}
@ -627,12 +632,12 @@ impl Command for Predeclaration {
self.signature.clone()
}
fn usage(&self) -> &str {
&self.signature.usage
fn description(&self) -> &str {
&self.signature.description
}
fn extra_usage(&self) -> &str {
&self.signature.extra_usage
fn extra_description(&self) -> &str {
&self.signature.extra_description
}
fn run(
@ -680,12 +685,12 @@ impl Command for BlockCommand {
self.signature.clone()
}
fn usage(&self) -> &str {
&self.signature.usage
fn description(&self) -> &str {
&self.signature.description
}
fn extra_usage(&self) -> &str {
&self.signature.extra_usage
fn extra_description(&self) -> &str {
&self.signature.extra_description
}
fn run(

View File

@ -9,14 +9,14 @@ fn test_signature() {
assert_eq!(signature, from_build);
// constructing signature with description
let signature = Signature::new("signature").usage("example usage");
assert_eq!(signature.usage, "example usage".to_string())
let signature = Signature::new("signature").description("example description");
assert_eq!(signature.description, "example description".to_string())
}
#[test]
fn test_signature_chained() {
let signature = Signature::new("new_signature")
.usage("description")
.description("description")
.required("required", SyntaxShape::String, "required description")
.optional("optional", SyntaxShape::String, "optional description")
.required_named(
@ -126,7 +126,7 @@ fn test_signature_same_name() {
#[test]
fn test_signature_round_trip() {
let signature = Signature::new("new_signature")
.usage("description")
.description("description")
.required("first", SyntaxShape::String, "first required")
.required("second", SyntaxShape::Int, "second required")
.optional("optional", SyntaxShape::String, "optional description")
@ -145,8 +145,8 @@ fn test_signature_round_trip() {
let returned: Signature = serde_json::from_str(&string).unwrap();
assert_eq!(signature.name, returned.name);
assert_eq!(signature.usage, returned.usage);
assert_eq!(signature.extra_usage, returned.extra_usage);
assert_eq!(signature.description, returned.description);
assert_eq!(signature.extra_description, returned.extra_description);
assert_eq!(signature.is_filter, returned.is_filter);
assert_eq!(signature.category, returned.category);