mirror of
https://github.com/fish-shell/fish-shell
synced 2024-12-26 12:53:13 +00:00
if started without a locale read system config
A common problem for users is that fish doesn't get a locale. This often happens if systemd is used with getty and fish as login shell. Fixes #277 Note that I (@krader) made editorial changes before merging this. For example, running `make style` and otherwise changing long statements to a series of shorter statements. So if there are any problems it is possible I introduced them.
This commit is contained in:
parent
b12c413c28
commit
0a51b17716
2 changed files with 87 additions and 16 deletions
|
@ -1,4 +1,3 @@
|
||||||
#
|
|
||||||
# Main file for fish command completions. This file contains various
|
# Main file for fish command completions. This file contains various
|
||||||
# common helper functions for the command completions. All actual
|
# common helper functions for the command completions. All actual
|
||||||
# completions are located in the completions subdirectory.
|
# completions are located in the completions subdirectory.
|
||||||
|
@ -7,7 +6,6 @@
|
||||||
#
|
#
|
||||||
# Set default field separators
|
# Set default field separators
|
||||||
#
|
#
|
||||||
|
|
||||||
set -g IFS \n\ \t
|
set -g IFS \n\ \t
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -18,8 +16,7 @@ function __fish_default_command_not_found_handler
|
||||||
end
|
end
|
||||||
|
|
||||||
if status --is-interactive
|
if status --is-interactive
|
||||||
# The user has seemingly explicitly launched an old fish with
|
# The user has seemingly explicitly launched an old fish with too-new scripts installed.
|
||||||
# too-new scripts installed.
|
|
||||||
if not contains "string" (builtin -n)
|
if not contains "string" (builtin -n)
|
||||||
set -g __is_launched_without_string 1
|
set -g __is_launched_without_string 1
|
||||||
# XXX nostring - fix old fish binaries with no `string' builtin.
|
# XXX nostring - fix old fish binaries with no `string' builtin.
|
||||||
|
@ -195,6 +192,11 @@ function . --description 'Evaluate contents of file (deprecated, see "source")'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Set the locale if it isn't explicitly set. Allowing the lack of locale env vars to imply the
|
||||||
|
# C/POSIX locale causes too many problems. Do this before reading the snippets because they might be
|
||||||
|
# in UTF-8 (with non-ASCII characters).
|
||||||
|
__fish_set_locale
|
||||||
|
|
||||||
# As last part of initialization, source the conf directories
|
# As last part of initialization, source the conf directories
|
||||||
# Implement precedence (User > Admin > Extra (e.g. vendors) > Fish) by basically doing "basename"
|
# Implement precedence (User > Admin > Extra (e.g. vendors) > Fish) by basically doing "basename"
|
||||||
set -l sourcelist
|
set -l sourcelist
|
||||||
|
@ -225,15 +227,6 @@ end
|
||||||
|
|
||||||
if status --is-login
|
if status --is-login
|
||||||
|
|
||||||
# Check for i18n information in
|
|
||||||
# /etc/sysconfig/i18n
|
|
||||||
|
|
||||||
if test -f /etc/sysconfig/i18n
|
|
||||||
string match -r '^[a-zA-Z]*=.*' < /etc/sysconfig/i18n | while read -l line
|
|
||||||
set -gx (string split '=' -m 1 -- $line | string replace -ra '"([^"]+)"' '$1' | string replace -ra "'([^']+)'" '$1')
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Put linux consoles in unicode mode.
|
# Put linux consoles in unicode mode.
|
||||||
#
|
#
|
||||||
|
|
78
share/functions/__fish_set_locale.fish
Normal file
78
share/functions/__fish_set_locale.fish
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
# Try to set the locale from the system configuration if we did not inherit any. One case where this
|
||||||
|
# can happen is a linux with systemd where the user logs in via getty (e.g., on the system console).
|
||||||
|
# See https://github.com/fish-shell/fish-shell/issues/3092. This isn't actually our job, so there's
|
||||||
|
# a bunch of edge-cases we are unlikely to handle properly. If we get a value for _any_ language
|
||||||
|
# variable, we assume we've inherited something sensible so we skip this to allow the user to set it
|
||||||
|
# at runtime without mucking with config files.
|
||||||
|
#
|
||||||
|
# NOTE: This breaks the expectation that an empty LANG will be the same as LANG=POSIX, but an empty
|
||||||
|
# LANG seems more likely to be caused by a missing or misconfigured locale configuration.
|
||||||
|
|
||||||
|
function __fish_set_locale
|
||||||
|
set -l LOCALE_VARS
|
||||||
|
set LOCALE_VARS $LOCALE_VARS LANG LANGUAGE LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE
|
||||||
|
set LOCALE_VARS $LOCALE_VARS LC_MONETARY LC_MESSAGES LC_PAPER LC_NAME LC_ADDRESS
|
||||||
|
set LOCALE_VARS $LOCALE_VARS LC_TELEPHONE LC_MEASUREMENT LC_IDENTIFICATION
|
||||||
|
|
||||||
|
# We check LC_ALL to figure out if we have a locale but we don't set it later. That is because
|
||||||
|
# locale.conf doesn't allow it so we should not set it.
|
||||||
|
if string length -q -- $$LOCALE_VARS $LC_ALL
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
|
||||||
|
# Unset all variables - they are empty anyway and this makes merging easier.
|
||||||
|
for locale_var in $LOCALE_VARS
|
||||||
|
set -e $locale_var
|
||||||
|
end
|
||||||
|
|
||||||
|
# Try to extract the locale from the kernel boot commandline. The splitting here is a bit weird,
|
||||||
|
# but we operate under the assumption that the locale can't include whitespace. Other whitespace
|
||||||
|
# shouldn't concern us, but a quoted "locale.LANG=SOMETHING" as a value to something else might.
|
||||||
|
# Here the last definition of a variable takes precedence.
|
||||||
|
if test -r /proc/cmdline
|
||||||
|
for var in (string match -ra 'locale.[^=]+=\S+' < /proc/cmdline)
|
||||||
|
set -l kv (string replace 'locale.' '' -- $var | string split '=')
|
||||||
|
# Only set locale variables, not other stuff contained in these files - this also
|
||||||
|
# automatically ignores comments.
|
||||||
|
if contains -- $kv[1] $LOCALE_VARS
|
||||||
|
and set -q kv[2]
|
||||||
|
set -gx $kv[1] (string trim -c '\'"' -- $kv[2])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Now read the config files we know are used by various OS distros.
|
||||||
|
#
|
||||||
|
# /etc/sysconfig/i18n is for old Red Hat derivatives (and possibly of no use anymore).
|
||||||
|
#
|
||||||
|
# /etc/env.d/02locale is from OpenRC.
|
||||||
|
#
|
||||||
|
# The rest are systemd inventions but also used elsewhere (e.g. Void Linux). systemd's
|
||||||
|
# documentation is a bit unclear on this. We merge all the config files (and the commandline),
|
||||||
|
# which seems to be what systemd itself does. (I.e. the value for a variable will be taken from
|
||||||
|
# the highest-precedence source) We read the systemd files first since they are a newer
|
||||||
|
# invention and therefore the rest are likely to be accumulated cruft.
|
||||||
|
#
|
||||||
|
# NOTE: Slackware puts the locale in /etc/profile.d/lang.sh, which we can't use because it's a
|
||||||
|
# full POSIX-shell script.
|
||||||
|
set -l user_cfg_dir (set -q XDG_CONFIG_HOME; and echo $XDG_CONFIG_HOME; or echo ~/.config)
|
||||||
|
for f in $user_cfg_dir/locale.conf /etc/locale.conf /etc/env.d/02locale /etc/sysconfig/i18n
|
||||||
|
if test -r $f
|
||||||
|
while read -l kv
|
||||||
|
set kv (string split '=' -- $kv)
|
||||||
|
if contains -- $kv[1] $LOCALE_VARS
|
||||||
|
and set -q kv[2]
|
||||||
|
# Do not set already set variables again - this makes the merging happen.
|
||||||
|
if not set -q $kv[1]
|
||||||
|
set -gx $kv[1] (string trim -c '\'"' -- $kv[2])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end <$f
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# If we really cannot get anything, at least set character encoding to UTF-8.
|
||||||
|
if not string length -q -- $$LOCALE_VARS $LC_ALL
|
||||||
|
set -gx LC_CTYPE en_US.UTF-8
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in a new issue