2023-03-26 23:23:05 +08:00
|
|
|
use crate::common::{char_offset, EXPAND_RESERVED_BASE, EXPAND_RESERVED_END};
|
2023-04-09 20:33:20 +08:00
|
|
|
use crate::env::Environment;
|
2023-04-18 18:53:32 +08:00
|
|
|
use crate::operation_context::OperationContext;
|
|
|
|
use crate::parse_constants::ParseErrorList;
|
|
|
|
use crate::wchar::{wstr, WString};
|
|
|
|
use bitflags::bitflags;
|
2023-03-26 23:23:05 +08:00
|
|
|
use widestring_suffix::widestrs;
|
2023-03-11 10:47:41 +08:00
|
|
|
|
2023-04-18 18:53:32 +08:00
|
|
|
bitflags! {
|
|
|
|
/// Set of flags controlling expansions.
|
|
|
|
pub struct ExpandFlags : u16 {
|
|
|
|
/// Skip command substitutions.
|
|
|
|
const SKIP_CMDSUBST = 1 << 0;
|
|
|
|
/// Skip variable expansion.
|
|
|
|
const SKIP_VARIABLES = 1 << 1;
|
|
|
|
/// Skip wildcard expansion.
|
|
|
|
const SKIP_WILDCARDS = 1 << 2;
|
|
|
|
/// The expansion is being done for tab or auto completions. Returned completions may have the
|
|
|
|
/// wildcard as a prefix instead of a match.
|
|
|
|
const FOR_COMPLETIONS = 1 << 3;
|
|
|
|
/// Only match files that are executable by the current user.
|
|
|
|
const EXECUTABLES_ONLY = 1 << 4;
|
|
|
|
/// Only match directories.
|
|
|
|
const DIRECTORIES_ONLY = 1 << 5;
|
|
|
|
/// Generate descriptions, stored in the description field of completions.
|
|
|
|
const GEN_DESCRIPTIONS = 1 << 6;
|
|
|
|
/// Un-expand home directories to tildes after.
|
|
|
|
const PRESERVE_HOME_TILDES = 1 << 7;
|
|
|
|
/// Allow fuzzy matching.
|
|
|
|
const FUZZY_MATCH = 1 << 8;
|
|
|
|
/// Disallow directory abbreviations like /u/l/b for /usr/local/bin. Only applicable if
|
|
|
|
/// fuzzy_match is set.
|
|
|
|
const NO_FUZZY_DIRECTORIES = 1 << 9;
|
|
|
|
/// Allows matching a leading dot even if the wildcard does not contain one.
|
|
|
|
/// By default, wildcards only match a leading dot literally; this is why e.g. '*' does not
|
|
|
|
/// match hidden files.
|
|
|
|
const ALLOW_NONLITERAL_LEADING_DOT = 1 << 10;
|
|
|
|
/// Do expansions specifically to support cd. This means using CDPATH as a list of potential
|
|
|
|
/// working directories, and to use logical instead of physical paths.
|
|
|
|
const SPECIAL_FOR_CD = 1 << 11;
|
|
|
|
/// Do expansions specifically for cd autosuggestion. This is to differentiate between cd
|
|
|
|
/// completions and cd autosuggestions.
|
|
|
|
const SPECIAL_FOR_CD_AUTOSUGGESTION = 1 << 12;
|
|
|
|
/// Do expansions specifically to support external command completions. This means using PATH as
|
|
|
|
/// a list of potential working directories.
|
|
|
|
const SPECIAL_FOR_COMMAND = 1 << 13;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-03-26 23:23:05 +08:00
|
|
|
/// Character representing a home directory.
|
|
|
|
pub const HOME_DIRECTORY: char = char_offset(EXPAND_RESERVED_BASE, 0);
|
|
|
|
/// Character representing process expansion for %self.
|
|
|
|
pub const PROCESS_EXPAND_SELF: char = char_offset(EXPAND_RESERVED_BASE, 1);
|
|
|
|
/// Character representing variable expansion.
|
|
|
|
pub const VARIABLE_EXPAND: char = char_offset(EXPAND_RESERVED_BASE, 2);
|
|
|
|
/// Character representing variable expansion into a single element.
|
|
|
|
pub const VARIABLE_EXPAND_SINGLE: char = char_offset(EXPAND_RESERVED_BASE, 3);
|
|
|
|
/// Character representing the start of a bracket expansion.
|
|
|
|
pub const BRACE_BEGIN: char = char_offset(EXPAND_RESERVED_BASE, 4);
|
|
|
|
/// Character representing the end of a bracket expansion.
|
|
|
|
pub const BRACE_END: char = char_offset(EXPAND_RESERVED_BASE, 5);
|
|
|
|
/// Character representing separation between two bracket elements.
|
|
|
|
pub const BRACE_SEP: char = char_offset(EXPAND_RESERVED_BASE, 6);
|
|
|
|
/// Character that takes the place of any whitespace within non-quoted text in braces
|
|
|
|
pub const BRACE_SPACE: char = char_offset(EXPAND_RESERVED_BASE, 7);
|
|
|
|
/// Separate subtokens in a token with this character.
|
|
|
|
pub const INTERNAL_SEPARATOR: char = char_offset(EXPAND_RESERVED_BASE, 8);
|
|
|
|
/// Character representing an empty variable expansion. Only used transitively while expanding
|
|
|
|
/// variables.
|
|
|
|
pub const VARIABLE_EXPAND_EMPTY: char = char_offset(EXPAND_RESERVED_BASE, 9);
|
2023-03-11 10:47:41 +08:00
|
|
|
|
|
|
|
const _: () = assert!(
|
2023-03-26 23:23:05 +08:00
|
|
|
EXPAND_RESERVED_END as u32 > VARIABLE_EXPAND_EMPTY as u32,
|
2023-03-11 10:47:41 +08:00
|
|
|
"Characters used in expansions must stay within private use area"
|
|
|
|
);
|
|
|
|
|
2023-04-18 18:53:32 +08:00
|
|
|
#[derive(Copy, Clone, Eq, PartialEq)]
|
|
|
|
pub enum ExpandResultCode {
|
|
|
|
/// There was an error, for example, unmatched braces.
|
|
|
|
error,
|
|
|
|
/// Expansion succeeded.
|
|
|
|
ok,
|
|
|
|
/// Expansion was cancelled (e.g. control-C).
|
|
|
|
cancel,
|
|
|
|
/// Expansion succeeded, but a wildcard in the string matched no files,
|
|
|
|
/// so the output is empty.
|
|
|
|
wildcard_no_match,
|
|
|
|
}
|
|
|
|
|
|
|
|
/// These are the possible return values for expand_string.
|
|
|
|
pub struct ExpandResult {
|
|
|
|
// todo!
|
|
|
|
pub result: ExpandResultCode,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl PartialEq<ExpandResultCode> for ExpandResult {
|
|
|
|
fn eq(&self, other: &ExpandResultCode) -> bool {
|
|
|
|
self.result == *other
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-03-26 23:23:05 +08:00
|
|
|
/// The string represented by PROCESS_EXPAND_SELF
|
|
|
|
#[widestrs]
|
|
|
|
pub const PROCESS_EXPAND_SELF_STR: &wstr = "%self"L;
|
2023-04-18 18:53:32 +08:00
|
|
|
|
|
|
|
/// expand_one is identical to expand_string, except it will fail if in expands to more than one
|
|
|
|
/// string. This is used for expanding command names.
|
|
|
|
///
|
|
|
|
/// \param inout_str The parameter to expand in-place
|
|
|
|
/// \param flags Specifies if any expansion pass should be skipped. Legal values are any combination
|
|
|
|
/// of skip_cmdsubst skip_variables and skip_wildcards
|
|
|
|
/// \param ctx The parser, variables, and cancellation checker for this operation. The parser may be
|
|
|
|
/// null. \param errors Resulting errors, or nullptr to ignore
|
|
|
|
///
|
|
|
|
/// \return Whether expansion succeeded.
|
|
|
|
#[allow(unused_variables)]
|
|
|
|
pub fn expand_one(
|
|
|
|
s: &mut WString,
|
|
|
|
flags: ExpandFlags,
|
|
|
|
ctx: &OperationContext,
|
|
|
|
errors: Option<&mut ParseErrorList>,
|
|
|
|
) -> bool {
|
|
|
|
todo!()
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Expand a command string like $HOME/bin/cmd into a command and list of arguments.
|
|
|
|
/// Return the command and arguments by reference.
|
|
|
|
/// If the expansion resulted in no or an empty command, the command will be an empty string. Note
|
|
|
|
/// that API does not distinguish between expansion resulting in an empty command (''), and
|
|
|
|
/// expansion resulting in no command (e.g. unset variable).
|
|
|
|
/// If \p skip_wildcards is true, then do not do wildcard expansion
|
|
|
|
/// \return an expand error.
|
|
|
|
#[allow(unused_variables)]
|
|
|
|
pub fn expand_to_command_and_args(
|
|
|
|
instr: &wstr,
|
|
|
|
ctx: &OperationContext,
|
|
|
|
out_cmd: &mut WString,
|
|
|
|
out_args: Option<&Vec<WString>>,
|
|
|
|
errors: &mut ParseErrorList,
|
|
|
|
skip_wildcards: bool,
|
|
|
|
) -> ExpandResult {
|
|
|
|
todo!()
|
|
|
|
}
|
2023-04-09 20:33:20 +08:00
|
|
|
|
|
|
|
/// Perform tilde expansion and nothing else on the specified string, which is modified in place.
|
|
|
|
///
|
|
|
|
/// \param input the string to tilde expand
|
|
|
|
pub fn expand_tilde(input: &mut WString, _vars: &dyn Environment) {
|
|
|
|
if input.chars().next() == Some('~') {
|
|
|
|
input.replace_range(0..1, wstr::from_char_slice(&[HOME_DIRECTORY]));
|
|
|
|
todo!();
|
|
|
|
// expand_home_directory(input, vars);
|
|
|
|
}
|
|
|
|
}
|