Files
nushell/crates/nu-command/src/default_context.rs
Bahex 8771872d86 Add path self command for getting absolute paths to files at parse time (#14303)
Alternative solution to:
- #12195 

The other approach:
- #14305

# Description
Adds ~`path const`~ `path self`, a parse-time only command for getting
the absolute path of the source file containing it, or any file relative
to the source file.

- Useful for any script or module that makes use of non nuscript files.
- Removes the need for `$env.CURRENT_FILE` and `$env.FILE_PWD`.
- Can be used in modules, sourced files or scripts.

# Examples

```nushell
# ~/.config/nushell/scripts/foo.nu
const paths = {
    self: (path self),
    dir: (path self .),
    sibling: (path self sibling),
    parent_dir: (path self ..),
    cousin: (path self ../cousin),
}

export def main [] {
    $paths
}
```

```nushell
> use foo.nu
> foo
╭────────────┬────────────────────────────────────────────╮
│ self       │ /home/user/.config/nushell/scripts/foo.nu  │
│ dir        │ /home/user/.config/nushell/scripts         │
│ sibling    │ /home/user/.config/nushell/scripts/sibling │
│ parent_dir │ /home/user/.config/nushell                 │
│ cousin     │ /home/user/.config/nushell/cousin          │
╰────────────┴────────────────────────────────────────────╯
```


Trying to run in a non-const context
```nushell
> path self
Error:   × this command can only run during parse-time
   ╭─[entry #1:1:1]
 1 │ path self 
   · ─────┬────
   ·      ╰── can't run after parse-time
   ╰────
  help: try assigning this command's output to a const variable
```

Trying to run in the REPL i.e. not in a file
```nushell
> const foo = path self
Error:   × Error: nu:🐚:file_not_found
  │ 
  │   × File not found
  │    ╭─[entry #3:1:13]
  │  1 │ const foo = path self
  │    ·             ─────┬────
  │    ·                  ╰── Couldn't find current file
  │    ╰────
  │ 
   ╭─[entry #3:1:13]
 1 │ const foo = path self
   ·             ─────┬────
   ·                  ╰── Encountered error during parse-time evaluation
   ╰────
```

# Comparison with #14305
## Pros
- Self contained implementation, does not require changes in the parser.
- More concise usage, especially with parent directories.

---------

Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com>
2024-12-06 08:19:08 -06:00

482 lines
10 KiB
Rust

use crate::*;
use nu_protocol::engine::{EngineState, StateWorkingSet};
pub fn add_shell_command_context(mut engine_state: EngineState) -> EngineState {
let delta = {
let mut working_set = StateWorkingSet::new(&engine_state);
macro_rules! bind_command {
( $( $command:expr ),* $(,)? ) => {
$( working_set.add_decl(Box::new($command)); )*
};
}
// If there are commands that have the same name as default declarations,
// they have to be registered before the main declarations. This helps to make
// them only accessible if the correct input value category is used with the
// declaration
// Database-related
// Adds all related commands to query databases
#[cfg(feature = "sqlite")]
add_database_decls(&mut working_set);
// Charts
bind_command! {
Histogram
}
// Filters
#[cfg(feature = "rand")]
bind_command! {
Shuffle
}
bind_command! {
All,
Any,
Append,
Chunks,
Columns,
Compact,
Default,
Drop,
DropColumn,
DropNth,
Each,
Enumerate,
Every,
Filter,
Find,
First,
Flatten,
Get,
GroupBy,
Headers,
Insert,
IsEmpty,
IsNotEmpty,
Interleave,
Items,
Join,
SplitBy,
Take,
Merge,
Move,
TakeWhile,
TakeUntil,
Last,
Length,
Lines,
ParEach,
ChunkBy,
Prepend,
Range,
Reduce,
Reject,
Rename,
Reverse,
Select,
Skip,
SkipUntil,
SkipWhile,
Sort,
SortBy,
SplitList,
Tee,
Transpose,
Uniq,
UniqBy,
Upsert,
Update,
Values,
Where,
Window,
Wrap,
Zip,
};
// Misc
bind_command! {
Panic,
Source,
Tutor,
};
// Path
bind_command! {
Path,
PathBasename,
PathSelf,
PathDirname,
PathExists,
PathExpand,
PathJoin,
PathParse,
PathRelativeTo,
PathSplit,
PathType,
};
// System
#[cfg(feature = "os")]
bind_command! {
Complete,
External,
Exec,
NuCheck,
Sys,
SysCpu,
SysDisks,
SysHost,
SysMem,
SysNet,
SysTemp,
SysUsers,
UName,
Which,
};
// Help
bind_command! {
Help,
HelpAliases,
HelpExterns,
HelpCommands,
HelpModules,
HelpOperators,
HelpEscapes,
};
// Debug
bind_command! {
Ast,
Debug,
DebugInfo,
DebugProfile,
Explain,
Inspect,
Metadata,
MetadataAccess,
MetadataSet,
TimeIt,
View,
ViewFiles,
ViewIr,
ViewSource,
ViewSpan,
};
#[cfg(all(feature = "os", windows))]
bind_command! { RegistryQuery }
#[cfg(all(
feature = "os",
any(
target_os = "android",
target_os = "linux",
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd",
target_os = "macos",
target_os = "windows"
)
))]
bind_command! { Ps };
// Strings
bind_command! {
Char,
Decode,
Encode,
DecodeHex,
EncodeHex,
DecodeBase32,
EncodeBase32,
DecodeBase32Hex,
EncodeBase32Hex,
DecodeBase64,
EncodeBase64,
DetectColumns,
Parse,
Split,
SplitChars,
SplitColumn,
SplitRow,
SplitWords,
Str,
StrCapitalize,
StrContains,
StrDistance,
StrDowncase,
StrEndswith,
StrExpand,
StrJoin,
StrReplace,
StrIndexOf,
StrLength,
StrReverse,
StrStats,
StrStartsWith,
StrSubstring,
StrTrim,
StrUpcase,
Format,
FormatDate,
FormatDuration,
FormatFilesize,
};
// FileSystem
#[cfg(feature = "os")]
bind_command! {
Cd,
Ls,
UMkdir,
Mktemp,
UMv,
UCp,
Open,
Start,
Rm,
Save,
Touch,
UTouch,
Glob,
Watch,
};
// Platform
#[cfg(feature = "os")]
bind_command! {
Ansi,
AnsiLink,
AnsiStrip,
Clear,
Du,
Input,
InputList,
InputListen,
IsTerminal,
Kill,
Sleep,
Term,
TermSize,
TermQuery,
Whoami,
};
#[cfg(all(unix, feature = "os"))]
bind_command! { ULimit };
// Date
bind_command! {
Date,
DateHumanize,
DateListTimezones,
DateNow,
DateToRecord,
DateToTable,
DateToTimezone,
};
// Shells
bind_command! {
Exit,
};
// Formats
bind_command! {
From,
FromCsv,
FromJson,
FromMsgpack,
FromMsgpackz,
FromNuon,
FromOds,
FromSsv,
FromToml,
FromTsv,
FromXlsx,
FromXml,
FromYaml,
FromYml,
To,
ToCsv,
ToJson,
ToMd,
ToMsgpack,
ToMsgpackz,
ToNuon,
ToText,
ToToml,
ToTsv,
Upsert,
Where,
ToXml,
ToYaml,
};
// Viewers
bind_command! {
Griddle,
Table,
};
// Conversions
bind_command! {
Fill,
Into,
IntoBool,
IntoBinary,
IntoCellPath,
IntoDatetime,
IntoDuration,
IntoFloat,
IntoFilesize,
IntoInt,
IntoRecord,
IntoString,
IntoGlob,
IntoValue,
SplitCellPath,
};
// Env
bind_command! {
ExportEnv,
LoadEnv,
SourceEnv,
WithEnv,
ConfigNu,
ConfigEnv,
ConfigMeta,
ConfigReset,
};
// Math
bind_command! {
Math,
MathAbs,
MathAvg,
MathCeil,
MathFloor,
MathMax,
MathMedian,
MathMin,
MathMode,
MathProduct,
MathRound,
MathSqrt,
MathStddev,
MathSum,
MathVariance,
MathLog,
};
// Bytes
bind_command! {
Bytes,
BytesLen,
BytesStartsWith,
BytesEndsWith,
BytesReverse,
BytesReplace,
BytesAdd,
BytesAt,
BytesIndexOf,
BytesCollect,
BytesRemove,
BytesBuild
}
// Network
#[cfg(feature = "network")]
bind_command! {
Http,
HttpDelete,
HttpGet,
HttpHead,
HttpPatch,
HttpPost,
HttpPut,
HttpOptions,
Port,
}
bind_command! {
Url,
UrlBuildQuery,
UrlSplitQuery,
UrlDecode,
UrlEncode,
UrlJoin,
UrlParse,
}
// Random
#[cfg(feature = "rand")]
bind_command! {
Random,
RandomBool,
RandomChars,
RandomDice,
RandomFloat,
RandomInt,
RandomUuid,
RandomBinary
};
// Generators
bind_command! {
Cal,
Seq,
SeqDate,
SeqChar,
Generate,
};
// Hash
bind_command! {
Hash,
HashMd5::default(),
HashSha256::default(),
};
// Experimental
bind_command! {
IsAdmin,
};
// Removed
bind_command! {
LetEnv,
DateFormat,
};
// Stor
#[cfg(feature = "sqlite")]
bind_command! {
Stor,
StorCreate,
StorDelete,
StorExport,
StorImport,
StorInsert,
StorOpen,
StorReset,
StorUpdate,
};
working_set.render()
};
if let Err(err) = engine_state.merge_delta(delta) {
eprintln!("Error creating default context: {err:?}");
}
// Cache the table decl id so we don't have to look it up later
let table_decl_id = engine_state.find_decl("table".as_bytes(), &[]);
engine_state.table_decl_id = table_decl_id;
engine_state
}