The official fish documentation makes no mention of how `string split`
treats empty tokens, e.g. splitting 'key1##key2' on '#' or (more
confusingly) splitting '/path' on '/'. With this commit, `string split`
now has an option to exclude zero-length substrings from the resulting
array with a new `--no-empty/-n`. The default behavior of preserving
empty entries is kept so as to avoid breakage.
The two unicode glyphs used to represent missing new lines and redacted
characters for secure entry are both not present in the glyph tables of
the default font under Windows (Consolas and Lucida Console), use an
alternative glyph instead.
The "return" symbol is replaced with a pilcrow (¶) and the "redacted
character" symbol is replaced with a bullet (•). Both of these are
well-defined in almost all fonts as they're very old symbols. This
change only takes place if -DWSL is supplied by the build toolchain.
Note: this means a Windows SSH client connecting to a fish remote
instance on a non-Windows machine will still use the (unavailable)
default glyphs instead.
The newly added `:` command is implemented as a function (to avoid
increasing complexity by making it a builtin), but it is saved to a path
that does not match its filename (since its name is somewhat of a
special character that might cause problems during installation).
Directly probing the `colon` function for autoload causes `:` to be
correctly loaded, so doing just that after function paths are loaded
upon startup.
This is a hack since the CPP code shouldn't really be aware of
individual functions, perhaps there is a better way of doing this.
Fixes an issue introduced in 4414d5c888
where functions loaded from custom directories are not detected as being
valid for purposes of determining whether or not completions should be
called.
Work around #4810 by retrieving localizations at runtime to avoid issues
possibly caused by inserting into the static unordered_map during static
initialization.
Closes#810.
Line continuations (i.e. escaped new lines) now make sense again. With
the smart pipe support (pipes continue on to next line) recently added,
this hack to have continuations ignore comments makes no sense.
This is valid code:
```fish
echo hello |
# comment here
tr -d 'l'
```
this isn't:
```fish
echo hello | \
# comment here
tr -d 'l'
```
Reverts @snnw's 318daaffb2Closes#2928. Closes#2929.
From the discussion in #3802, handling spaces within braces more
gracefully. Leading and trailing whitespace that isn't quoted or escaped
is stripped, whitespace in the middle is preserved. Any whitespace
encountered within expansion tokens is treated as a single space,
similar to how programming languages that don't hard break tokens/quotes
on line endings would.
The value is not electrified or tied and is read-only. It isn't cached
in the get_hostname_identifier() function as the ENV_GLOBAL $hostname
will cache it for its duration.
The behavior of `gethostname` in case of an insufficient buffer is
library and version dependent. Work around this by using a big enough
buffer then truncating the output to our desired max length.
The 0th index of the array was tested inside the loop instead of just
once outside it.
Also explain `input_mapping_is_match` control code behavior and
reasoning and simplify control flow.
Drops the % notation for process expansion. The existing notation was a
mess and expanded jobs, process ids, and process names via dark magic.
With this change, % is no longer a special character and can be used
unescaped with impunity.
The variables %self and %last, referring to fish's own pid and the pid
of the last backgrounded job respectively, have been replaced with $pid
and $last_pid. These are read-only variables, protected against being
redefined by the user.
Author's note: I would have personally preferred $fish_pid instead of
$pid but since we debated changing $version to $fish_version and then
reverted that change (with much acrimony), it makes no sense to break
with that precedent here. Additionally, $fish_last_pid is quite wordy.
Closes#4230. Closes#1202.
When number is infinite, not a number, larger than LONG_MAX or smaller
than LONG_MIN, print a corresponding error and return STATUS_CMD_ERROR.
This should fix the worst of the problems, by at least making them clear.
Fixes#4479.
Fixes#4768.
This allows prompts to react to $COLUMNS by e.g. omitting some parts.
We still fallback to a ">" prompt if that's still not short enough,
but now the user has a way of making a nicer prompt.
Fixes#904.
Fixes#4381.
If the head is not a valid, existent command, do not load and run custom
completion sources. This applies to both the autosuggestion provider and
manual user completions. File-based completions will still be offered.
Supersedes #4782 and #4783. Closes#4783. Closes#4782. Closes#2365.
This promotes "and" and "or" from a type of statement to "job
decorators," as a possible prefix on a job. The point is to rationalize
how they interact with && and ||.
In the new world 'and' and 'or' apply to a entire job conjunction, i.e.
they have "lower precedence." Example:
if [ $age -ge 0 ] && [ $age -le 18 ]
or [ $age -ge 75 ] && [ $age -le 100 ]
echo "Child or senior"
end
This should speed things up on slower PCs given that the vast majority
of shell commands are simple jobs consisting of a single command without
any pipelines, in which case there's no need for a keepalive process at
all. Applies to WSL only.
As a temporary workaround for the behavior described in
Microsoft/WSL#2997 wherein WSL does not correctly assign the spawned
child its own PID as its PGID, explicitly set the PGID for the newly
spawned process.
This now reports "TOO_MANY_ARGS" instead of no error (and triggering
an assertion).
We might want to add a new error type or report the missing operator
before, but this is okay for now.
This turns a bunch of ifs on their heads.
We often see this pattern in te:
```c
if (s->type != SOME_TYPE) {
// error handling
} else {
// normal code
}
```
Only, since we want to return the first error, we do
```c
if (s->type == SOME_TYPE) {
// normal code
} else if (s->type != TOK_ERROR) {
// Add a new error - if it already has type error
// this should already be handled.
}
```
One big issue is the comma operator, that means arity-1 functions can
take an arbitrary number of arguments. E.g.
```fish
math "sin(5,9)"
```
will return the value of sin for _9_, since this is read as "5 COMMA
9".
This enables some limited use of arguments for wrapping completions. The
simplest example is that complete gco -w 'git checkout' now works like
you would want: `gco <tab>` now invokes git's completions with the
`checkout` argument prepended.
Fixes#1976
Previously, in
ls ^a bcd
(with "^" as the cursor), kill-word would delete the "a" and then go
on, remove the space and the "bcd".
With this, it will only kill the "a".
Fixes#4747.
This is part of an effort to improve fish's Unicode handling. This commit
attempts to grapple with the fact that, certain characters (principally
emoji) were considered to have a wcwidth of 1 in Unicode 8, but a width of
2 in Unicode 9.
The system wcwidth() here cannot be trusted; terminal emulators do not
respect it. iTerm2 even allows this to be set in preferences.
This commit introduces a new function is_width_2_in_Uni9_but_1_in_Uni8() to
detect characters of version-ambiguous width. For these characters, it
returns a width guessed based on the value of TERM_PROGRAM and
TERM_VERSION, defaulting to 1. This value can be overridden by setting the
value of a new variable fish_emoji_width (presumably either to 1 or 2).
Fixes#4539, #2652.
`argparse`, `read`, `set`, `status`, `test` and `[` now can't be used
as function names anymore.
This is because (except for `test` and `[`) there is no way to wrap these properly, so any
function called that will be broken anyway.
For `test` (and `[`), there is nothing that can be added and there
have been confused users who created a function that then broke
everything.
Fixes#3000.
Prior to this fix, each redirection type was a separate token_type.
Unify these under a single type TOK_REDIRECT and break the redirection
type out into a new sub-type redirection_type_t.
Prior to this the tokenizer ran "one ahead", where tokenizer_t::next()
would in fact return the last-parsed token. Switch to parsing on demand
instead of running one ahead; this is simpler and prepares for tokenizer
changes.
Turns out the process-exit is only ever used in conjunction with
`%self`. Make that explicit by just adding a new "fish_exit" event,
and deprecate the general process-exit machinery.
Fixes#4700.
The previous attempt to support newlines after pipes changed the lexer to
swallow newlines after encountering a pipe. This has two problems that are
difficult to fix:
1. comments cannot be placed after the pipe
2. fish_indent won't know about the newlines, so it will erase them
Address these problems by removing the lexer behavior, and replacing it
with a new parser symbol "optional_newlines" allowing the newlines to be
reflected directly in the fish grammar.
Prior to this fix, if you attempt to complete from inside a quote and the
completion contained an entity that cannot be represented inside quotes
(i.e. \n \r \t \b), the result would be a broken mess of quotes. Rewrite
the implementation so that it exits the quotes, emits the correct unquoted
escape, and then re-enters the quotes.
Properly escape literal tildes in tab completion results. Currently we
always escape tildes in unquoted arguments; in the future we may escape
only leading tildes.
Fixes#2274
Prior to this fix, autoloads like function and completion autoloads
would check their path variable (like fish_function_path) on every
autoload request. Switch to invalidating it in response to the variable
changing.
This improves time on a microbenchmark:
for i in (seq 50000)
setenv test_env val$i
end
from ~11 seconds to ~6.5 seconds.
The job control functions were a bit messy, in particular
`set_child_group`'s name would imply that all it does is set the child
group, but in reality it used to set the child group (via `setpgid`),
set the job's pgrp if it hasn't been set, and possibly assign control of
the terminal to the newly-created job.
These have been split into separate functions. Now `set_child_group`
does just (and only) that, `maybe_assign_terminal` might assign the
terminal to the new pgrp, and `on_process_created` is used to set the
job properties the first time an external process is created. This might
also speed things up (but probably not noticeably) as there are no more
repeated calls to `getpgrp()` if JOB_CONTROL is not set.
Additionally, this closes#4715 by no longer unconditionally calling
`setpgid` on all new processes, including those created by `posix_spawn`
which does not need this since the child's pgrep is set at in the
arguments to that API call.
This switches function execution from the function's source code to
its stored node and pstree. This means we no longer have to re-parse
the function every time we execute it.
The idea is that we can return the shared pointer directly, avoiding
lots of annoying little getter functions that each need to take locks.
It also helps to pull together the data structures used to initialize
functions versus store them.
This concerns block nodes with redirections, like
begin ... end | grep ...
Prior to this fix, we passed in a pointer to the node. Switch to passing
in the tnode and parsed source ref. This improves type safety and better
aligns with the function-node plans.
Prior to this fix, functions stored a string representation of their
contents. Switch them to storing a parsed source reference and the
tnode of the contents. This is part of an effort to avoid reparsing
a function's contents every time it executes.
Add a fish-specific wrapper around std::mutex that records whether it is
locked in a bool. This is to make ASSERT_IS_LOCKED() simpler (it can just
check the boolean instead of relying on try_lock) which will make Coverity
Scan happier.
Some details: Coverity Scan was complaining about an apparent double-unlock
because it's unaware of the semantics of try_lock(). Specifically fish
asserts that a lock is locked by asserting that try_lock fails; if it
succeeds fish prints an error and then unlocks the lock (so as not to leave
it locked). This unlock is of course correct, but it confused Coverity Scan.
Use wcstring/string instead of a character array. The variable
`term_env` was not being freed before the function exited.
Fixes defect 7520324 in coverity scan.
keepalive processes are typically killed by the main shell process.
However if the main shell exits the keepalive may linger. In WSL
keepalives are used more often, and the lingering keepalives are both
leaks and prevent the tests from finishing.
Have keepalives poll for their parent process ID and exit when it
changes, so they can clean themselves up. The polling frequency can be
low.
Have WSL use a keepalive whenever the first process is external.
This works around the fact that WSL prohibits setting an exited
process as the group leader.
When the pager wants to use the full screen to show many options, it reserves
space at the top to see the command. Previously it pretended the command was a
prompt and engaged the prompt layout mechanism to compute these lines. Instead
let's juts count newlines since escape sequences within commands are very rare.
There were several issues with the way that the include tests for curses.h
were being done that were ultimately causing fish to use the headers from
ncurses but link against curses on platforms that provide an actual
libcurses.so that isn't just a symlink to libncurses.so
In particular, the old code was first testing for curses's cureses.h and then
falling back to libncurses's implementation of the same - but that logic was
reversed when it came to including term.h, in which case it was testing for
the ncurses term.h and falling back to the curses.h header. Long story short,
while cmake will link against libcurses.so if both libcurses.so and
libncurses.so are present (unless CURSES_NEED_NCURSES evaluates to TRUE, but
that makes ncurses a hard requirement), but we were brining in some of the
defines from the ncurses headers, causing SIGSEGV panics when fish ultimately
tried to access variables that weren't exported or were mapped to undefined
areas of memory in the other library.
Additionally it is an error to include termios.h prior to including the plain
Jane curses.h (not ncurses/curses.h), causing errors about unimplemented types
SGTTY/chtype. So far as I can tell, both curses.h and ncurses/curses.h pull in
termios.h themselves so it shouldn't even be necessary to manually include it,
but I have just moved its #include below that of curses.h
This special cases expansion of $history variables, so that slicing
history no longer needs to construct the entire history array. Speedup
is around 100x in my test.
Fixes#4650
Prior to this fix, if the user typed normal characters while the
completion pager was shown, it would begin searching. This feature was
not well liked, so we are going to instead just append the characters as
normal and disable paging. Control-S can be used to toggle the search
field.
Fixes#2249
try_get_child() was taking the address of a reference; clang was thereby
assuming it could not be null and so was dropping the null check. Ensure
we do not dereference a null pointer.
Fixes#4678
This was a symbol that represented either an argument or a redirection.
This was only used as part of argument_or_redirection_list.
It's simpler to just have these types be alternatives in the list type.
Some dotfile users like to add directories to PATH that point at
non-existent directories (because those directories exist on other
machines). Stop warning in that case, unless those directories contain
a colon, in which case it's probably a user error.
Changed cd completion to differentiate between cd autosuggest and cd tab
completion. cd autosuggest will find deepest unique hierarchy and cd tab
completion will not.
Issue #4402
This untangles the CMake versioning issues (I hope) as discussed in #4626.
Note most of the advice found on the Internet about how to inject git
versions into CMake is just wrong.
The behavior we want is to unconditionally run the script
build_tools/git_version_gen.sh at build time (i.e. when you invoke ninja or
make, and not when you invoke cmake, which is build system generation time).
This script is careful to only update the FISH-BUILD-VERSION-FILE if the
contents have changed, to avoid spurious rebuilding dependencies of
FISH-BUILD-VERSION-FILE. Assuming the git version hasn't changed, the script
will run, but not update FISH-BUILD-VERSION-FILE, and therefore
fish_version.o will not have to be rebuilt.
This might normally rebuild more than is necessary even if the timestamp is
not updated, because ninja computes the dependency chain ahead of time. But
Ninja also supports the 'restat' option for just this case, and CMake is rad
and exposes this via BYPRODUCTS. So mark FISH-BUILD-VERSION-FILE as a
byproduct and make the script always update a dummy file
(fish-build-version-witness.txt). Note this is the use case for which
BYPRODUCTS is designed.
We also have fish_version.cpp #include "FISH-BUILD-VERSION-FILE", and do a
semi-silly thing and make FISH-BUILD-VERSION-FILE valid C++ (so there's just
one version file). This means we have to filter out the quotes in other
cases..
This reverts commit 25839b8c36.
This was an attempt to simplify the version generation, but it
computed the version at build sytem generation time rather than
at build time, requiring another run of CMake to update it.
Correctly generate FISH_BUILD_VERSION for use in fish_version.h/cpp and
fish.pc to allow `fish --version` and `echo $version` to work again.
Not needing the same convoluted measures used by Makefile builds to
prevent the regeneration of the fish version file when it hasn't
changed.
Purposely created a new `cmake_git_version_gen.sh` file so that the old
`git_version_gen.sh` remains compatible with the existing Makefile build
script. Same reason why `fish.pc.in` was not modified to use a lowercase
variable name to match the CMAKE variable of the same name.
Closes#4626
A large portion of time was spent constructing strings and passing
them to debug(). Turn debug into a macro so that the strings are only
constructed if they're going to be printed.