Skip to content

Commit

Permalink
Implement XDG Base Directory Specification support (#63)
Browse files Browse the repository at this point in the history
  • Loading branch information
magicant authored Sep 30, 2024
2 parents a223b3b + 2b2f102 commit a67ac2f
Show file tree
Hide file tree
Showing 9 changed files with 75 additions and 36 deletions.
20 changes: 10 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
3 changes: 2 additions & 1 deletion doc/faq.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
10 changes: 6 additions & 4 deletions doc/invoke.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
15 changes: 14 additions & 1 deletion share/initialization/common
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
5 changes: 3 additions & 2 deletions share/initialization/default
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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
Expand Down
3 changes: 2 additions & 1 deletion share/initialization/sample
Original file line number Diff line number Diff line change
@@ -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.


Expand Down
2 changes: 1 addition & 1 deletion tests/run-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions variable.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
52 changes: 36 additions & 16 deletions yash.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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) {
Expand All @@ -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),
Expand All @@ -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);
Expand Down

0 comments on commit a67ac2f

Please sign in to comment.