From 6248f539db692d666491bb3dd8faca2678d0ef4d Mon Sep 17 00:00:00 2001 From: Ajeet D'Souza <98ajeet@gmail.com> Date: Fri, 9 Apr 2021 00:05:42 +0530 Subject: [PATCH] Add support for Elvish (#174) --- CHANGELOG.md | 5 +++ Cargo.toml | 1 + README.md | 18 ++++++--- shell.nix | 1 + src/cmd/init.rs | 2 + src/shell.rs | 32 +++++++++++++-- templates/bash.txt | 28 +++++++------ templates/elvish.txt | 86 ++++++++++++++++++++++++++++++++++++++++ templates/fish.txt | 33 ++++++++------- templates/nushell.txt | 23 ++++++----- templates/posix.txt | 33 +++++++-------- templates/powershell.txt | 33 +++++++-------- templates/xonsh.txt | 30 +++++++------- templates/zsh.txt | 29 +++++++------- 14 files changed, 243 insertions(+), 111 deletions(-) create mode 100644 templates/elvish.txt diff --git a/CHANGELOG.md b/CHANGELOG.md index c6b60ec..88c6dbd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Support for [Nushell](https://www.nushell.sh/). +- Support for [Elvish](https://elv.sh/). + +### Changed + +- `z` now excludes the current directory from search results. ### Fixed diff --git a/Cargo.toml b/Cargo.toml index c9d655b..fe68fbf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,6 +36,7 @@ default = [] # - bash # - black: # - dash +# - elvish: # - fish: # - mypy: # - nushell: diff --git a/README.md b/README.md index cce127c..b83b854 100644 --- a/README.md +++ b/README.md @@ -112,15 +112,23 @@ zoxide import --from autojump /path/to/db #### bash -Add the following line to your `~/.bashrc`: +Add the following line to your configuration file (usually `~/.bashrc`): ```sh eval "$(zoxide init bash)" ``` +#### elvish + +Add the following line to your configuration file (usually `~/.elvish/rc.elv`): + +```sh +eval $(zoxide init elvish | slurp) +``` + #### fish -Add the following line to your `~/.config/fish/config.fish`: +Add the following line to your configuration file (usually `~/.config/fish/config.fish`): ```fish zoxide init fish | source @@ -154,7 +162,7 @@ Invoke-Expression (& { #### xonsh -Add the following line to your profile (usually `~/.xonshrc`): +Add the following line to your configuration file (usually `~/.xonshrc`): ```python execx($(zoxide init xonsh), 'exec', __xonsh__.ctx, filename='zoxide') @@ -162,7 +170,7 @@ execx($(zoxide init xonsh), 'exec', __xonsh__.ctx, filename='zoxide') #### zsh -Add the following line to your `~/.zshrc`: +Add the following line to your configuration file (usually `~/.zshrc`): ```sh eval "$(zoxide init zsh)" @@ -170,7 +178,7 @@ eval "$(zoxide init zsh)" #### Any POSIX shell -Add the following line to your shell's configuration file: +Add the following line to your configuration file: ```sh eval "$(zoxide init posix --hook prompt)" diff --git a/shell.nix b/shell.nix index 0536653..0d6e86a 100644 --- a/shell.nix +++ b/shell.nix @@ -6,6 +6,7 @@ in pkgs.mkShell { buildInputs = [ pkgs-master.cargo-audit + pkgs-master.elvish pkgs-master.nushell pkgs-python pkgs.bash diff --git a/src/cmd/init.rs b/src/cmd/init.rs index d425a7c..23f3406 100644 --- a/src/cmd/init.rs +++ b/src/cmd/init.rs @@ -50,6 +50,7 @@ impl Cmd for Init { let source = match self.shell { Shell::Bash => shell::Bash(opts).render(), + Shell::Elvish => shell::Elvish(opts).render(), Shell::Fish => shell::Fish(opts).render(), Shell::Nushell => shell::Nushell(opts).render(), Shell::Posix => shell::Posix(opts).render(), @@ -65,6 +66,7 @@ impl Cmd for Init { #[derive(ArgEnum, Debug)] enum Shell { Bash, + Elvish, Fish, Nushell, Posix, diff --git a/src/shell.rs b/src/shell.rs index 7efe609..0aad47d 100644 --- a/src/shell.rs +++ b/src/shell.rs @@ -24,6 +24,7 @@ macro_rules! make_template { } make_template!(Bash, "bash.txt"); +make_template!(Elvish, "elvish.txt"); make_template!(Fish, "fish.txt"); make_template!(Nushell, "nushell.txt"); make_template!(Posix, "posix.txt"); @@ -123,8 +124,7 @@ mod tests { let opts = dbg!(&opts()[i]); let mut source = Bash(opts).render().unwrap(); source.push('\n'); - // FIXME: caused by - let source = source.as_str().trim_start(); + Command::new("shfmt") .args(&["-d", "-s", "-ln", "bash", "-i", "4", "-ci", "-"]) .write_stdin(source) @@ -134,6 +134,31 @@ mod tests { .stderr(""); } + #[test] + fn elvish_elvish_#i() { + let opts = dbg!(&opts()[i]); + let mut source = String::new(); + + // Filter out lines using edit:*, since those functions + // are only available in the interactive editor. + for line in Elvish(opts) + .render() + .unwrap() + .split('\n') + .filter(|line| !line.contains("edit:")) + { + source.push_str(line); + source.push('\n'); + } + + Command::new("elvish") + .args(&["-c", &source, "-norc"]) + .assert() + .success() + .stdout("") + .stderr(""); + } + #[test] fn fish_fish_#i() { let opts = dbg!(&opts()[i]); @@ -238,8 +263,7 @@ mod tests { let opts = dbg!(&opts()[i]); let mut source = Posix(opts).render().unwrap(); source.push('\n'); - // FIXME: caused by - let source = source.as_str().trim_start(); + Command::new("shfmt") .args(&["-d", "-s", "-ln", "posix", "-i", "4", "-ci", "-"]) .write_stdin(source) diff --git a/templates/bash.txt b/templates/bash.txt index 791f401..7909716 100644 --- a/templates/bash.txt +++ b/templates/bash.txt @@ -1,7 +1,7 @@ -{%- let SECTION = "# =============================================================================\n#" -%} -{%- let NOT_CONFIGURED = "# -- not configured --" -%} +{%- let section = "# =============================================================================\n#" -%} +{%- let not_configured = "# -- not configured --" -%} -{{ SECTION }} +{{ section }} # Utility functions for zoxide. # @@ -20,14 +20,14 @@ function __zoxide_cd() { \builtin cd "$@" {%- if echo %} && __zoxide_pwd {%- endif %} } -{{ SECTION }} +{{ section }} # Hook configuration for zoxide. # # Hook to add new entries to the database. {%- match hook %} {%- when Hook::None %} -{{ NOT_CONFIGURED }} +{{ not_configured }} {%- when Hook::Prompt %} function __zoxide_hook() { @@ -44,19 +44,20 @@ function __zoxide_hook() { zoxide add -- "${__zoxide_pwd_old}" fi } + {%- endmatch %} # Initialize hook. if [ "${__zoxide_hooked}" != '1' ]; then __zoxide_hooked='1' - {%- if hook == Hook::None %} - {{ NOT_CONFIGURED }} - {%- else %} +{%- if hook == Hook::None %} + {{ not_configured }} +{%- else %} PROMPT_COMMAND="__zoxide_hook;${PROMPT_COMMAND:+${PROMPT_COMMAND}}" - {%- endif %} +{%- endif %} fi -{{ SECTION }} +{{ section }} # When using zoxide with --no-aliases, alias these internal functions as # desired. # @@ -87,7 +88,7 @@ function __zoxide_zi() { __zoxide_result="$(zoxide query -i -- "$@")" && __zoxide_cd "${__zoxide_result}" } -{{ SECTION }} +{{ section }} # Convenient aliases for zoxide. Disable these using --no-aliases. # @@ -113,11 +114,12 @@ function {{cmd}}i() { } {%- when None %} -{{ NOT_CONFIGURED }} + +{{ not_configured }} {%- endmatch %} -{{ SECTION }} +{{ section }} # To initialize zoxide with bash, add the following line to your bash # configuration file (usually ~/.bashrc): # diff --git a/templates/elvish.txt b/templates/elvish.txt new file mode 100644 index 0000000..b4d2999 --- /dev/null +++ b/templates/elvish.txt @@ -0,0 +1,86 @@ +{%- let section = "# =============================================================================\n#" -%} +{%- let not_configured = "# -- not configured --" -%} + +use builtin +use path + +{{ section }} +# Utility functions for zoxide. +# + +# cd + custom logic based on the value of _ZO_ECHO. +fn __zoxide_cd [path]{ + builtin:cd $path +{%- if echo %} + builtin:echo $pwd +{%- endif %} +} + +{{ section }} +# Hook configuration for zoxide. +# + +if (not (and (builtin:has-env __zoxide_hooked) (builtin:eq (builtin:get-env __zoxide_hooked) 1))) { + builtin:set-env __zoxide_hooked 1 + + # Initialize hook to track previous directory. + builtin:set-env __zoxide_oldpwd $pwd + before-chdir = [$@before-chdir [_]{ builtin:set-env __zoxide_oldpwd $pwd }] + + # Initialize hook to add directories to zoxide. +{%- match hook %} +{%- when Hook::None %} + {{ not_configured }} +{%- when Hook::Prompt %} + edit:before-readline = [$@edit:before-readline []{ zoxide add $pwd }] +{%- when Hook::Pwd %} + after-chdir = [$@after-chdir [_]{ zoxide add $pwd }] +{%- endmatch %} +} + +{{ section }} +# When using zoxide with --no-aliases, alias these internal functions as +# desired. +# + +# Jump to a directory using only keywords. +fn __zoxide_z [@rest]{ + if (builtin:eq [] $rest) { + __zoxide_cd ~ + } elif (builtin:eq [-] $rest) { + __zoxide_cd (builtin:get-env __zoxide_oldpwd) + } elif (and (builtin:eq (builtin:count $rest) 1) (path:is-dir $rest[0])) { + __zoxide_cd $rest[0] + } else { + __zoxide_cd (zoxide query --exclude $pwd -- $@rest) + } +} +edit:add-var __zoxide_z~ $__zoxide_z~ + +# Jump to a directory using interactive search. +fn __zoxide_zi [@rest]{ + __zoxide_cd (zoxide query -i -- $@rest) +} +edit:add-var __zoxide_zi~ $__zoxide_zi~ + +{{ section }} +# Convenient aliases for zoxide. Disable these using --no-aliases. +# + +{%- match cmd %} +{%- when Some with (cmd) %} + +edit:add-var z~ $__zoxide_z~ +edit:add-var zi~ $__zoxide_zi~ + +{%- when None %} + +{{ not_configured }} + +{%- endmatch %} + +{{ section }} +# To initialize zoxide with xonsh, add the following line to your elvish +# configuration file (usually ~/.elvish/rc.elv): +# +# eval $(zoxide init elvish | slurp) diff --git a/templates/fish.txt b/templates/fish.txt index 3d0e8d3..5b31019 100644 --- a/templates/fish.txt +++ b/templates/fish.txt @@ -1,12 +1,10 @@ -{%- let SECTION = "# =============================================================================\n#" -%} -{%- let NOT_CONFIGURED = "# -- not configured --" -%} +{%- let section = "# =============================================================================\n#" -%} +{%- let not_configured = "# -- not configured --" -%} -{{ SECTION }} +{{ section }} # Utility functions for zoxide. # -# Remove definitions. - # pwd based on the value of _ZO_RESOLVE_SYMLINKS. function __zoxide_pwd {%- if resolve_symlinks %} @@ -19,32 +17,32 @@ end # cd + custom logic based on the value of _ZO_ECHO. function __zoxide_cd builtin cd $argv - {%- if echo %} +{%- if echo %} and __zoxide_pwd - {%- endif %} +{%- endif %} and builtin commandline -f repaint end -{{ SECTION }} +{{ section }} # Hook configuration for zoxide. # # Initialize hook to add new entries to the database. if test "$__zoxide_hooked" != 1 set __zoxide_hooked 1 - {%- match hook %} - {%- when Hook::None %} +{%- match hook %} +{%- when Hook::None %} function __zoxide_hook - {%- when Hook::Prompt %} +{%- when Hook::Prompt %} function __zoxide_hook --on-event fish_prompt - {%- when Hook::Pwd %} +{%- when Hook::Pwd %} function __zoxide_hook --on-variable PWD - {%- endmatch %} +{%- endmatch %} command zoxide add -- (__zoxide_pwd) end end -{{ SECTION }} +{{ section }} # When using zoxide with --no-aliases, alias these internal functions as # desired. # @@ -74,7 +72,7 @@ function __zoxide_zi and __zoxide_cd $__zoxide_result end -{{ SECTION }} +{{ section }} # Convenient aliases for zoxide. Disable these using --no-aliases. # @@ -99,11 +97,12 @@ function {{cmd}}i end {%- when None %} -{{ NOT_CONFIGURED }} + +{{ not_configured }} {%- endmatch %} -{{ SECTION }} +{{ section }} # To initialize zoxide with fish, add the following line to your fish # configuration file (usually ~/.config/fish/config.fish): # diff --git a/templates/nushell.txt b/templates/nushell.txt index 5309c71..da786c5 100644 --- a/templates/nushell.txt +++ b/templates/nushell.txt @@ -1,7 +1,7 @@ -{%- let SECTION = "# =============================================================================\n#" -%} -{%- let NOT_CONFIGURED = "# -- not configured --" -%} +{%- let section = "# =============================================================================\n#" -%} +{%- let not_configured = "# -- not configured --" -%} -{{ SECTION }} +{{ section }} # Hook configuration for zoxide. # @@ -22,7 +22,7 @@ printf "zoxide: PWD hooks are not supported on Nushell.\n Use 'zoxide ini {%- endmatch %} -{{ SECTION }} +{{ section }} # When using zoxide with --no-aliases, alias these internal functions as # desired. # @@ -48,21 +48,21 @@ def __zoxide_z [...rest:string] { cd $(zoxide query --exclude $(pwd) -- $args | str trim) } } - {%- if echo %} +{%- if echo %} echo $(pwd) - {%- endif %} +{%- endif %} } # Jump to a directory using interactive search. def __zoxide_zi [...rest:string] { let args = $(echo $rest | skip 1) cd $(zoxide query -i -- $args | str trim) - {%- if echo %} +{%- if echo %} echo $(pwd) - {%- endif %} +{%- endif %} } -{{ SECTION }} +{{ section }} # Convenient aliases for zoxide. Disable these using --no-aliases. # @@ -73,11 +73,12 @@ alias {{cmd}} = __zoxide_z '' alias {{cmd}}i = __zoxide_zi '' {%- when None %} -{{ NOT_CONFIGURED }} + +{{ not_configured }} {%- endmatch %} -{{ SECTION }} +{{ section }} # To initialize zoxide with Nushell: # # Initialize zoxide's Nushell script: diff --git a/templates/posix.txt b/templates/posix.txt index f91b8f7..f5788bc 100644 --- a/templates/posix.txt +++ b/templates/posix.txt @@ -1,7 +1,7 @@ -{%- let SECTION = "# =============================================================================\n#" -%} -{%- let NOT_CONFIGURED = "# -- not configured --" -%} +{%- let section = "# =============================================================================\n#" -%} +{%- let not_configured = "# -- not configured --" -%} -{{ SECTION }} +{{ section }} # Utility functions for zoxide. # @@ -20,14 +20,14 @@ __zoxide_cd() { \cd "$@" {%- if echo %} && __zoxide_pwd {%- endif %} } -{{ SECTION }} +{{ section }} # Hook configuration for zoxide. # # Hook to add new entries to the database. {%- match hook %} {%- when Hook::None %} -{{ NOT_CONFIGURED }} +{{ not_configured }} {%- when Hook::Prompt %} __zoxide_hook() { @@ -35,26 +35,26 @@ __zoxide_hook() { } {%- when Hook::Pwd %} -{{ NOT_CONFIGURED }} +{{ not_configured }} {%- endmatch %} # Initialize hook. if [ "${__zoxide_hooked}" != '1' ]; then __zoxide_hooked='1' - {%- match hook %} - {%- when Hook::None %} - {{ NOT_CONFIGURED }} - {%- when Hook::Prompt %} +{%- match hook %} +{%- when Hook::None %} + {{ not_configured }} +{%- when Hook::Prompt %} PS1="${PS1}\$(__zoxide_hook)" - {%- when Hook::Pwd %} +{%- when Hook::Pwd %} \printf "%s\n%s\n" \ "zoxide: PWD hooks are not supported on POSIX shells." \ " Use 'zoxide init posix --hook prompt' instead." - {%- endmatch %} +{%- endmatch %} fi -{{ SECTION }} +{{ section }} # When using zoxide with --no-aliases, alias these internal functions as # desired. # @@ -83,7 +83,7 @@ __zoxide_zi() { __zoxide_result="$(zoxide query -i -- "$@")" && __zoxide_cd "${__zoxide_result}" } -{{ SECTION }} +{{ section }} # Convenient aliases for zoxide. Disable these using --no-aliases. # @@ -109,11 +109,12 @@ __zoxide_unset '{{cmd}}i' } {%- when None %} -{{ NOT_CONFIGURED }} + +{{ not_configured }} {%- endmatch %} -{{ SECTION }} +{{ section }} # To initialize zoxide with your POSIX shell, add the following line to your # shell configuration file: # diff --git a/templates/powershell.txt b/templates/powershell.txt index 6d31fce..74762eb 100644 --- a/templates/powershell.txt +++ b/templates/powershell.txt @@ -1,7 +1,7 @@ -{%- let SECTION = "# =============================================================================\n#" -%} -{%- let NOT_CONFIGURED = "# -- not configured --" -%} +{%- let section = "# =============================================================================\n#" -%} +{%- let not_configured = "# -- not configured --" -%} -{{ SECTION }} +{{ section }} # Utility functions for zoxide. # @@ -13,12 +13,12 @@ function __zoxide_pwd { # cd + custom logic based on the value of _ZO_ECHO. function __zoxide_cd($dir) { Set-Location $dir -ea Stop - {%- if echo %} +{%- if echo %} __zoxide_pwd - {%- endif %} +{%- endif %} } -{{ SECTION }} +{{ section }} # Hook configuration for zoxide. # @@ -30,16 +30,16 @@ function __zoxide_hook { # Initialize hook. if ($__zoxide_hooked -ne '1') { $__zoxide_hooked = '1' - {%- match hook %} - {%- when Hook::None %} - {{ NOT_CONFIGURED }} - {%- when Hook::Prompt %} +{%- match hook %} +{%- when Hook::None %} + {{ not_configured }} +{%- when Hook::Prompt %} $__zoxide_prompt_old = $function:prompt function prompt { $null = __zoxide_hook & $__zoxide_prompt_old } - {%- when Hook::Pwd %} +{%- when Hook::Pwd %} if ($PSVersionTable.PSVersion.Major -ge 6) { $ExecutionContext.InvokeCommand.LocationChangedAction = { $null = __zoxide_hook @@ -49,10 +49,10 @@ if ($__zoxide_hooked -ne '1') { "zoxide: PWD hooks are not supported below powershell 6.`n" + " Use 'zoxide init powershell --hook prompt' instead.") } - {%- endmatch %} +{%- endmatch %} } -{{ SECTION }} +{{ section }} # When using zoxide with --no-aliases, alias these internal functions as # desired. # @@ -84,7 +84,7 @@ function __zoxide_zi { } } -{{ SECTION }} +{{ section }} # Convenient aliases for zoxide. Disable these using --no-aliases. # @@ -95,11 +95,12 @@ Set-Alias {{cmd}} __zoxide_z Set-Alias {{cmd}}i __zoxide_zi {%- when None %} -{{ NOT_CONFIGURED }} + +{{ not_configured }} {%- endmatch %} -{{ SECTION }} +{{ section }} # To initialize zoxide with powershell, add the following line to your # powershell configuration file (the location is stored in $profile): # diff --git a/templates/xonsh.txt b/templates/xonsh.txt index 7e44dd4..dd19f6d 100644 --- a/templates/xonsh.txt +++ b/templates/xonsh.txt @@ -1,5 +1,5 @@ -{%- let SECTION = "# =============================================================================\n#" -%} -{%- let NOT_CONFIGURED = "# -- not configured --" -%} +{%- let section = "# =============================================================================\n#" -%} +{%- let not_configured = "# -- not configured --" -%} """Initialize zoxide on Xonsh.""" @@ -19,7 +19,7 @@ from typing import AnyStr, List, Optional import xonsh.dirstack # type: ignore # pylint: disable=import-error import xonsh.environ # type: ignore # pylint: disable=import-error -{{ SECTION }} +{{ section }} # Utility functions for zoxide. # @@ -80,22 +80,21 @@ def __zoxide_errhandler(func): return wrapper -{{ SECTION }} +{{ section }} # Hook configuration for zoxide. # # Initialize hook to add new entries to the database. if globals().get("__zoxide_hooked") is not True: globals()["__zoxide_hooked"] = True - - {% match hook -%} - {%- when Hook::None -%} - {{ NOT_CONFIGURED }} - {%- when Hook::Prompt -%} +{% match hook -%} +{%- when Hook::None %} + {{ not_configured }} +{%- when Hook::Prompt %} @events.on_post_prompt # type: ignore # pylint:disable=undefined-variable - {%- when Hook::Pwd -%} +{%- when Hook::Pwd %} @events.on_chdir # type: ignore # pylint:disable=undefined-variable - {%- endmatch %} +{%- endmatch %} def __zoxide_hook(**_kwargs): """Hook to add new entries to the database.""" pwd = __zoxide_pwd() @@ -103,7 +102,7 @@ if globals().get("__zoxide_hooked") is not True: subprocess.run([zoxide, "add", "--", pwd], check=False) -{{ SECTION }} +{{ section }} # When using zoxide with --no-aliases, alias these internal functions as # desired. # @@ -147,7 +146,7 @@ def __zoxide_zi(args: List[str]): __zoxide_cd(__zoxide_result) -{{ SECTION }} +{{ section }} # Convenient aliases for zoxide. Disable these using --no-aliases. # @@ -158,11 +157,12 @@ aliases["{{cmd}}"] = __zoxide_z aliases["{{cmd}}i"] = __zoxide_zi {%- when None %} -{{ NOT_CONFIGURED }} + +{{ not_configured }} {%- endmatch %} -{{ SECTION }} +{{ section }} # To initialize zoxide with xonsh, add the following line to your xonsh # configuration file (usually ~/.xonshrc): # diff --git a/templates/zsh.txt b/templates/zsh.txt index aed3ce2..5d004b2 100644 --- a/templates/zsh.txt +++ b/templates/zsh.txt @@ -1,7 +1,7 @@ -{%- let SECTION = "# =============================================================================\n#" -%} -{%- let NOT_CONFIGURED = "# -- not configured --" -%} +{%- let section = "# =============================================================================\n#" -%} +{%- let not_configured = "# -- not configured --" -%} -{{ SECTION }} +{{ section }} # Utility functions for zoxide. # @@ -20,7 +20,7 @@ function __zoxide_cd() { \builtin cd "$@" {%- if echo %} && __zoxide_pwd {%- endif %} } -{{ SECTION }} +{{ section }} # Hook configuration for zoxide. # @@ -32,17 +32,17 @@ function __zoxide_hook() { # Initialize hook. if [ "${__zoxide_hooked}" != '1' ]; then __zoxide_hooked='1' - {%- match hook %} - {%- when Hook::None %} - {{ NOT_CONFIGURED }} - {%- when Hook::Prompt %} +{%- match hook %} +{%- when Hook::None %} + {{ not_configured }} +{%- when Hook::Prompt %} precmd_functions+=(__zoxide_hook) - {%- when Hook::Pwd %} +{%- when Hook::Pwd %} chpwd_functions=("${chpwd_functions[@]}" "__zoxide_hook") - {%- endmatch %} +{%- endmatch %} fi -{{ SECTION }} +{{ section }} # When using zoxide with --no-aliases, alias these internal functions as # desired. # @@ -74,7 +74,7 @@ function __zoxide_zi() { __zoxide_result="$(zoxide query -i -- "$@")" && __zoxide_cd "${__zoxide_result}" } -{{ SECTION }} +{{ section }} # Convenient aliases for zoxide. Disable these using --no-aliases. # @@ -99,11 +99,12 @@ function {{cmd}}i() { } {%- when None %} -{{ NOT_CONFIGURED }} + +{{ not_configured }} {%- endmatch %} -{{ SECTION }} +{{ section }} # To initialize zoxide with zsh, add the following line to your zsh # configuration file (usually ~/.zshrc): #