Prior to this fix, fish would invalidate the exported variable list
whenever an exported variable changes. However we soon will not have a
single "exported variable list." If a global variable changes, it is
infeasible to find all exported variable lists and invalidate them.
Switch to a new model where we store a list of generation counts. Every
time an exported variable changes, the node gets a new generation. If the
current generation list does not match the cached one, then we know that
our exported variable list is stale.
This makes the following changes:
1. Events in background threads are executed in those threads, instead of
being silently dropped
2. Blocked events are now per-parser instead of global
3. Events are posted in builtin_set instead of within the environment stack
The last one means that we no longer support event handlers for implicit
sets like (example) argv. Instead only the `set` builtin (and also `cd`)
post variable-change events.
Events from universal variable changes are still not fully rationalized.
When setting a variable without a specified scope, we should give priority
to an existing local or global above an existing universal variable with
the same name.
In 16fd780484 there was a regression that
made universal variables have priority.
Fixes#5883
Prior to this fix, a function_block stored a process_t, which was only used
when printing backtraces. Switch this to an array of arguments, and make
various other cleanups around null terminated argument arrays.
This runs build_tools/style.fish, which runs clang-format on C++, fish_indent on fish and (new) black on python.
If anything is wrong with the formatting, we should fix the tools, but automated formatting is worth it.
This was a sort of side channel that was only used to propagate redraws
after universal variable changes. We can eliminate it and handle these
more directly.
env_scoped_t lives between environment_t and env_stack_t.
It represents the read-only logic of env_stack_t and will be used to back
the new environment snapshot implementation.
Prior to this change, fish used a global flag to decide if we should check
for changes to universal variables. This flag was then checked at arbitrary
locations, potentially triggering variable updates and event handlers for
those updates; this was very hard to reason about.
Switch to triggering a universal variable update at a fixed location,
after running an external command. The common case is that the variable
file has not changed, which we can identify with just a stat() call, so
this is pretty cheap.
When popping a scope from the environment stack, we currently do a lot of
nonsense like looking for changed curses variables. We want to centralize
this in env_stack_t so that it can be migrated to the env_dispatch logic.
Move this logic up one level in preparation for doing that.
This new file is supposed to encapsulate all of the logic around
reacting to variable changes, as opposed to the environment core.
This is to help break up the env.cpp monolith.
This switches env_var_t to be an immutable value type, and stores its
contents via a shared_ptr. This eliminates string copying when fetching
env_var_t values.
Mostly related to usage _(L"foo"), keeping in mind the _
macro does a wcstring().c_str() already.
And a smattering of other trivial micro-optimizations certain
to not help tangibly.
Since Unicode 9, the width of some characters changed to 2.
Depending on the system, it might have support for it, or it might
not.
Instead of hardcoding specific glibc etc versions, we check what the
system wcwidth says to "😃", U+1F603 "Grinning Face With Big Eyes".
The intention is to, in most cases, make setting $fish_emoji_width
unnecessary, but since it sets the "guessed_emoji_width", that variable still takes precedence if it is set.
Unfortunately this approach has some caveats:
- It relies on the locale being set to a unicode-supporting one.
(C.UTF-8 is unfortunately not standard, so we can't use it)
- It relies on the terminal's wcwidth having unicode9 support IFF the
system wcwidth does.
This is like #5722, but at runtime.
The additional caveat is that we don't try to achieve a unicode
locale, but since we re-run the heuristic when the locale changes (and
we try to get a unicode locale), we should still often get the correct
value.
Plus if you use a C locale and your terminal still displays emoji,
you've misconfigured your system.
Fixes#5722.
Prior to this fix, an "event" was used as both a predicate on which events
to match, and also as the event itself. Re-express these concepts
distinctly: an event is something that happened, an event_handler is the
predicate and name of the function to execute.
Taking advantage of the maybe_t's, the logic and nesting here
can be a bit less intense.
Small adjustments to debug output, and found a more accurate
version number for Lion Terminal.app.
Longer term we should have a terminal_t class or something
encapsulating all the kinds of terminal detection we have
with methods that return the color support, and also stuff
like whether the terminal has the newline glitch, the
ambiguous width character behavior, etc.
`/tmp` isn't present / writeable on every system. Instead of always
using `/tmp`, try to use standard environment variables and
configuration to find a temporary directory.
Adapted from #3974, with updates based on those comments.
Closes#3845.
This will print out along with the stuff we've guessed about color
support. We get a lot of bug reports about these messing up rendering,
this is useful diagnostic output.
Ask the system where utilities are available with confstr (POSIX).
This is the same string printed by `getconf PATH`, which likely
includes more directories.
For some reason, we have two places where a variable can be read-only:
- By key in env.cpp:is_read_only(), which is checked via set*
- By flag on the actual env_var_t, which is checked e.g. in
parse_execution
The latter didn't happen for non-electric variables like hostname,
because they used the default constructor, because they were
constructed via operator[] (or some such C++-iness).
This caused for-loops to crash on an assert if they used a
non-electric read-only var like $hostname or $SHLVL.
Instead, we explicitly set the flag.
We might want to remove one of the two read-only checks, or something?
Fixes#5548.
This requires threading environment_t through many places, such as completions
and history. We introduce null_environment_t for when the environment isn't
important.
@ridiculousfish had introduced this in 3a45cad12e
to work around an issue with Coverity Scan where it couldn't tell the
mutex was correctly locked, but even with the `fish_mutex_t` hack, it
still emits the same warnings, so there's no pointing in keeping it.
Cleaned up the code to no longer replicate in fishscript what fish
already does (and caches to boot) in C++ in setting up the paths to the
user configuration directory.
Also introduced a `$__fish_user_data_dir` instead of the sporadic
definitions of `$userdatadir` that may or may not go through
`XDG_DATA_HOME`.
* Debug level 3: describe all commands being executed (this is, after all,
a shell and one can argue that this is the most important debug
information avaliable)
* Debug level 4: details of execution, mainly fork vs no-fork and io
handling
Also introduced j->preview() to print a short descriptor of the job
based on the head of the first process so we don't overwhelm with
needless repitition, but also so that we don't have to rely on
distinguishing between repeated, non-unique/non-monotonic job ids that
are often recycled within a single "execution cycle" (pressing enter
once).
In private mode, access to previous history is blocked and new history
does not persist and is only available for the duration of the current
session.
This mode can be used when it is not desirable for commandline history
to leak into a session, e.g. via autocomplete or when it is desirable to
test the behavior of fish in the absence of history items without
permanently clearing the history.
I'm sure there are a lot more features that can be incorporated into
private mode, such as restricting access to certain user-specific
configuration files, etc.
This addresses a lot of the concerns raised in #1363 (which was later
changed to track mosh-specific problems). See also #102.
This switches quoted expansion like "$foo" to use foo's delimiter instead of
space. The delimiter is space for normal variables and colonf or path variables.
Expansions like "$PATH" will now expand using ':'.
This commit begins to bake in a notion of path-style variables.
Prior to this fix, fish would export arrays as ASCII record separator
delimited, except for a whitelist (PATH, CDPATH, MANPATH). This is
surprising and awkward for other programs to deal with, and there's no way
to get similar behavior for other variables like GOPATH or LD_LIBRARY_PATH.
This commit does the following:
1. Exports all arrays as colon delimited strings, instead of RS.
2. Introduces a notion of "path variable." A path variable will be
"colon-delimited" which means it gets colon-separated in quoted expansion,
and automatically splits on colons. In this commit we only do the exporting
part.
Colons are not escaped in exporting; this is deliberate to support uses
like
`set -x PYTHONPATH "/foo:/bar"`
which ought to work (and already do, we don't want to make a compat break
here).
This switches fish to a "virtual" PWD, where it no longer uses getcwd to
discover its PWD but instead synthesizes it based on normalizing cd against
the $PWD variable.
Both pwd and $PWD contain the virtual path. pwd is taught about -P to
return the physical path, and -L the logical path (which is the default).
Fixes#3350
Prior to this change, env_get_pwd_slash() would try to infer the PWD from
getcwd() if $PWD were missing. But this results env_get_pwd_slash() doing
something radically different than $PWD, and also is a lot of code for a
scenario that cannot be reliably reproduced. Just return "/" in this case.
There's been no reproducible case entered for #5080, but the stack trace
indicates the problem is with env_get_pwd_slash() returning an empty
string, which isn't a string that terminates in `/`.
In addition to making the failure case to return the path `./` (which
has the benefit of having the same meaning as $PWD), trying a little bit
harder to retrieve the real PWD by using getcwd(3). While
get_current_dir(3) is documented as relying on PWD, getcwd(3) does not
mention any such caveats, so it's possible that it will work even if
something is breaking PWD.
Just a thought, but it's possible if due to some recursion PWD surpassed
some predetermined value (maybe PATH_MAX) that PWD (on certain platforms
or under certain enivronments) won't be set (hence the code that deals
with ERANGE errors from the getcwd(3) call).
Closes#5080.
This was done in share/config.fish, but leads to surprising results if
that isn't read - e.g. because someone just built fish in the git
directory to test it without installing.
It's also not something that is any more or less complicated.
For compatibility, keep it in config.fish as well for the time being.
This switches the universal variables file from a machine-specific
name to the fixed '.config/fish/fish_universal_variables'. The old file
name is migrated if necessary.
Fixes#1912
The previous commit caused the tests to fail since env_remove() was
returning a blanket `!0` when a variable couldn't be unset because it
didn't exist in the first place. This caused the wrong message to be
emitted since the code clashed with a return code for `env_set()`.
Added `ENV_NOT_FOUND` to signify that the variable requested unset
didn't exist in the first place, but _not_ printing the error message
currently so as not to break existing behavior before checking if this
is something we want.
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.
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.
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.
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.
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.