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, 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.
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
The type cached_esc_sequences_t caches escape sequences, and is tasked
with finding an escape sequence that prefixes a given string. Before
this fix, it did so by storing the lengths of cached escape sequences,
and searching for substrings of that length. The new implementation
instead stores all cached escape sequences in a sorted vector, and uses
binary search to find the shortest escape sequence that is a prefix of
the input. This is a substantial simplification that also reduces
allocations.
This eliminates the "missing" notion of env_var_t. Instead
env_get returns a maybe_t<env_var_t>, which forces callers to
handle the possibility that the variable is missing.
maybe_t is an implementation of the Maybe/Optional type, allowing
for an optional value to be stored. This will enable a more
principled approach for functions that return values or failure,
such as env_get.
This commit backs out certain optimizations around setting environment
variables, and replaces them with move semantics. env_set accepts a
list, by value, permitting callers to use std::move to transfer
ownership.
cherry-picked from krader1961/fish-shell commit b69df4fe72
Fixes#4353 (regression in indexing of history contents) and introduces
new unit tests to catch bad $history indexing in the future.
Make setting fish vars more efficient by avoiding creating a
wcstring_list_t for the case where we're setting one value. For the case
where we're passing a list of values swap it with the list in the var
rather than copying it. This makes the benchmark in #4200 approximately
6% faster.
No longer using RAII wrappers around pthread_mutex_t and pthread_cond_t
in favor of the C++11 std::mutex, std::recursive_mutex, and
std::condition_variable data types.
Internally fish should store vars as a vector of elements. The current
flat string representation is a holdover from when the code was written
in C.
Fixes#4200
Make the `env_var_t::missing_var()` object a singleton rather than a
dynamically constructed object. This requires some discipline in its use
since C++ doesn't directly support immutable objects. But it is slightly
more efficient and helps identify code that incorrectly mutates `env_var_t`
objects that should not be modified.
It's bugged me forever that the scope is the second arg to `env_get()`
but not `env_set()`. And since I'll be introducing some helper functions
that wrap `env_set()` now is a good time to change the order of its
arguments.
This makes command substitutions impose the same limit on the amount
of data they accept as the `read` builtin. It does not limit output of
external commands or builtins in other contexts.
Fixes#3822
Rewrite the `abbr` function to store each abbreviation in a separate
variable. This greatly improves the efficiency. For the common case
it is 5x faster. For pathological cases it is upwards of 100x faster.
Most people should be able to unconditionally define abbreviations in
their config.fish without a noticable slow down.
Fixes#4048
Fish 2.6.0 introduced a regression that keeps setting
`fish_escape_delay_ms` as a uvar from working. This also fixes a related
problem: callbacks generated from the initial loading of universal vars
were not being acted on.
Fixes#4196
This fixes a stupid bug in my previous commit to standardize on a new
`list_to_array_val()` function. This adds a unit test to keep this from
regressing.
This is the first step in implementing a better abstraction for handling
fish script vars in the C++ code. It implements a new function (with two
signatures) to provide a standard method for construct the flag string
representation of a fish script array.
Partial fix for #4200
This implements `status is-breakpoint` that returns true if the current
shell prompt is displayed in the context of a `breakpoint` command.
This also fixes several bugs. Most notably making `breakpoint` a no-op if
the shell isn't interactive. Also, typing `breakpoint` at an interactive
prompt should be an error rather than creating a new nested debugging
context.
Partial fix for #1310
This started out as a refactoring to eliminate the lint warnings. Adding
unit tests revealed the current implementation does not behave as
implied. So this is a complete rewrite of the implementation. With the
addition of unit tests so that it doesn't break in the future and anyone
who thinks this new version behaves wrong can update the unit tests to
help ensure we're testing for the correct behavior.
Fixes#4027
This changes all of the builtins to behave like `string` to return
STATUS_INVALID_ARGS (121) if the args passed to the command don't make
sense. Also change several of the builtins to use the existing symbols
(e.g., STATUS_CMD_OK and STATUS_CMD_ERROR) rather than hardcoded "0"
and "1" for consistency and to make it easier to find such values in
the future.
Fixes#3985
This primarily replaces "STATUS_BUILTIN_OK" with "STATUS_CMD_OK" and
"STATUS_BUILTIN_ERROR" with "STATUS_CMD_ERROR". That is because we want
to make it clear these status codes are applicable to fish functions as
well as builtins. Future changes will make it easier to use these
symbols and values in functions.
There should be just one place that calls `setupterm()`. While refactoring
the code I also decided to not make initializing the curses subsystem a
fatal error. We now try two fallback terminal names ("ansi" and "dumb")
and if those can't be used we still end up with a usable shell.
Fixes#3850
I recently upgraded the software on my macOS server and was dismayed to
see that cppcheck reported a huge number of format string errors due to
mismatches between the format string and its arguments from calls to
`assert()`. It turns out they are due to the macOS header using `%lu`
for the line number which is obviously wrong since it is using the C
preprocessor `__LINE__` symbol which evaluates to a signed int.
I also noticed that the macOS implementation writes to stdout, rather
than stderr. It also uses `printf()` which can be a problem on some
platforms if the stream is already in wide mode which is the normal case
for fish.
So implement our own `assert()` implementation. This also eliminates
double-negative warnings that we get from some of our calls to
`assert()` on some platforms by oclint.
Also reimplement the `DIE()` macro in terms of our internal
implementation.
Rewrite `assert(0 && msg)` statements to `DIE(msg)` for clarity and to
eliminate oclint warnings about constant expressions.
Fixes#3276, albeit not in the fashion I originally envisioned.
We now are stingier with taking history file locks - if the lock
is held too long we may just break it. But the current file save
architecture holds the lock for the duration of the save. It also
has some not-quite-right checks that can cause spurious failures in
the history stress test.
Reimplement the history save to retry. Rather than holding the lock,
rewrite the file to a temporary location and then take the lock. If
the history file has changed, start all over.
This is going to be slower under contention, but the advantage is that
the lock is only held for a brief period (stat + rename) rather than
across calls to write().
Some updated logic also fixes spurious failures that were easy to observe
when tsan was enabled. These failures were due to failing to check if the
file at the path was the same file we opened.
The next step is to move the history file saving to a background thread
to reduce the chances of it impacting user's typing.
Commit ab189a75 introduced a regression where we stop breaking out
of loops in response to a child death via a signal. Fix that regression.
Also introduces a test to help ensure we don't regress in the future.
Fixes#3780
Previously we would try to walk all the blocks (from within the
signal handler!) and mark them as skipped. Stop doing that, it's
wildly unsafe.
Also rationalize how the skip flag is set per block. Remove places
that shouldn't set it (e.g. break and continue shouldn't set skip
on the loop block).
We should never use stdio functions that use stdout implicitly. Saving a
few characters isn't worth the inconsistency. Too, using the forms such
as `fwprintf()` which take an explicit stream makes it easier to find
the places we write to stdout versus stderr.
Fixes#3728
On some platforms, notably GNU libc, you cannot mix narrow and wide
stdio functions on a stream like stdout or stderr. Doing so will drop
the output of one or the other. This change makes all output to the
stderr stream consistently use the wide forms.
This change also converts some fprintf(stderr,...) calls to debug()
calls where appropriate.
Fixes#3692
I noticed that universal variable tests were failing on Cygwin and
Dragonfly BSD. The failures were because we are attempting to verify the
correct behavior of mechanisms that are known to be broken on those
platforms. There are still uvar test failures on those platforms with
this change but they are due to actual problems rather than bugs in the
tests.
Fixes#3587
Using `\e` is clearer and shorter than `\x1b`. It's also consistent with how
we write related control chars; e.g., we don't write `\x0a` we write '\n'.
Tests that exercise error paths may result in output to
stderr. This may make it look like the test failed when it did
not. Introduce should_suppress_stderr_for_tests() to suppress
this output so the test output looks clean.
This commit fixes a bug which causes that
fish -c ')'; echo $status
("Illegal command name" error) returns 0. This is inconsistent with
e.g. when trying to run non-existent command:
fish -c 'invalid-command'; echo $status
("Unknown command" error) which correctly returns 127.
A new status code,
STATUS_ILLEGAL_CMD = 123
is introduced - which is returned whenever the 'Illegal command name *'
message is printed.
This commit also adds a test which checks if valid commands return 0,
while commands with illegal name return status code 123.
Fixes#3606.
The `test` builtin currently has unexpected behavior with respect to
expressions such as `'' -eq 0`. That currently evaluates to true with a
return status of zero. This change addresses that oddity while also
ensuring that other unusual strings (e.g., numbers with leading and
trailing whitespace) are handled consistently.
Fixes#3346
The existing code is inconsistent, and in a couple of cases wrong, about
dealing with strings that are not valid ints. For example, there are
locations that call wcstol() and check errno without first setting errno
to zero. Normalize the code to a consistent pattern. This is mostly to
deal with inconsistencies between BSD, GNU, and other UNIXes.
This does make some syntax more liberal. For example `echo $PATH[1 .. 3]`
is now valid due to uniformly allowing leading and trailing whitespace
around numbers. Whereas prior to this change you would get a "Invalid
index value" error. Contrast this with `echo $PATH[ 1.. 3 ]` which was
valid and still is.
My previous change removed one place where is_wchar_ucs2() was used and
replaced it with compile time tests. This change does the same for the
other uses.
On Cygwin there are two narrowing conversions at line 931 in
src/fish_tests.cpp due to the code assuming a wchar_t is four bytes.
Obviously that's wrong but only became an issue with the pending change to
switch to C++11. The problematic values aren't actually used on Windows
because the tests that would use them are bypassed if is_wchar_ucs2()
returns true. This change predicates that code on a compile time rather
than a run time test.
Earlier lint cleanups overlooked a couple of modules because on macOS at
the moment oclint ignores them. I noticed this when I ran `make lint-all`
on Ubuntu.
When performing fuzzy completion, if a directory segment is
valid, then don't consider it for a fuzzy match even if
the literal match produces no results.
Fixes#3211
Prior to this fix, when performing completions, we would prepend
the wildcard to the resulting files. When doing fuzzy completions,
we would take some wildcard segment, attempt to locate it in the
final completion, and then replace it with our fuzzy-matched directory.
With this fix, we pass along the "resolved so far" path, and prepend
that instead of doing "surgery" on the completion. This simplifies the
logic.
Fixes#3185