This includes the "." in what `path extension` prints.
This allows distinguishing between an empty extension (just `.`) and a
non-existent extension (no `.` at all).
These are short flags for "--perm=read" and "--type=link" and such.
Not every type or permission has a shorthand - we don't want "-s" for
"suid". So just the big three each get one.
This is theoretically sound, because a path can only be PATH_MAX - 1
bytes long, so at least the PATH_MAXest byte needs to be a NULL.
The one case this could break is when something has a NULL-output mode
but doesn't bother printing the NULL for only one path, and that path
contains a newline. So we leave --null-in there, to force it on.
This adds a "path" builtin that can handle paths.
Implemented so far:
- "path filter PATHS", filters paths according to existence and optionally type and permissions
- "path base" and "path dir", run basename and dirname, respectively
- "path extension PATHS", prints the extension, if any
- "path strip-extension", prints the path without the extension
- "path normalize PATHS", normalizes paths - removing "/./" components
- and such.
- "path real", does realpath - i.e. normalizing *and* link resolution.
Some of these - base, dir, {strip-,}extension and normalize operate on the paths only as strings, so they handle nonexistent paths. filter and real ignore any nonexistent paths.
All output is split explicitly, so paths with newlines in them are
handled correctly. Alternatively, all subcommands have a "--null-input"/"-z" and "--null-output"/"-Z" option to handle null-terminated input and create null-terminated output. So
find . -print0 | path base -z
prints the basename of all files in the current directory,
recursively.
With "-Z" it also prints it null-separated.
(if stdout is going to a command substitution, we probably want to
skip this)
All subcommands also have a "-q"/"--quiet" flag that tells them to skip output. They return true "when something happened". For match/filter that's when a file passed, for "base"/"dir"/"extension"/"strip-extension" that's when something about the path *changed*.
Filtering
---------
`filter` supports all the file*types* `test` has - "dir", "file", "link", "block"..., as well as the permissions - "read", "write", "exec" and things like "suid".
It is missing the tty check and the check for the file being non-empty. The former is best done via `isatty`, the latter I don't think I've ever seen used.
There currently is no way to only get "real" files, i.e. ignore links pointing to files.
Examples
--------
> path real /bin///sh
/usr/bin/bash
> path extension foo.mp4
mp4
> path extension ~/.config
(nothing, because ".config" isn't an extension.)
This teaches `--on-signal SIGINT` (and by extension `trap cmd SIGINT`)
to work properly in scripts, not just interactively. Note any such
function will suppress the default behavior of exiting. Do this for
SIGTERM as well.
* New -n flag for string join command.
This is an argument that excludes empty result items. Fixes#8351
* New documentation for string-join.
The new argument --no-empty was added at string-join manpage.
* New completions for the new -n flag for string join.
* Remove the documentation of the new -n flag of string join0
The reason to remove this new argument in the join0 is that this flag basically doesn't make any difference in the join0.
* Refactor the validation for the string join.
The string join command was using the length of the argument, this commit changes the validation to use the empty function.
* Revert #4b56ab452
The reason for the revert is thath the build broke on the ubuntu in the Github actions.
* Revert #e72e239a1
The reason the compilation on GitHub broke is that the test was weird, it didn't even run it, Common CI systems are typically very very resource-constrained.
* Resolve conflicts in the string-join.rst.
* Resolve conflicts in the "string-join.rst".
commit #1242d0fd7 not fixed all conflicts.
* Implement fish_wcstod_underscores
* Add fish_wcstod_underscores unit tests
* Switch to using fish_wcstod_underscores in tinyexpr
* Add tests for math builtin underscore separator functionality
* Add documentation for underscore separators for math builtin
* Add a changelog entry for underscore numeric separators
Includes harmonizing the display of options and arguments, standardising
terminology, using the envvar directive more broadly, adding help options to all
commands that support them, simplifying some language, and tidying up multiple
formatting issues.
string documentation is not changed.
man(1) uses lowercase placeholders but we usually don't. Additionally,
the new synopsis autoformatting only recognizes placeholders if they
are uppercase. Use uppercase for all placeholders.
Recent synopsis changes move from literal code blocks to
[RST line blocks]. This does not translate well to HTML: it's not
rendered in monospace, so aligment is lost. Additionally, we don't
get syntax highlighting in HTML, which adds differences to our code
samples which are highlighted.
We hard-wrap synopsis lines (like code blocks). To align continuation
lines in manpages we need [backslashes in weird places]. Combined with
the **, *, and `` markup, it's a bit hard to get the alignment right.
Fix these by moving synopsis sources back to code blocks and compute
HTML syntax highlighting and manpage markup with a custom Sphinx
extension.
The new Pygments lexer can tokenize a synopsis and assign the various
highlighting roles, which closely matches fish's syntax highlighing:
- command/keyword (dark blue)
- parameter (light blue)
- operator like and/or/not/&&/|| (cyan)
- grammar metacharacter (black)
For manpage output, we don't project the fish syntax highlighting
but follow the markup convention in GNU's man(1):
bold text type exactly as shown.
italic text replace with appropriate argument.
To make it easy to separate these two automatically, formalize that
(italic) placeholders must be uppercase; while all lowercase text is
interpreted literally (so rendered bold).
This makes manpages more consistent, see string-join(1) and and(1).
Implementation notes:
Since we want manpage formatting but Sphinx's Pygments highlighing
plugin does not support manpage output, add our custom "synopsis"
directive. This directive parses differently when manpage output is
specified. This means that the HTML and manpage build processes must
not share a cache, because the parsed doctrees are cached. Work around
this by using separate cache locations for build targets "sphinx-docs"
(which creates HTML) and "sphinx-manpages". A better solution would
be to only override Sphinx's ManualPageBuilder but that would take a
bit more code (ideally we could override ManualPageWriter but Sphinx
4.3.2 doesn't really support that).
---
Alternative solution: stick with line blocks but use roles like
:command: or :option: (or custom ones). While this would make it
possible to produce HTML that is consistent with code blocks (by adding
a bit of CSS), the source would look uglier and is harder to maintain.
(Let's say we want to add custom formatting to the [|] metacharacters
in HTML. This is much easier with the proposed patch.)
---
[RST line blocks]: https://docutils.sourceforge.io/docs/ref/rst/restructuredtext.html#line-blocks
[backslashes in weird places]: https://github.com/fish-shell/fish-shell/pull/8626#discussion_r782837750
This corrects what looks like wrong alignment of some synopsis lines.
(I think the alignment is not a bad idea but it makes us do more
manual work, maybe we can automate that in future. We still need to
figure out how to translate it to HTML.)
"man -l build/user_doc/man/man1/history.1" before:
string match [-a | --all] [-e | --entire] [-i | --ignore-case]
[-r | --regex] [-n | --index] [-q | --quiet] [-v | --invert]
PATTERN [STRING…]
and after:
string match [-a | --all] [-e | --entire] [-i | --ignore-case]
[-r | --regex] [-n | --index] [-q | --quiet] [-v | --invert]
PATTERN [STRING…]
Also make the lines align the same way in the RST source by carefully
choosing the position of the backslash. I'm not sure why we used
two backslashes per line. Use only one; this gives us no choice
of where to put it so both source and man page output are aligned.
Change tabs to spaces to make the alignment in the source work.
The ellipsis is a grammar metacharacter, just like the []()|.
Write *FOO*… instead of *FOO…*, so the ellipsis is not underlined
in the man page. Not super sure about this one.
This matches the style in man(1) (except that we use the … ligature).
A previous iteration did the reverse (never use a space before the
ellipsis). That would be a smaller change.
We use plural "*OPTIONS*" more often than "*OPTION*...", so let's do
that everywhere.
In some other places where we do have an ellipsis, make sure to use
singular, since the ellipsis already means repetition. This change
is incomplete, and I'm not sure if this is worth it, since it's
subjective, so I might drop it.
Correct the grammar by moving the options after the command argument.
Also group the -c/--command and -p/--path pairs, to convey that the
short and long variants are equivalent.
While at it, consolidate the -C/--do-complete forms, like we usually
do.
One synopsis misrenders as
set [options] VARIABLE*[*INDICES]… VALUES…
Add a missing backslash to fix that. Also go back to uppercase
because I'm not sure why this was changed to lowercase.
Finally, remove the spurious ellipsis after VARIABLE[INDICES].
This element cannot be repeated. Multiple index values and ranges
can be specified but that's already implied by the plural INDICES.
For alteration we usually use "(a | b)", not "{a | b}".
While at it, instead of writing 4/6 subcommands in one line, write them
on separate lines, so it's very obvious that all these are separate
subcommands. We mainly use the (a | b) syntax for long/short options.
The -- is not special here and we don't mention it in other synopses.
It was originally added for a good reason in 98449fec5 (fix `math`
regression, 2017-07-14), along this addition to math.rst:
> You should always place a `--` flag separator before the expression. [...]
However, since 56d913453 (Cache math expressions, 2017-08-24) that
line was changed to
> You don't need to use `--` before the expression even if it begins with a minus sign [...]
Previously, when we got an unknown option with --ignore-unknown, we
would increment woptind but still try to read the same contents.
This means in e.g.
```
argparse -i h -- -ooo -h
```
The `-h` would also be skipped as an option, because after the first
`-o` getopt reads the other two `-o` and skips that many options.
This could be handled more extensively in wgetopt, but the simpler fix
is to just skip to the next argv entry once we have an unknown option
- there's nothing more we can do with it anyway!
Additionally, document this and clearly explain that we currently
don't transform the option.
Fixes#8637
Use the remaining_to_disclose count to determine if all completions
are shown (allows consistent behavior between short and long completion
lists).
Closes#8485
Currently,
set -q --unpath PATH
simply ignores the "--unpath" bit (and same for "--path").
This changes it, so just like exportedness you can check pathness.
Unless we use "complete --require-parameter", we must say "-w32",
not "-w 32", because the second "32" is a positional argument.
Notably, old options do not have this behavior, which is a bit weird,
see #8465
Taken from a discussion in #8459
* fish_key_reader: Simplify default output
It now only prints the bind statement. Timing information and such is
relegated to a separate "verbose" mode.
* Adjust fish_key_reader docs
* Adjust tests
Unlike in other shells, for-loops do not set $status if
1. the loop count is zero, or if
2. the loop body consists of only commands like "set" that don't
set $status.
POSIX for-loops always set an exit status (they set 0 if no loop
iterations). Following that would be awkward because it would add a
lot of complexity in combination with the 2 special cases above.
Document that "for" behaves the same as "set": it will pass through
existing $status, and also the last child's $status.
See the discussion in #8409
Unfortunately, currently :program: doesn't link to the program's page.
So we use the old-school :ref: again where we should link, i.e. for
everything that's not the program the current page is about.
Fixes#8438
Documents like fish-tutorial don't need the NAME portion below.
(they also shoudln't be in section 1! These should be section 7,
they aren't for programs.)
the manpage writer will skip NAME if given an empty sstring as
the description.
--
FISH-TUTORIAL(1) fish-shell FISH-TUTORIAL(1)
NAME
fish-tutorial - fish-shell tutorial
This fixes the indentation problem for the SYNOPSIS section by not
inserting the :: literal block. Format it the same way Sphinx does
their own manpages for commands.
Use more semantic markup, like :command:, so that commands are
highlighted in the man pages.
Split by sentence to give `man` a chance to ascertain lines.
Long-term, it should be possible to teach Sphinx to turn :command:s
into references and get us automatic links to articles for matching
cmds/*.
* commandline: Add --is-valid option to query whether it's syntactically complete
This means querying when the commandline is in a state that it could
be executed. Because our `execute` bind function also inserts a
newline if it isn't.
One case that's not handled right now: `execute` also expands
abbreviations, those can technically make the commandline invalid
again.
Unfortunately we have no real way to *check* without doing the
replacement.
Also since abbreviations are only available in command position when
you _execute_ them the commandline will most likely be valid.
This is enough to make transient prompts work:
```fish
function reset-transient --on-event fish_postexec
set -g TRANSIENT 0
end
function maybe_execute
if commandline --is-valid
set -g TRANSIENT 1
commandline -f repaint
else
set -g TRANSIENT 0
end
commandline -f execute
end
bind \r maybe_execute
```
and then in `fish_prompt` react to $TRANSIENT being set to 1.
* Add `set --function`
This makes the function's scope available, even inside of blocks. Outside of blocks it's the toplevel local scope.
This removes the need to declare variables locally before use, and will probably end up being the main way variables get set.
E.g.:
```fish
set -l thing
if condition
set thing one
else
set thing two
end
```
could be written as
```fish
if condition
set -f thing one
else
set -f thing two
end
```
Note: Many scripts shipped with fish use workarounds like `and`/`or`
instead of `if`, so it isn't easy to find good examples.
Also, if there isn't an else-branch in that above, just with
```fish
if condition
set -f thing one
end
```
that means something different from setting it before! Now, if
`condition` isn't true, it would use a global (or universal) variable of
te same name!
Some more interesting parts:
Because it *is* a local scope, setting a variable `-f` and
`-l` in the toplevel of a function ends up the same:
```fish
function foo2
set -l foo bar
set -f foo baz # modifies the *same* variable!
end
```
but setting it locally inside a block creates a new local variable
that shadows the function-scoped variable:
```fish
function foo3
set -f foo bar
begin
set -l foo banana
# $foo is banana
end
# $foo is bar again
end
```
This is how local variables already work. "Local" is actually "block-scoped".
Also `set --show` will only show the closest local scope, so it won't
show a shadowed function-level variable. Again, this is how local
variables already work, and could be done as a separate change.
As a fun tidbit, functions with --no-scope-shadowing can now use this to set variables in the calling function. That's probably okay given that it's already an escape hatch (but to be clear: if it turns out to problematic I reserve the right to remove it).
Fixes#565
Currently, if a "return" is given outside of a function, we'd just
throw an error.
That always struck me as a bit weird, given that scripts can also
return a value.
So simply let "return" outside also exit the script, kinda like "exit"
does.
However, unlike "exit" it doesn't quit an interactive shell - it seems
weird to have "return" do that as well. It sets $status, so it can be
used to quickly set that, in case you want to test something.
For builtins that have the same name as common commands, it might not
be entirely obvious that there is another page.
So, for those builtins, we add a note, but only in the man pages.
(exception is true and false because the note would be longer than the
page, and it's fridging true and false)
Fixes#8077.
`fish_config theme`:
- `list` to list all available themes (files in the two theme
directories - either the web_config/themes one or
~/.config/fish/themes!)
- `show` to show select (or all) themes right in the terminal - this
starts another fish that reads the theme file and prints the sample
text, manually colored
- `choose` to load a theme *now*, setting the variables globally
- `save` to load a theme and save the variables universally
- `dump` to write the current theme in .theme format (to stdout)
- `demo` to display the current theme
* string: Allow `collect --no-empty` to avoid empty ellision
Currently we still have that issue where
test -n (thing | string collect)
can return true if `thing` doesn't print anything, because the
collected argument will still be removed.
So, what we do is allow `--no-empty` to be used, in which case we
print one empty argument.
This means
test -n (thing | string collect -n)
can now be safely used.
"no-empty" isn't the best name for this flag, but string's design
really incentivizes reusing names, and it's not *terrible*.
* Switch to `--allow-empty`
`--no-empty` does the exact opposite for `string split` and split0.
Since `-a`/`--allow-empty` already exists, use it.
This introduces two functions to
- toggle a process prefix, used for adding "sudo"
- add a job suffix, used for adding "&| less"
Not sure if they are very useful; we'll see.
Closes#7905
The file is called "config.fish", not "init.fish". We'll call it
"configuration" now.
"Initialization" might be slightly more precise, but in an irritating
way.
Also some wording improvements to the section. In particular we now
mention config.fish *early*, before the whole shebang.
Prior to this change, a function with an on-job-exit event handler must be
added with the pgid of the job. But sometimes the pgid of the job is fish
itself (if job control is disabled) and the previous commit made last_pid
an actual pid from the job, instead of its pgroup.
Switch on-job-exit to accept any pid from the job (except fish itself).
This allows it to be used directly with $last_pid, except that it now
works if job control is off. This is implemented by "resolving" the pid to
the internal job id at the point the event handler is added.
Also switch to passing the last pid of the job, rather than its pgroup.
This aligns better with $last_pid.
It's a bit weird to *have* to fire up a browser to get fish_config to
choose a prompt.
So this adds a `prompt` subcommand to `fish_config`:
- `fish_config prompt list` shows all the available prompt names
- `fish_config prompt show` demos the available sample prompts
- `fish_config prompt choose` sources a prompt
- `fish_config prompt save` makes the choice permanent
A bare `fish_config` or `fish_config browse` opens the web UI.
Part of #3625.
TODO: This shows the right prompt on a new line. Showing it in-line is awkward
to do because we'd have to move it to the right.
This prints a description of the "host". Currently that's
`(chroot:debianchroot) $USER@$hostname`
with the chroot part when needed.
This also switches the default and terlar prompts to use it, the other
prompts have slightly different coloring or logic here.
* math: Make function parentheses optional
It's a bit annoying to use parentheses here because that requires
quoting or escaping.
This allows the parens to be omitted, so
math sin pi
is the same as
math 'sin(pi)'
Function calls have the lowest precedence, so
math sin 2 + 6
is the same as
math 'sin(2 + 6)'
* Add more tests
* Add a note to the docs
* even moar docs
Moar docca
* moar tests
Call me Nikola Testla
Unlike links, these are checked by sphinx and it complains if they
don't match.
Also they have a better chance of doing something useful in outputs
other than html.
After commit 6dd6a57c60, 3 remaining
builtins were affected by uint8_t overflow: `exit`, `return`, and
`functions --query`.
This commit:
- Moves the overflow check from `builtin_set_query` to `builtin_run`.
- Removes a conflicting int -> uint8_t conversion in `builtin_return`.
- Adds tests for the 3 remaining affected builtins.
- Simplifies the wording for the documentation for `set --query`.
- Does not change documentation for `functions --query`, because it does
not state the exit code in its API.
- Updates the CHANGELOG to reflect the change to all builtins.
builtin_set_query returns the number of missing variables. Because the
return value passed to the shell is an 8-bit unsigned integer, if the
number of missing variables is a multiple of 256, it would overflow to 0.
This commit saturates the return value at 255 if there are more than 255
missing variables.
This goes to a separate file because that makes option parsing easier
and allows profiling both at the same time.
The "normal" profile now contains only the profile data of the actual
run, which is much more useful - you can now profile a function by
running
fish -C 'source /path/to/thing' --profile /tmp/thefunction.prof -c 'thefunction'
and won't need to filter out extraneous information.
Currently binding `exit` to a key checks too late that it's exitted,
so it leaves the shell hanging around until the user does an execute
or similar.
As I understand it, the `exit` builtin is supposed to only exit the
current "thread" (once that actually becomes a thing), and the
bindings would probably run in a dedicated one, so the simplest
solution here is to just add an `exit` bind function.
Fixes#7604.
It was always a bit ridiculous that argparse required `X-longflag` if
that "X" short flag was never actually used anywhere.
Since the short letter is for getopt's benefit, we can hack around
this with our old friend: Unicode Private Use Areas.
We have a counter, starting at 0xE000 and going to 0xF8FF, that counts
up for all options that don't have a short flag and provides one. This
gives us up to 6400 long-only options.
6.4K should be enough for everybody.
When building from source, there is a warning:
../doc_src/cmds/string-match.rst:13: WARNING: Inline emphasis
start-string without end-string.
One fix appears to be putting a space after the epmhasized 'n' character,
e.g., `*n* th` instead of `*n*th`.
E.g. if we do `string match -q`, and we find a match, nothing about
the input can change anything, so we quit early.
This is mainly useful for performance, but it also allows `string`
with `-q` to be used with infinite input (e.g. `yes`).
Alternative to #7495.
Currently a bit limited, unfortunately printf's `%a` specifier is
absolutely unreadable.
So we add `hex` and `octal` with `0x` and `0` prefixes respectively,
and also take a number but currently only allow 16 and 8.
The output is truncated to integer, so scale values other than 0 are
invalid and 0 is implied.
The docs mention this may change.
This switch is no longer necessary when only one command is given.
Internally completions are stored separately for each command,
so we only every print one command name per "complete" line anyway.
If the padding is not divisible by the char's width without remainder,
we pad the remainder with spaces, so the total width of the output is correct.
Also add completions, changelog entry, adjust documentation, add examples
with emoji and some tests. Apply some minor style nitpicks and avoid extra
allocations of the input strings.
Technically the equivalence would be something like
string length -q $str
test -n (string join \n -- $str | string collect)
To handle when str has multiple empty strings;
but quoting is easier to remember and enough for most practical purposes.
This reads any additional positional arguments given to `fish -c` into
$argv.
We don't handle the first argument specially (as `$0`) as that's confusing and
doesn't seem very useful.
Fixes#2314.
This allows
bind -k backspace suppress-autosuggestion or backward-delete-char
To remove the suggestion on the first press and then delete
chars.
Note: This requires that we then don't reenable suggestions
immediately afterwards. Currently we don't after deletion.
Fixes#1419.
The person reading this is "you". It's completely okay and sounds
better to address them directly.
When we're talking about OS users or users of fish script the reader
writes, "the user" is still okay.
[ci skip]
The case for symlinked directories being duplicated a lot isn't there,
but there *is* a usecase for adding the symlink rather than the
target, and that's homebrew.
E.g. homebrew installs ruby into /usr/local/Cellar/ruby/2.7.1_2/bin,
and links to it from /usr/local/opt/ruby/bin. If we add the target, we
would miss updates.
Having path entries that point to the same location isn't a big
problem - it's a path lookup, so it takes a teensy bit longer. The
canonicalization is mainly so paths don't end up duplicated via weird
spelling and so relative paths can be used.
Taken from GNU realpath, this one makes realpath not resolve symlinks.
It still makes paths absolute and handles duplicate and trailing
slashes.
(useful in fish_add_path)
Currently, completions have to be specified like
```fish
complete -c foo -l opt
```
while
```fish
complete foo -l opt
```
just complains about there being too many arguments.
That's kinda useless, so we just assume if there is one left-over
argument that it's meant to be the command.
Theoretically we could also use *all* the arguments as commands to
complete, but that seems unlikely to be what the user wants.
(I don't think multi-command completions really happen)
Currently only `complete` will list completions, and it will list all
of them.
That's a bit ridiculous, especially since `complete -c foo` just does nothing.
So just make `complete -c foo` list all the completions for `foo`.
Previously, when a command wasn't found, fish would emit the
"fish_command_not_found" *event*.
This was annoying as it was hard to override (the code ended up
checking for a function called `__fish_command_not_found_handler`
anyway!), the setup was ugly,
and it's useless - there is no use case for multiple command-not-found handlers.
Instead, let's just call a function `fish_command_not_found` if it
exists, or print the default message otherwise.
The event is completely removed, but because a missing event is not an error
(MEISNAE in C++-speak) this isn't an issue.
Note that, for backwards-compatibility, we still keep the default
handler function around even tho the new one is hard-coded in C++.
Also, if we detect a previous handler, the new handler just calls it.
This way, the backwards-compatible way to install a custom handler is:
```fish
function __fish_command_not_found_handler --on-event fish_command_not_found
# do a little dance, make a little love, get down tonight
end
```
and the new hotness is
```fish
function fish_command_not_found
# do the thing
end
```
Fixes#7293.
Now command, jobs, type, abbr, builtin, functions and set take `-q` to
query for existence, but the long option is inconsistent.
The first three use `--quiet`, the latter use `--query`. Add `--query`
to the first three, but keep `--quiet` around.
Fixes#7276.
Instead of informing the bell character (hex 07), the example was using
an escaped \ followed by x07.
$ echo \\x07
\x07
$ echo \x07
$ echo \x07 | od -a
0000000 bel nl
0000002
$
* docs: Use \u instead of \\u
Instead of informing the Unicode character 慡, this example was using an
escaped \ followed by u6161.
$ echo \\u6161
\u6161
$ echo \u6161
慡
Before:
$ string escape --style=var 'a1 b2'\\u6161 | string unescape --style=var
a1 b2\u6161
Now:
$ string escape --style=var 'a1 b2'\u6161 | string unescape --style=var
a1 b2慡
Just as `math "bitand(5,3)"` and `math "bitor(6,2)"`.
These cast to long long before doing their thing,
so they truncate to an integer, producing weird results with floats.
That's to be expected because float representation is *very*
different, and performing bitwise operations on floats feels quite useless.
Fixes#7281.
Was: "parameter expansion takes before expressions are evaluated."
Now: "parameter expansion happens before expressions are evaluated."
I suspect the original intent was to use "takes place," but I see "happens" as less idiomatic and therefore may benefit non-English-native users.
Also return the number of failed files.
I decided to *just* print the filenames (newline-separated because
NULLs are annoying here) to make it easier to deal with.
See #7251.