Commit Graph

21786 Commits

Author SHA1 Message Date
Johannes Altmanninger
a772470b76 Multi-line autosuggestions
Unlike other shells, fish tries to make it easy to work with multiline
commands. Arguably, it's often better to use a full text editor but
the shell can feel more convenient.

Spreading long commands into multiple lines can improve readability,
especially when there is some semantic grouping (loops, pipelines,
command substitutions, quoted parts). Note that in Unix shell, every
quoted string can span multiple lines, like Python's triple quotes,
so the barrier to writing a multiline command is quite low.

However these commands are not autosuggested. From
1c4e5cadf2 (commitcomment-150853293)

> the reason we don't offer multi-line autosuggestion is that they
> can cause the command line to "jump" to make room for the second
> and third lines, if you're at the bottom of your terminal.

This jumping (as done by nushell for example) might be surprising,
especially since there is no limit on the height of a command.

Let's maybe avoid this jumping by rendering only however many lines
from the autosuggestion can fit on the screen without scrolling.

The truncation is hinted at by a single ellipsis ("…") after the
last suggested character, just like when a single-line autosuggestion
is truncated. (We might want to use something else in future.)

To implement this, query for the cursor position after every command,
so we know the y-position of the shell prompt within the terminal
window (whose height we already know).

Also, after we register a terminal window resize, query for the cursor
position before doing anything else (until we od #12004, only height
changes are relevant), to prevent this scenario:

	1. move prompt to bottom of terminal
	2. reduce terminal height
	3. increase terminal height
	4. type a command that triggers a multi-line autosuggestion
	5. observe that it would fail to truncate properly

As a refresher: when we fail to receive a query response, we always
wait for 2 seconds, except if the initial query had also failed,
see b907bc775a (Use a low TTY query timeout only if first query
failed, 2025-09-25).

If the terminal does not support cursor position report (which is
unlikely), show at most 1 line worth of autosuggestion.  Note that
either way, we don't skip multiline commands anymore.  This might make
the behavior worse on such terminals, which are probably not important
enough.  Alternatively, we could use no limit for such terminals,
that's probably the better fallback behavior. The only reason I didn't
do that yet is to stay a little bit closer to historical behavior.

Storing the prompt's position simplifies scrollback-push and the mouse
click handler, which no longer need to query.  Move some associated
code to the screen module.

Technically we don't need to query for cursor position if the previous
command was empty. But for now we do, trading a potential optimization
for andother simplification.

Disable this feature in pexpect tests for now, since those are still
missing some terminal emulation features.
2025-11-08 21:18:25 +01:00
Johannes Altmanninger
e1ce53fe15 screen: fix inconsistent initialization order 2025-11-08 21:18:25 +01:00
Johannes Altmanninger
77bdd4fbde reader: use unqualified enum variants in match statement
This reduces noise although the indentation is not great.
2025-11-08 21:18:25 +01:00
Johannes Altmanninger
3fdaa543ed reader: remove unused parameter 2025-11-08 21:18:25 +01:00
Johannes Altmanninger
336be1e36d termsize: better types
The u16 is implied by libc::winsize.
2025-11-08 21:18:25 +01:00
Johannes Altmanninger
382027663f termsize: try to simplify a little bit
Also add "safe_" prefix to functions we require to be
async-signal-safe.
2025-11-08 21:18:25 +01:00
Johannes Altmanninger
1d58b84637 mouse handling: fish's screen always starts at x=0
We already assume elsewhere that e.g. \r will return us to x=0
(fish coordinates).
2025-11-08 21:18:25 +01:00
Johannes Altmanninger
88ead18709 Move query-interrupt event-variant into query-result enum
I think the interruption event is grouped next to the check-exit one
because it used to be implemented as check exit but with a global flag
(I didn't check whether that applied to master).

Move it to the logical place.
2025-11-08 21:18:25 +01:00
Johannes Altmanninger
70058bdee2 reader: remove unused check
The readline state is never finished before the very first loop
iteration.  Move the check for rls.finished next to the one that
implements "read -n1" -- in future we might use the return value
for both.
2025-11-08 21:18:25 +01:00
Johannes Altmanninger
d1c85966d9 __fish_echo: fully overwrite lines, take 2
For the same reason as before (upcoming multi-line autosuggestions),
reapply 1fdf37cc4a (__fish_echo: fully overwrite lines, 2025-09-17)
after it was reverted in b7fabb11ac (Make command run by __fish_echo
output to TTY for color detection, 2025-10-05)
 (Make command run by __fish_echo output
to TTY for color detection, 2025-10-05).  Use clear-to-end-of-screen
to allow making "ls" output directly to the terminal.

Alternatively, we could create a pseudo TTY (e.g. call something like
"unbuffer ls --color=auto").
2025-11-08 21:18:25 +01:00
Daniel Rainer
0679d98950 printf: do not check for I flag
This flag is not supported by our sprintf, so remove it here, to avoid
suggesting that it might be supported.

Closes #11874
2025-11-08 21:18:25 +01:00
Johannes Altmanninger
a8b7d89ba5 doc terminal-compatibility: document Unicode characters used in output
Not sure if this will be useful but the fact that we use very
few Unicode characters, suggests that we are insecure about
this. Having some kind of central and explicit listing might help
future decision-making.  Obviously, completions and translations use
more characters, but those are not as central.
2025-11-08 21:18:25 +01:00
Fabian Boehm
828773b391 __fish_print_help: Also add "-l"
mandoc refuses to open files without.

See #12037
2025-11-08 15:30:47 +01:00
John Paul Adrian Glaubitz
35f4eb8e9a Fix build on Linux/SPARC by disabling SIGSTKFLT 2025-11-08 14:56:25 +01:00
Fabian Boehm
8c69e62a78 terminal-compatibility: Remove "Origin" column
This isn't very useful, makes the table very wide and invites discussion on who exactly invented
what.

Let's leave that to the historians.

Fixes #12031
2025-11-08 14:54:57 +01:00
Fabian Boehm
8e4fa9aafb functions/man: Pass "-l" to get man to open a file
Supported by mandoc, man-db and NetBSD man, and mandoc now requires
this.

Fixes #12037
2025-11-08 14:50:10 +01:00
Johannes Altmanninger
d6ed5f843e fish_tab_title to set terminal tab title independent of window title
Some modern terminals allow creating tabs in a single window;
this functionality has a lot of overlap with what a window manager
already provides, so I'm not sure if it's a good idea.  Regardless,
a lot of people still use terminal tabs (or even multiple levels of
tabs via tmux!), so let's add a fish-native way to set the tab title
independent of the window title.

Closes #2692
2025-11-06 13:02:23 +01:00
Daniel Rainer
ba7bc2be13 cleanup: remove unused variable
Closes #12023
2025-11-06 13:02:23 +01:00
ken
199475b6ca Stop disabling mouse tracking
Commit eecc223 (Recognize and disable mouse-tracking CSI events,
2021-02-06) made fish disable mouse reporting whenever we receive a
mouse event.  This was because at the time we didn't have a parser
for mouse inputs.  We do now, so let's allow users to toggle mouse
support with

	printf '\e[?1000h'
	printf '\e[?1000l'

Currently the only mouse even we support is left click (to move cursor
in commandline, select pager items).

Part of #4918
See #12026

[ja: tweak patch and commit message]
2025-11-06 13:02:23 +01:00
Johannes Altmanninger
60b50afefd Fix missing ICANON regression after read in noninteractive shell
Since commit 7e3fac561d (Query terminal only just before reading
from it, 2025-09-25),

	fish -c 'read; cat'

fails to turn ICANON back on for cat.

Even before that commit, I don't know how this ever worked.  Before or
after, we'd call tcsetattr() only to set our shell modes, not the
ones for external commands (term_donate)

I also don't think there's a good reason why we set modes twice
(between term_donate () and old_modes), but I'll make a minimal (=
safer) change for now until I understand this.

The only change from 7e3fac561d was that instead of doing things in
this order:

	terminal_init()
		set_shell_modes
	read
		reader_push()
		reader_readline()
			save & restore old_modes
	cat

we now do

	read
		reader_push()
			terminal_init()
				set_shell_modes()
		reader_readline()
			save & restore old_modes
	cat

So we call set_shell_modes() just before saving modes,
which obviously makes us save the wrong thing.
Again, not sure how that wasn't a problem before.

Fix it by saving modes before calling terminal_init().

Fixes #12024
2025-11-06 13:02:23 +01:00
Johannes Altmanninger
7aa64dc423 help: use "introduction" instead of "index" in user-visible section title
The new completions are like

	help index#default-shell

Add a hack to use the "introduction" here.

Not sure if this is worth it but I guess we should be okay because
we at least have test for completions.

In future, we should find a better way to declare that "introduction"
is our landing page.
2025-11-06 13:01:08 +01:00
Johannes Altmanninger
7a59540517 docs: use :doc: role when referencing entire pages
No need to define "cmd-foo" anchors; use :doc:`foo <cmds/foo>`
instead. If we want "cmd-foo" but it should be tested.

See also 38b24c2325 (docs: Use :doc: role when linking to commands,
2022-09-23).
2025-11-06 12:58:59 +01:00
Johannes Altmanninger
2cd60077e6 help: get section titles from Sphinx
functions/help and completions/help duplicate a lot of information
from doc_src. Get this information from Sphinx.

Drop short section titles such as "help globbing" in favor of the
full HTML anchor:

	help language#wildcards-globbing 

I think the verbosity is no big deal because we have tab completion,
we're trading in conciseness for consistency and better searchability.

In future, we can add back shorter invocations like "help globbing"
(especially given that completion descriptions often already repeated
the anchor path), but it should be checked by CI.

Also
- Remove some unused Sphinx anchors
- Remove an obsoleted script.
- Test that completions are in sync with Sphinx sources.
  (note that an alternative would be to check
  in the generated help_sections.rs file, see
  https://internals.rust-lang.org/t/how-fail-on-cargo-warning-warnings-from-build-rs/23590/5)

Here's a list of deleted msgids. Some of them were unused, for others
there was a better message (+ translation).

	$variable $variable 变量
	(command) command substitution (命令) 命令替换
	< and > redirections < 和 > 重定向
	Autoloading functions 自动加载函数
	Background jobs 后台作业
	Builtin commands 内建命令
	Combining different expansions 合并不同的展开
	Command substitution (SUBCOMMAND) 命令替换 (子命令)
	Defining aliases 定义别名
	Escaping characters 转义字符
	Help on how to reuse previously entered commands 关于如何重复使用先前输入的命令的帮助
	How lists combine 列表如何组合
	Job control 作业控制
	Local, global and universal scope 局域、全局和通用作用域
	Other features 其他功能
	Programmable prompt 可编程提示符
	Shell variable and function names Shell 变量和函数名
	Some common words 一些常用词
	The status variable 状况变量
	Variable scope for functions 函数的变量作用域
	Vi mode commands Vi 模式命令
	What set -x does `set -x` 做什么
	Writing your own completions 自己写补全
	ifs and elses if 和 else
	var[x..y] slices var[x..y] 切片
	{a,b} brace expansion {a,b} 大括号展开
	~ expansion ~ 展开


Closes #11796
2025-11-06 12:58:59 +01:00
Johannes Altmanninger
2c68a6704f Don't escape '#' in some cases where it's not necessary
This is useful for the next commit where tab completion produces
tokens like "foo#bar". Some cases are missing though, because we
still need to tell this function what's the previous character.
I guess next commit could also use a different sigil.
2025-11-06 12:58:59 +01:00
Johannes Altmanninger
cc95cef165 crates/build-man-pages: try to improve style 2025-11-06 12:08:10 +01:00
Johannes Altmanninger
cd76c2cb26 help/man: support \{ 2025-11-06 12:06:05 +01:00
Johannes Altmanninger
c586210306 help: more style changes
Seems better to propagate return code?
Otherwise only style changes.
2025-11-06 12:06:05 +01:00
Johannes Altmanninger
ec3cd4f4cb help: style changes and fixes 2025-11-06 12:06:05 +01:00
Johannes Altmanninger
eef5a7ff2b Use path to sphinx-build from CMake
Commit 0709e4be8b (Use standalone code paths by default, 2025-10-26)
made CMake builds enable the embed-data feature.  This means that
crates/build-man-pages/build.rs will run "sphinx-build" to create
man pages for embedding, now also for CMake builds.

Let's use the sphinx-build found by CMake at configuration-time.

This makes VARS_FOR_CARGO depend on cmake/Docs.cmake, so adjust the
order accordingly.
2025-11-05 17:34:21 +01:00
Johannes Altmanninger
988985727f Disable failing fish_config test for now
This has probably been failing intermittently in CI ever since it
was introduced. We have a reproducible test now, so let's disable
this test in CI for now to reduce noise.

See #12018
2025-11-04 14:48:40 +01:00
Shigure Kurosaki
dad58ac20a fix(edit_command_buffer): ignore cat alias
Signed-off-by: Shigure Kurosaki <shigure@hqsy.net>

Closes #12007
2025-11-04 14:13:22 +01:00
Johannes Altmanninger
3f9d8db5b7 builtin ulimit: extract function 2025-11-04 14:13:22 +01:00
Johannes Altmanninger
0b6afbd17b Prefer commandline case over same-length autosuggestion
If I run

	history append 'echo -X'

and type "echo -x", it renders as "echo -X".

This is not wrong but can be pretty confusing, (since the
autosuggestion is the same length as the command line).

Let's favor the case typed by the user in this specific case I guess.
Should add a full solution later.

Part of #11452
2025-11-04 14:13:22 +01:00
Daniel Rainer
e9936bc5ed cleanup: use let-else to reduce indentation
Closes #12019
2025-11-04 11:51:25 +01:00
Daniel Rainer
068a1ab95c refactor: make wwrite_to_fd more idiomatic
There is no need to use `'\0'`, we can use `0u8` instead.

`maxaccum` does not clearly indicate what it represents; use
`accum_capacity` instead.

To get the size of `accum`, we can use `accum.len()`, which is easier to
understand.

Use `copy_from_slice` instead of `std::ptr::copy`. This avoids the
unsafe block, at the cost of a runtime length check. If we don't want
this change for performance reasons, we might consider using
`std::ptr::copy_nonoverlapping` here (which is done by `copy_from_slice`
internally).

Part of #12008
2025-11-04 11:51:09 +01:00
Daniel Rainer
74d9a3537c gettext: fall back to all language variants
If a language is specified using only the language code, without a
region identifier, assume that the user prefers translations from any
variant of the language over the next fallback option. For example, when
a user sets `LANGUAGE=zh:pt`, assume that the user prefers both `zh_CN` and
`zh_TW` over the next fallback option. The precedence of the different
variants of a language will be arbitrary. In this example, with the
current set of relevant available catalogs (`pt_BR`, `zh_CN`, `zh_TW`),
the effective precedence will be either `zh_CN:zh_TW:pt_BR` or
`zh_TW:zh_CN:pt_BR`.

Users who want more control over the order can
specify variants to get the results they want.
For example:
- `LANGUAGE=zh_TW:zh:pt` will result in `zh_TW:zh_CN:pt_BR`.
- `LANGUAGE=zh_CN:pt:zh` will result  in `zh_CN:pt_BR:zh_TW`.
- `LANGUAGE=zh_CN:pt` will result  in `zh_CN:pt_BR`.
English is always used as the last fallback.

This approach (like the previous approach) differs from GNU gettext
semantics, which map region-less language codes to on specific "default"
variant of the language, without specifying how this default is chosen.
We want to avoid making such choices and believe it is better to utilize
translations from all language variants we have available when users do
not explicitly specify their preferred variant. This way, users have an
easier time discovering localization availability, and can be more
explicit in their preferences if they don't like the defaults.
If there are conflicts with gettext semantics, users can also set locale
variables without exporting them, so fish uses different values than its
child processes.

Closes #12011
2025-11-03 17:13:42 +00:00
Johannes Altmanninger
143a4aca0f Readme: fix RST syntax 2025-11-03 09:17:00 +01:00
Johannes Altmanninger
20e66ad990 Add workaround for terminals confused by MSYS2 paths
Some terminals handle invalid OSC 7 working directories by falling
back to the home directory, which is worse than if they didn't support
OSC 7.  Try to work arond the common case (when $MSYSTEM is set).

	local wezterm = require 'wezterm'
	local config = wezterm.config_builder()
	config.default_prog = {
	     'C:\\msys64\\msys2_shell.cmd',
	    '-ucrt64',
	    '-defterm',
	    '-here',
	    '-no-start',
	    '-shell', 'fish'
	}
	config.default_cwd = 'C:\\msys64\\home\\xxx'
	return config

Upstream issues:
- https://github.com/wezterm/wezterm/discussions/7330
- https://invent.kde.org/utilities/konsole/-/merge_requests/1136

Closes #11981
2025-11-03 09:17:00 +01:00
Johannes Altmanninger
ceec382161 Disable repaint on WINCH again for VTE/Konsole/WezTerm
This was accidentally turned on because c31e769f7d (Use XTVERSION for
terminal-specific workarounds, 2025-09-21) used the wrong argument
order.  Fix that.
2025-11-03 09:17:00 +01:00
Johannes Altmanninger
782916930a Work around failing asan tests
I could reproduce both
tests/checks/tmux-empty-prompt.fish
tests/pexpects/autosuggest.py

failing in ASan CI. I didn't bisect it, since I don't think there is
a problematic code change. Bump the timeout a bit.

Closes #12016
2025-11-03 09:17:00 +01:00
Johannes Altmanninger
a767739c06 doc terminal-compatibility: fix inconsistent parameter wildcard notation 2025-11-03 09:17:00 +01:00
Peter Ammon
cf3c9d75d7 Don't run the man check test if FISH_BUILD_DOCS is 0 2025-11-01 13:12:58 -07:00
Peter Ammon
1846d7fd7e Merge branch 'cleanup-thread-pool'
This merges changes that make thread pools instanced. We no longer have
a single global thread pool. This results in significant simplifications
especially in the reader (no more "canary").
2025-11-01 11:46:25 -07:00
Johannes Altmanninger
b8c7ee3a85 Fix Dockerfile syntax
Enigmatic error:

	   1 | >>> FROM alpine:3.22 # updatecli.d/docker.yml
	ERROR: failed to build: failed to solve: dockerfile parse error on line 1: FROM requires either one or three arguments

Fixes daadd81ab6 (More automation for updating dependencies, 2025-10-31).
2025-11-01 13:11:33 +01:00
Johannes Altmanninger
0709e4be8b Use standalone code paths by default
When users update fish by replacing files, existing shells might
throw weird errors because internal functions in share/functions/
might have changed.

This is easy to remedy by restarting the shell,
but I guess it would be nice if old shells kept using old data.
This is somewhat at odds with lazy-loading.

But we can use the standalone mode.  Turn that on by default.

Additionally, this could simplify packaging.  Some packages incorrectly
put third party files into /usr/share/fish/completion/ when they ought
to use /usr/share/fish/vendor_completions.d/ for that.  That packaging
mistake can make file conflicts randomly appearing when either fish
or foo ships a completion for foo.  Once we actually stop installing
/usr/share/fish/completions, there will no longer be a conflict (for
better or worse, things will silently not work, unless packagers
notice that the directory doesn't actually exist anymore).

The only advantage of having /usr/share/fish/ on the file system is
discoverability. But getting the full source code is better anyway.

Note that we still install (redundant) $__fish_data_dir when using
CMake.  This is to not unnecessarily break both
1. already running (old) shells as users upgrade to 4.2
2. plugins (as mentioned in an earlier commit),

We can stop installing $__fish_data_dir once we expect 99% of users
to upgrade from at least 4.2.

If we end up reverting this, we should try to get rid of the embed-data
knob in another way, but I'm not sure how.

Closes #11921

To-do:
- maybe make it a feature flag so users can turn it off without
  recompiling with "set -Ua no-embed-data".
2025-11-01 12:58:13 +01:00
Johannes Altmanninger
328f9a9d16 Readme: reword the "Building fish with Cargo" section
The next commit will make embed-data the default also for CMake builds.

Even if we revert that, from a user perspective we better call it
"Building fish with Cargo" rather than "Building fish with embedded
data".

While at it, let's list the user-facing differences when building
with Cargo as opposed to CMake.

I suppose it's not needed to mention :

> An empty ``/etc/fish/config.fish`` as well as empty directories
> ``/etc/fish/{functions,completions,conf.d}``

because that's obvious.

Since installation via Cargo is already aimed at developers, maybe
add "uv run" here to reliably install a recent version of Sphinx.
A small extra step up-front seems better than not having docs.
2025-11-01 12:58:13 +01:00
Johannes Altmanninger
1d9233abc7 Fix CMake build with embed-data 2025-11-01 12:58:13 +01:00
Johannes Altmanninger
c9cc2a4069 config_paths: inline function again
Now that the dust has settled, there is only one caller of the path
detection logic, so we don't need the enum.  Remove it.  No functional
change.
2025-11-01 12:58:13 +01:00
Johannes Altmanninger
e0a2fa35cc Define __fish_{data,help}_dir again on standalone builds
As mentioned in a previous commit ("Don't special-case __fish_data_dir
in standalone builds"), we want to enable embed-data by default.
To reduce the amount of breakage, we'll keep installing files,
and keep defining those variables at least for some time.

We have no use for $__fish_data_dir apart from helping plugins and
improving upgrade experience, but we still use $__fish_help_dir;
so this will allow installed "standalone" builds to use local docs
via our "help" function.
2025-11-01 12:58:13 +01:00
Johannes Altmanninger
da5a57890a env: extract function for setting our config path variables
While at it, reorder the assignments to match the order in ConfigPaths.
2025-11-01 12:58:13 +01:00