diff --git a/README.md b/README.md index 4eab7e86..32fc39ab 100644 --- a/README.md +++ b/README.md @@ -66,16 +66,16 @@ details, see the manual. ### Initialization scripts -When yash is started as a login shell, it reads `~/.yash_profile`. This -file is a shell script in which you define environment variables using -the export command. - -When yash is started for an interactive use, it reads `~/.yashrc` (after -reading `~/.yash_profile` if it is a login shell also). In this file, -you make other configurations such as aliases, prompt strings, key -bindings for command line editing, and command-not-found handler. -Use the [share/initialization/sample](share/initialization/sample) file -as a template for your `~/.yashrc`. +When yash is started as a login shell, it reads `$XDG_CONFIG_HOME/yash/profile` +or `~/.yash_profile` as a fallback. This file is a shell script in which you +define environment variables using the export command. + +When yash is started for an interactive use, it reads `$XDG_CONFIG_HOME/yash/rc` +or `~/.yashrc` (after reading `$XDG_CONFIG_HOME/yash/profile` if it is a login +shell also). In this file, you make other configurations such as aliases, +prompt strings, key bindings for command line editing, and command-not-found +handler. Use the [share/initialization/sample](share/initialization/sample) +file as a template for your `$XDG_CONFIG_HOME/yash/rc`. ### Making yash your login shell diff --git a/doc/faq.txt b/doc/faq.txt index ae3c8b0b..076db636 100644 --- a/doc/faq.txt +++ b/doc/faq.txt @@ -48,7 +48,8 @@ variable to a different value. Please consult your OS's documentation to learn how to configure these variables in detail. If you want to apply the same configuration every time you start yash, write -the command in ~/.yashrc or ~/.yash_profile. +the command in $XDG_CONFIG_HOME/yash/rc or $XDG_CONFIG_HOME/yash/profile. The old locations +~/.yashrc and ~/.yash_profile are also supported as a fallback. If yash still rejects Unicode characters being entered, see the section below regarding line-editing. diff --git a/doc/invoke.txt b/doc/invoke.txt index 6af22ded..b58f4dd5 100644 --- a/doc/invoke.txt +++ b/doc/invoke.txt @@ -92,16 +92,18 @@ Yash initializes itself as follows: specified or the shell is in the link:posix.html[POSIXly-correct mode]. + If the +--profile={{filename}}+ option is not specified, the shell reads - link:expand.html#tilde[~]/.yash_profile as a default. + $XDG_CONFIG_HOME/yash/profile or link:expand.html#tilde[~]/.yash_profile + as a fallback. .. If in the interactive mode, the shell reads the file specified by the +--rcfile={{filename}}+ option unless the +--norcfile+ option is specified. + If the +--rcfile={{filename}}+ option is not specified, the shell instead reads the following files: - If not in the POSIXly-correct mode, the shell reads - link:expand.html#tilde[~]/.yashrc. If it cannot be read, the shell - searches link:params.html#sv-yash_loadpath[+YASH_LOADPATH+] for a file - named initialization/default. + $XDG_CONFIG_HOME/yash/rc or link:expand.html#tilde[~]/.yashrc as a + fallback. If it cannot be read, the shell searches + link:params.html#sv-yash_loadpath[+YASH_LOADPATH+] for a file named + initialization/default. - If in the POSIXly-correct mode, the shell performs link:expand.html[parameter expansion] on the value of the link:params.html#sv-env[+ENV+ environment variable] and treats the diff --git a/share/initialization/common b/share/initialization/common index ddc47d88..168681a5 100644 --- a/share/initialization/common +++ b/share/initialization/common @@ -182,7 +182,20 @@ fi : ${ECHO_STYLE:=RAW} # variables needed for command history -HISTFILE=~/.yash_history HISTSIZE=5000 + +if ! [ "${HISTFILE-}" ]; then + HISTFILE=${XDG_STATE_HOME:-~/.local/state}/yash/history + + # handle old default history path + if [ -f ~/.yash_history ]; then + printf 'Note: The default history file location has been changed to "%s".\n' "$HISTFILE" >&2 + HISTFILE=~/.yash_history + printf 'Please consider moving the existing file from the current location "%s".\n' "$HISTFILE" >&2 + fi +fi + +HISTSIZE=5000 + # HISTRMDUP makes prediction less accurate # HISTRMDUP=500 diff --git a/share/initialization/default b/share/initialization/default index 04970bcc..fe48a8e3 100644 --- a/share/initialization/default +++ b/share/initialization/default @@ -1,6 +1,6 @@ ##### Default Yashrc ##### # This file is automatically loaded when yash starts up and a user-specific -# initialization script cannot be read from ~/.yashrc. +# initialization script cannot be read from $XDG_CONFIG_HOME/yash/rc or ~/.yashrc. # This file is in the public domain. # print introduction @@ -10,7 +10,8 @@ cat <<__END__ Welcome to yash! You are seeing this message because a user-specific initialization script is -not found at ~/.yashrc. The current session has been loaded with common +not found at ${XDG_CONFIG_HOME:-$HOME/.config}/yash/rc or ~/.yashrc. +The current session has been loaded with common settings that should be useful for many users. To suppress this message, copy a sample initialization script from ${yashdatadir}/initialization/sample to ~/.yashrc and make any customization in it if you want. For bare default diff --git a/share/initialization/sample b/share/initialization/sample index c1f14503..8df423cd 100644 --- a/share/initialization/sample +++ b/share/initialization/sample @@ -1,5 +1,6 @@ ##### Sample Yashrc ##### -# This is a sample initialization script for yash. Copy this file to ~/.yashrc +# This is a sample initialization script for yash. Copy this file to +# $XDG_CONFIG_HOME/yash/rc or ~/.yashrc # and add your favorite customization to it. diff --git a/tests/run-test.sh b/tests/run-test.sh index 6faeb3ce..4fe92c11 100644 --- a/tests/run-test.sh +++ b/tests/run-test.sh @@ -82,7 +82,7 @@ unset -v ENV FCEDIT HANDLED HISTFILE HISTRMDUP HISTSIZE HOME IFS LC_ALL unset -v LC_COLLATE LC_MESSAGES LC_MONETARY LC_NUMERIC LC_TIME LINES MAIL unset -v MAILCHECK MAILPATH NLSPATH OLDPWD POST_PROMPT_COMMAND PROMPT_COMMAND unset -v PS1 PS1R PS1S PS2 PS2R PS2S PS3 PS3R PS3S PS4 PS4R PS4S -unset -v RANDOM TERM YASH_AFTER_CD YASH_LE_TIMEOUT YASH_VERSION +unset -v RANDOM TERM XDG_CONFIG_HOME YASH_AFTER_CD YASH_LE_TIMEOUT YASH_VERSION unset -v A B C D E F G H I J K L M N O P Q R S T U V W X Y Z _ unset -v a b c d e f g h i j k l m n o p q r s t u v w x y z unset -v posix skip diff --git a/variable.h b/variable.h index 24dcc13f..8e81816f 100644 --- a/variable.h +++ b/variable.h @@ -69,6 +69,7 @@ extern char **environ; #define VAR_TARGETWORD "TARGETWORD" #define VAR_TERM "TERM" #define VAR_WORDS "WORDS" +#define VAR_XDG_CONFIG_HOME "XDG_CONFIG_HOME" #define VAR_YASH_AFTER_CD "YASH_AFTER_CD" #define VAR_YASH_LE_TIMEOUT "YASH_LE_TIMEOUT" #define VAR_YASH_LOADPATH "YASH_LOADPATH" diff --git a/yash.c b/yash.c index fbc9aabf..2fc20afc 100644 --- a/yash.c +++ b/yash.c @@ -57,7 +57,7 @@ static struct input_file_info_T *new_input_file_info(int fd, size_t bufsize) __attribute__((malloc,warn_unused_result)); static void execute_profile(const wchar_t *profile); static void execute_rcfile(const wchar_t *rcfile); -static bool execute_file_in_home(const wchar_t *path) +static bool execute_file_in(const wchar_t *dir_var_name, const wchar_t *path) __attribute__((nonnull)); static bool execute_file(const wchar_t *path); static bool execute_file_mbs(const char *path); @@ -256,20 +256,33 @@ struct input_file_info_T *new_input_file_info(int fd, size_t bufsize) return info; } -/* Executes "$HOME/.yash_profile". */ +/* Executes "$XDG_CONFIG_HOME/yash/profile", "$HOME/.config/yash/profile" or + * "$HOME/.yash_profile" as a fallback. + */ void execute_profile(const wchar_t *profile) { - if (profile != NULL) + if (profile != NULL) { execute_file(profile); - else - execute_file_in_home(L".yash_profile"); + return; + } + + if (execute_file_in(L VAR_XDG_CONFIG_HOME, L"yash/profile")) + return; + + if (execute_file_in(L VAR_HOME, L".config/yash/profile")) + return; + + execute_file_in(L VAR_HOME, L".yash_profile"); + } -/* Executes the initialization file. - * `rcfile' is the filename to source. - * If `rcfile' is NULL, it defaults to "$HOME/.yashrc" and if the file cannot be - * read it falls back to "initialization/default" from $YASH_LOADPATH. - * In the POSIXly-correct mode, `rcfile' is ignored and "$ENV" is used. */ + +/* Executes the initialization file. `rcfile' is the filename to source. + * If `rcfile' is NULL, defaults to "$XDG_CONFIG_HOME/yash/rc", + * "~/.config/yash/rc", or "~/.yashrc" as a fallback and * finally if the file + * cannot * be read it falls back to "initialization/default" * from + * $YASH_LOADPATH. * In the POSIXly-correct mode, `rcfile' is ignored and * "$ENV" + * is used. */ void execute_rcfile(const wchar_t *rcfile) { if (posixly_correct) { @@ -286,7 +299,14 @@ void execute_rcfile(const wchar_t *rcfile) execute_file(rcfile); return; } - if (execute_file_in_home(L".yashrc")) + + if (execute_file_in(L VAR_XDG_CONFIG_HOME, L"yash/rc")) + return; + + if (execute_file_in(L VAR_HOME, L".config/yash/rc")) + return; + + if (execute_file_in(L VAR_HOME, L".yashrc")) return; char *path = which("initialization/default", get_path_array(PA_LOADPATH), @@ -296,15 +316,15 @@ void execute_rcfile(const wchar_t *rcfile) } /* Executes the specified file. The `path' must be relative to $HOME. */ -bool execute_file_in_home(const wchar_t *path) +bool execute_file_in(const wchar_t *dir_var_name, const wchar_t *path) { - const wchar_t *home = getvar(L VAR_HOME); - if (home == NULL || home[0] == L'\0') + const wchar_t *directory = getvar(dir_var_name); + if (directory == NULL || directory[0] == L'\0') return false; xwcsbuf_T fullpath; - wb_initwithmax(&fullpath, add(add(wcslen(home), wcslen(path)), 1)); - wb_cat(&fullpath, home); + wb_initwithmax(&fullpath, add(add(wcslen(directory), wcslen(path)), 1)); + wb_cat(&fullpath, directory); if (fullpath.contents[fullpath.length - 1] != L'/') wb_wccat(&fullpath, L'/'); wb_cat(&fullpath, path);