* Hoist `for` loop control var to enclosing scope
It should be possible to reference the last value assigned to a `for`
loop control var when the loop terminates. This makes it easier to detect
if we broke out of the loop among other things. This change makes fish
`for` loops behave like most other shells.
Fixes#1935
* Remove redundant line
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.
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.
Commit f872f25f introduced a freed memory access regression on line 460
of env.cpp, where an environment variable was converted to a temporary
string, the .c_str() address of which was stored while the string
temporary was destroyed.
This commit keeps a reference to the original string lying around so
that the c_str() pointer does not point to freed memory.
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.
Since we are including XXHash32/64 anyway for the wchar_t* hashing,
we might as well use it.
Use arch-specific hash size and xxhash for all wcstring hashing
Instead of using XXHash64 for all platforms, use the 32-bit version
when running on 32-bit platforms where XXHash64 is significantly slower
than XXHash32 (and the additional precision will not be used).
Additionally, manually specify wcstring_hash as hashing method for
non-const wcstring unordered_set/map instances (the const varieties
don't have an in-library hash and so already use our xxhash-based
specialization when calling std::hash<const wcstring>).
commit 50f414a45d58fcab664ff662dd27befcfa0fdd95
Author: Mahmoud Al-Qudsi <mqudsi@neosmart.net>
Date: Sat Aug 19 13:43:35 2017 -0500
Converted file_id_t set to unordered_set with custom hash
commit 83ef2dd7cc1bc3e4fdf0b2d3546d6811326cc3c9
Author: Mahmoud Al-Qudsi <mqudsi@neosmart.net>
Date: Sat Aug 19 13:43:14 2017 -0500
Converted remaining set<wcstring> to unordered_set<wcstring>
commit 053da88f933f27505b3cf4810402e2a2be070203
Author: Mahmoud Al-Qudsi <mqudsi@neosmart.net>
Date: Sat Aug 19 13:29:21 2017 -0500
Switched function sets to unordered_set
commit d469742a14ac99599022a9258cda8255178826b5
Author: Mahmoud Al-Qudsi <mqudsi@neosmart.net>
Date: Sat Aug 19 13:21:32 2017 -0500
Converted list of modified variables to an unordered set
commit 5c06f866beeafb23878b1a932c7cd2558412c283
Author: Mahmoud Al-Qudsi <mqudsi@neosmart.net>
Date: Sat Aug 19 13:15:20 2017 -0500
Convert const_string_set_t to std::unordered_set
As it is a readonly-list of raw character pointer strings (not
wcstring), this necessitated the addition of a hashing function since
the C++ standard library does not come with a char pointer hash
function.
To that end, a zlib-licensed [0] port of the excellent, lightweight
XXHash family of 32- and 64-bit hashing algorithms in the form of a C++
header-only include library has been included. XXHash32/64 is pretty
much universally the fastest hashing library for general purpose
applications, and has been thoroughly vetted and is used in countless
open source projects. The single-header version of this library makes it
a lot simpler to include in the fish project, and the license
compatibility with fish' GPLv2 and the zero-lib nature should make it an
easy decision.
std::unordered_set brings a massive speedup as compared to the default
std::set, and the further use of the fast XXHash library to provide the
string hashing should make all forms of string lookups in fish
significantly faster (to a user-noticeable extent).
0: http://create.stephan-brumme.com/about.html
commit 30d7710be8f0c23a4d42f7e713fcb7850f99036e
Author: Mahmoud Al-Qudsi <mqudsi@neosmart.net>
Date: Sat Aug 19 12:29:39 2017 -0500
Using std::unordered_set for completions backing store
While the completions shown to the user are sorted, their storage in
memory does not need to be since they are re-sorted before they are
shown in completions.cpp.
commit 695e83331d7a60ba188e57f6ea0d9b6da54860c6
Author: Mahmoud Al-Qudsi <mqudsi@neosmart.net>
Date: Sat Aug 19 12:06:53 2017 -0500
Updated is_loading to use unordered_set
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.
The `react_to_variable_change()` function is called whenever a fish var
is set. Even as a consequence of statements like `for x in a b c`. It is
therefore critical that that function be as fast as possible. Especially
when setting the var doesn't have any side-effects which is true something
like 99.9999% of the time.
This change reduces the overhead of `react_to_variable_change()` to
unmeasurable levels. Making the synthetic benchmark in issue #4341
36% faster.
Fixes#4341
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.
My previous change to eliminate `class var_entry_t` caused me to notice
that `env_get()` turned a set but empty var into a missing var. Which
is wrong. Fixing that brought to light several other pieces of code that
were wrong as a consequence of the aforementioned bug.
Another step to fixing issue #4200.
This is the first step to implementing issue #4200 is to stop subclassing
env_var_t from wcstring. Not too surprisingly doing this identified
several places that were incorrectly treating env_var_t and wcstring as
interchangeable types. I'm not talking about those places that passed
an env_var_t instance to a function that takes a wcstring. I'm talking
about doing things like assigning the former to the latter type, relying
on the implicit conversion, and thus losing information.
We also rename `env_get_string()` to `env_get()` for symmetry with
`env_set()` and to make it clear the function does not return a string.
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
When executing a function, local-exported (`set -lx`) variables
previously were not accessible at all. This is weird e.g. in case of
aliases, since
```fish
set -lx PAGER cat
git something # which will call $PAGER
```
would not work if `git` were a function, even if that ends up calling
`command git`.
Now, we copy these variables, so functions get a local-exported copy.
```fish
function x
echo $var
set var wurst
echo $var
end
set -lx var banana
x # prints "banana" and "wurst"
echo $var # prints "banana"
```
One weirdness here is that, if a variable is both local and global,
the local-copy takes precedence:
```fish
set -gx var banana
set -lx var pineapple
echo $var # prints "pineapple"
x # from above, prints "pineapple" and "wurst"
echo $var # still prints "pineapple"
set -el var # deletes local version
echo $var # "banana" again
```
I don't think there is any more consistent way to handle this - the
local version is the one that is accessed first, so it should also be
written to first.
Global-exported variables are _not_ copied, instead they still offer
full read-write access.
In the rare case that we don't inherit $HOME _and_ can't read it from
/etc/passwd, this makes it so instead of triggering an assert() $HOME
is set to the empty list.
Tilde-expansion expands to nothing in such a case (and a string-empty
$HOME), `cd` errors out.
Fixes#4229.
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
Don't import the bash history if the user has specified that a non-default
fish history file should be used. Also, rename the var that specifies
the fish history session ID from `FISH_HISTFILE` to `FISH_HISTORY`.
Fixes#4172
Using the FISH_HISTFILE variable will let people customise the session
to use for the history file. The resulting history file is:
`$XDG_DATA_HOME/fish/name_history`
Where `name` is the name of the session. The default value is `fish`
which results in the current history file.
If it's set to an empty string, the history will not be stored to a
file.
Fixes#102
Switch from null terminated arrays to `wcstring_list_t` for lists of
special env var names. Rename `list_contains_string` to `contains` and
modify the latter interface to not rely on a `#define`.
Rename `list_contains_string()` to `contains()` and eliminate the
current variadic implementation. Update all callers of the removed
version to use the string list version.
There are at least three env vars describing a sequence of paths to be
searched where an empty path element is implicitly equivalent to ".".
This change converts the implicit "." to explicit whenever the variable
is imported or set. This makes the variable much easier to use in fish
scripts.
Fixes#3914
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.