Write man pages: `man z4h`, `man z4hssh`, etc. --- Implement completions for `z4h`. --- Make `z4h help` more useful. --- Implement `z4h bindkey`. `z4h bindkey -l` should list bindings in a nice table with sections. All widgets should have a human-readable description. `z4h bindkey -L [array]` should list all bindings in `z4h bindkey` command format. If `array` is specified, it's filled with `z4h bindkey` commands that can be passed through `eval`. `-r escseq` should allow binding raw escape sequences. By default should warn when something got unbound. Can be turned off with `-q`. ```zsh zh4 bindkey emacs,viins 'up','ctrl-p' z4h-up-local-history ``` --- `vicmd` has `^P` bound to `up-history` by default. It should probably use bound to the same thing but with local history. `vicmd` has no bindings for global history. It should. --- Add "Try it locally" to docs. Basically, create a directory and make it `ZDOTDIR`. --- Add `z4h replicate [-f] [-b dir] [var=val]...`. It should have its own `:z4h:replicate: files` style. Argument `ZDOTDIR=$HOME` is implied. All zsh startup files that don't exist in the current `ZDOTDIR` should also not exist in the target. `-b ''` disables backup. The default argument is something like `$ZDOTDIR/z4h-backup.date-time`. Files should be stored there with subdirectories all the way from `/`. `-f` causes silent action, including backing up or deleting files. If not set, `z4h replicate` first prints the whole plan of what it's going to do (move this file here, copy that file there, etc.) and asks for confirmation. --- Add `z4h uninstall`. --- Add `install` script that people can download and run. Should have a wizard inside. --- Try to make this work: ```zsh zstyle ':completion:*:manuals' separate-sections true zstyle ':completion:*:manuals.*' insert-sections true ``` `man printf` should show: ```text 1 printf -- general commands 3 printf -- library functions 3p printf -- library functions [POSIX] ``` Maybe this can be done by writing a custom completion function for `man` and enabling it with `compdef`. --- Install `bat`. --- Add options to `z4h chsh`. Perhaps `-v` so that it prints what your login and current shells are and what it's going to do about it. Also add `-r` or something to prevent the creation of `no-chsh`. Maybe `-f` to ignore `no-chsh` and to call `chsh` even if it seems unnecessary. Should return `0` if login shell is current shell or if it successfully changes it. Should return `1` if user says "no" and `2` on errors. --- Move `z4h chsh` to `z4h-chsh`. --- `zcompile` autoloadable files. --- Create `fn` directory similarly to `bin`. Add it to `fpath`. --- Add `:z4h:fzf disable yes`. List: `fzf`, `fzf-bin`, `fzf-tab`, `powerlevel10k`, `extra-completions`, `autosuggestions`, `syntax-highlighting`. This disabled cloning and all usage. --- Add `:z4h:fzf update no`. The list is the same as for `disable` plus `z4h`. --- Add `:z4h:fzf git-clone-flags` and `:z4h:fzf git-pull-flags`. --- Add `-f` to `z4h clone` to force `Z4H_UPDATE=1` behavior. --- Add `z4h download [-f] [-q] [-o file] url` that uses `curl` or `wget`. Respects `Z4H_UPDATE` unless `-f` is specified. --- Add `z4h-recovery-shell`. Copy from https://github.com/zsh4humans/core/blob/master/init.zsh. Bind it to something. Defend against builtins being overridden by functions or disabled. --- Add `_z4h_intro`. Copy from https://github.com/zsh4humans/core/blob/master/init.zsh. --- Add `_z4h_err`. Copy from https://github.com/zsh4humans/core/blob/master/init.zsh. --- Add this: ```zsh zstyle :z4h: hidden-files [ignore|show|recurse] ``` If not `ignore`, should set `dotglob`, add `-A` to `ls`, make `alt-down` and `alt-f` show hidden leaves. `recurse` should make `alt-down` and `alt-f` recurse hidden directories. Will need to find another example of modifying aliases in `.zshrc` (currently it adds `-A` to `ls`). --- Make `cd ` consistent with `alt-down`. --- Check if `alt-f` works on alpine (busybox). --- Add options I like directly to `.zshrc`. They'll also serve as example. (Not sure if there are any that aren't already set in `z4h.zsh`.) --- Check what happens when running `sudo zsh`. Consider adding `$USER` to `$Z4H`. --- Name all private functions like this: `-z4h-foo-bar`. --- Make `-z4h-clone` (or rather `-z4h-clone`) autoloadable. --- Replace `git pull` with `git fetch origin $ref` followed by `git reset --hard origin/$ref`. If the latter fails, try `git clean -df` and repeat `git reset`. If the whole thing fails, try `git clone`. --- `-z4h-clone` should print "installing" or "updating" based on the presence of the target directory. It shouldn't produce additional output on success. --- Restore "downloading z4h.zsh" message in `.zshrc`. --- Change the structure of `$Z4H` to this: ```text . ├── bin ├── romkatv │   └── zsh4humans │   ├── fn │   │   ├── -z4h-clone │   │   └── z4h-help │   ├── main.zsh # defines and calls _z4h_prelude, defines z4h, etc. │   └── z4h.zsh # the same as $Z4H/z4h.zsh but could be newer version; not used ├── zsh-users │   └── zsh-autosuggestions └── z4h.zsh # downloaded by zshrc ``` `z4h.zsh` is in fact a pure POSIX sh script. It looks like this: ```sh if [ -e "$Z4H"/zsh4humans/main.zsh ]; then . "$Z4H"/zsh4humans/main.zsh return fi # git clone, curl or wget romkatv/zsh4humans . "$Z4H"/zsh4humans/main.zsh ``` `romkatv/zsh4humans` shouldn't be hard-coded but derived from `$Z4H_URL`. It's not very important to update this file. The only case where it executes to the end after the initial installation is when `z4h` self-update gets aborted in the very short time window where `romkatv/zsh4humans` is renamed. So it's OK to never update the root `z4h.zsh`. But updating it is also OK (`cp` + `mv` should be easy enough). --- Use src branch of powerlevel10k. When updating, use the following algorithm: - if there is more than one `gitstatus/usrbin/gitstatusd-*`, nuke them all - rename `gitstatus/usrbin/gitstatusd-*` - `git pull` - rename `gitstatus/usrbin/gitstatusd-*` back - run `gitstatus/install` When initializing, check if there is exactly one `gitstatus/usrbin/gitstatusd-*`. If not, nuke all and run `gitstatus/install`. This way `gitstatus/install` is called only when installing or updating, so it's ok if it runs `uname` (by the way, change `gitstatus` to use `uname -sm`). We also avoid downloading `gitstatusd` when it doesn't change. --- Try harder when looking for zsh. Check `command zsh`, `$SHELL`, `/usr/local/bin/zsh`, `/usr/bin/zsh`, `/bin/zsh` and `~/.zsh-bin/bin/zsh`, in this order. --- Add `-z4h-restart` (or `z4h restart`?) and use it instead of plain `exec $_z4h_exe`. This function should check whether `$_z4h_exe` is good before execing it. ```zsh $_z4h_exe -fc '[[ $ZSH_VERSION == (5.<4->*|<6->.*) ]]' ``` Maybe also check that `zmodload zsh/zselect` and `autoload add-zsh-hook` work. If `$_z4h_exe` is not good, try to find a good one. If there aren't any, install zsh-bin. If everything fails, keep current prompt. Basically the same thing as `_z4h_prelude`. --- Use some kind of counter to detect exec loop during initialization. --- Figure out how to allow customization of zsh-bin installation location. This should be defined with `zstyle`, so it won't be available when we actually need to install zsh-bin. Install it to `$Z4H`, `exec` into zsh, and then move zsh-bin to its intended location. Should it be allowed to put zsh-bin in `$Z4H`? One problem with this is that `chsh` becomes very dangerous. OK in ssh though? Probably better to disallow putting zsh-bin under `$XDG_CACHE_HOME` or `~/.cache`. ```zsh zstyle :z4h: zsh-installation-dir /usr/local ~/.local zstyle :z4h:ssh zsh-installation-dir /usr/local ~/.local ``` If there is more than one option, ask the user to choose. Mark options that would require `sudo`. --- Make `persist=1` option in `zstyle :z4h:ssh files` the default and remove support for `persist`. --- Make `LS_COLORS` less obnoxious on NTFS. --- When `main.zsh` is being sourced, traverse the stack to find `.zshrc` and export `ZDOTDIR` pointing to its directory. --- Remove all uses of `$TTY` before `z4h init`. Instead, check `[[ -t 0 && -t 1 ]]`. --- Add this: ```zsh zstyle :z4h:locale lang 'c' 'en_us' 'en_gb' 'en_*' '*' zstyle :z4h:locale force no # if 'no', locale is changed only when encoding is not UTF-8 ``` Set locale early in `z4h install`. --- Add this: ```zsh zstyle :z4h:fzf-tab channel stable zstyle :z4h:syntax-highlighting channel dev zstyle :z4h:powerlevel10k git-ref src zstyle :z4h:fzf-tab:channel stable fca05e66d1c397cb5e72e8b185b1c3d1a0fc063d zstyle :z4h:fzf-tab:channel dev master ``` If `git-ref` is set, it wins. Otherwise commit is derived from `channel`. --- Remove `~/.zshrc` from master branch. --- Add this: ```zsh z4h add-hook --after '*' --before 'foo*' --after 'foobar' preinit powerlevel10k _z4h-powerlevel10k-init arg1 arg2 z4h run-hooks preinit arg3 arg4 z4h preinit ``` - Ordering constraints are applied in the order they are specified. - `z4h preinit` runs `z4h run-hooks preinit`. It complains if executed for the second time. - The precmd hook runs `z4h postinit` if it hasn't run yet. This allows users to run it manually. - If `_z4h_powerlevel10k_init arg1 arg2` is not specified, it defaults to `powerlevel10k`. - It's OK to use `-a` and `-b` instead of `--after` and `--before`. `.zshrc` will look like this: ```zsh . "$Z4H"/z4h.zsh || return z4h use zsh-syntax-highlighting z4h use powerlevel10k z4h install # installs and/or updates everything z4h preinit # enables instant prompt, sources most things, sets parameters, etc. z4h postinit # runs compinit and sources zsh-syntax-highlighting; called from precmd if not called called explicitly ``` `z4h use foo` calls `z4h-use-foo`, which in turn calls `z4h add-hook` a few times and nothing else. --- Add this: ```zsh if z4h use -t powerlevel10k; then # is powerlevel10k used? ... fi ``` --- Add config presets: ```zsh . "$Z4H"/z4h.zsh || return zstyle :z4h: config-version 1.0.0 # <== z4h use zsh-syntax-highlighting z4h use powerlevel10k ... ``` `config-version` can be used by the core code to do things differently but its primary purpose is to set default values of various parameters, styles, options, bindings, etc. All `z4h use` directives should be in `.zshrc`. `z4h install` and `z4h preinit` should also be in `.zshrc`. Everything else should be in preset. --- Make `z4h ssh` use the same directories (`ZDOTDIR`, `Z4H`, etc.) as local. Make setup and teardown configurable through `zstyle`. ```zsh zstyle ':z4h:ssh:*' setup my-ssh-setup function my-ssh-setup() { local ssh_args=("$@") z4h ssh-send-env FOO $foo z4h ssh-send-env BAR z4h ssh-eval 'baz=qux' z4h ssh-send-file -f /foo/bar '$FOO/baz' } ``` All these commands must be applied in the order they are listed. Remote code must be interpreted by zsh (hence `$FOO/baz` is OK without quotes). `ssh-send-file` should be able to send directories. The meaning of trailing slash in source and `destination` should be the same as in `rsync`. --- `z4h ssh` should be able to send history and then to retrieve it. For retrieving there needs to be `teardown` hook similar to `setup`. --- `z4h ssh` should perform setup and interactive connection with these SSH options: ``` -o 'ControlMaster auto' -o 'ControlPath ~/.ssh/control-master-%r@%h:%p' -o 'ControlPersist 10' ``` These can be overridden via zstyle. --- Create `zle-experimental-save-restore-cursor` branch in `zsh`. Sync it to 5.8 and add `fix-sigwinch` code on top. Guard the new code with `ZLE_EXPERIMENTAL_SAVE_RESTORE_CURSOR`. Create a patch from this commit and store it in `zsh-bin`. Modify `build` to apply the patch. Set patchlevel to the commit hash from `zle-experimental-save-restore-cursor`. Add `ZLE_EXPERIMENTAL_SAVE_RESTORE_CURSOR=1` to zsh4humans. --- Add an option to specify the minimum required zsh version. It should also allow specifying that you really want zsh from zsh-bin and not some other zsh 5.8. --- Add these straight to `.zshrc`? ```zsh zstyle ':completion:*' sort false zstyle ':completion:*' list-dirs-first true ``` It would be nice to add `--group-directories-first` to `ls` for consistency but it's tricky because it's not POSIX. --- Figure out if `_approximate` matcher works and whether it's worth it. --- Implement syntax highlighting of preview in `z4h-fzf-history` with `zsh-syntax-highlighting`. To do this, start a companion `zsh` (like in gitstatus), load `zsh-syntax-highlighting` there (make sure to disable widget wrapping as it's very slow) and communicate with it over pipes. --- Replace this status message from `z4h reset`: ```text z4h: cloning zsh4humans/powerlevel10k ``` With this: ```text z4h: cloning romkatv/powerlevel10k ``` --- Revamp vi bindings. See https://github.com/zsh-vi-more/vi-motions and https://github.com/softmoth/zsh-vim-mode. Cursor shape changes should go to p10k? --- When looking for zsh, check `/etc/shells`. If there are several zsh versions installed, pick the one from `PATH`. If it's too old, pick the latest latest from the rest. --- When zsh-bin installs zsh, it should ask whether to add it to /etc/shells. By default it should do this only when the installation directory is world-readable. --- If `ZDOTDIR` is set and doesn't point to `$HOME` when `install` starts, ask whether to install to `$HOME` or `$ZDOTDIR`. Backups should go under the same directory. --- Create `~/.zshenv` with just `setopt no_global_rcs` in it. --- Add `z4h use [-d] [-f] [module]...` where `module` is one of the built-in things: `zsh-users/zsh-autosuggestions`, `bindkey`, `term-title`, etc. Without `-d` modules are added to `_z4h_use_queue`. With `-d` they are added to `_z4h_use_queue_d[-1]`. The latter is an array with nul separated lists as its elements. On `-f` it should install a `precmd` hook called `-z4h-precmd-$#_z4h_install_queue_d` that calls `${(0)_z4h_install_queue_d[${0#-z4h-precmd-}]}`, and call `-z4h-use-rigi $_z4h_use_queue`. `-z4h-use-rigi` should be the same as the current `-z4h-init` with a bunch of conditions added in: ```zsh if (( ${@[(Ie)zsh-users/zsh-autosuggestions]} )); then ... fi ``` It should issue warnings (but not fail) for arguments it doesn't recognize. --- Add this: ```zsh zstyle ':z4h:' preset rigi ``` Could support multiple values for preset "addons". Presets can be used by the core code to do things differently but its primary purpose is to set default values of various parameters, styles, options, bindings, etc. `z4h init` will simply call the preset function -- `-z4h-init-rigi`. The latter will do this: ```zsh local -a mods=() zstyle -T :z4h:zsh-users/zsh-autosuggestion install && mods+=zsh-autosuggestion ... z4h install -f -- $mods local -a mods=() zstyle -T :z4h:compinit use && mods+=compinit ... z4h use -d -- $mods local -a mods=() zstyle -T :z4h:zsh-users/zsh-autosuggestion use && mods+=zsh-autosuggestion ... z4h use -f -- $mods ``` --- Use `fc` to write history in `z4h-stash-buffer`. Might need `fc -p`. --- Support this for local development: ``` zstyle ':z4h:romkatv/powerlevel10k' channel command ln -s ~/powerlevel10k ``` The command is called with an extra argument designating target directory. --- Move the top of `~/.zshrc` to `~/.zshenv`. To make it work, `z4h ssh` will need to start interactive sh. --- Move `$ZDOTDIR` to `~/.zsh`, leave just `~/.zshenv` in the home directory. Also leave a symlink form `~/.zshrc` to `~/.zsh/.zshrc` so that users and bad tools don't get confused. --- When retrieving files in `z4h ssh` and there is no base64 either on local or remote host, use this for encoding: ```zsh od -t x1 -An -v | tr -d '[:space:]' ``` Decode with `sysread`, followed by `print -n -- ${buf//(#m)??/'\x'$MATCH}`. This can be done while reading from the network to speed things up. This encoding has 50% overhead compared to base64. --- Make history over ssh more robust so that it never gets overwritten. --- Protect scripts against rogue aliases as functions as described in the EXAMPLES section of https://pubs.opengroup.org/onlinepubs/9699919799/utilities/command.html. Use `unset -f` on all builtins, too. ```zsh IFS=' ' 'unset' '-f' 'unalias' '[' 'cat' ... 'unalias' '-a' PATH="$(command -p getconf PATH):$PATH" ... ``` This can be broken only by function `unset`. There is a similar but different example at https://pubs.opengroup.org/onlinepubs/9699919799/utilities/env.html. --- Add `z4h pack` that produces `install-z4h` file. It should be similar to the bootstrap script created by `z4h ssh`. It should be all ASCII. It should respect `:z4h:pack:tag extra-files` and similar. `tag` is the value passed via optional `-t tag`. Defaults to emty. This allows one to define different file sets for different packs. By default the same set of files as sent by ssh should be packed, plus all history files. --- Support `fzf` customization via `zstyle`. Add nice support for bindings (including continuous completion and query insertion via fake actions like `z4h-accept-and-repeat` and `z4h-accept-query`). Also allow for low level overrides. ```zsh zstyle :z4h:expand-or-complete:fzf command my-fzf zstyle :z4h:expand-or-complete:fzf bindings ctrl-u:kill-line zstyle :z4h:expand-or-complete:fzf flags --no-exact ``` `flags` and `bindings` have the semantics of *extra* flags and bindings. Extra flags should be added at the front of standard flags because the first flag wins. All flags should be passed to the command (`my-fzf` above) where users can munge them any way they like. Use `--foo=bar` syntax to make it easier to remove flags (one argument -- one flag). Extra bindings could be added at the end of standard bindings because the last binding wins. However, in order to handle fake actions such as `z4h-accept-and-repeat` it'll probably be necessary to resolve binding conflicts within z4h. The goal is to allow this syntax for disabling continuous completion: ```zsh zstyle :z4h:expand-or-complete:fzf extra-bindings tab:ignore ``` `ignore` could be any other legit action. The point is that by default `tab` is bound to `z4h-accept-and-repeat` but we rebind it. --- Support preview customization in fzf. At the very least allow changing the size (down to 0) of preview in history. --- Ctrl+/ is a bad binding on some keyboard layouts. See #35. --- `run-help` has some issues with aliases. See https://github.com/romkatv/zsh4humans/issues/35#issuecomment-657515701. --- Currently `find` for recursive completions is called with `-xdev`. This should be customizable. See https://github.com/romkatv/zsh4humans/issues/35#issuecomment-660477146. --- Define `command_not_found_handler` for more operating systems (similarly to how it's done for Homebrew and Debian). --- `command_not_found_handler` should simultaneously use Homebrew and `/usr/lib/command-not-found` if both are available. --- Make `Alt+{Up,Left,Right}` work within `fzf`. See [this comment]( https://github.com/romkatv/zsh4humans/issues/35#issuecomment-674357739). --- Colorize files in git completions the same way they are shown in `git status`. --- Propagate arguments of `zsh -ic "..."` trhough `exec` when switching to a different zsh. --- Make `run-help z4h source` work. --- `z4h ssh` should start login shell. --- When doing `exec $_z4h_exe`, preserve `-l`. --- Document binding syntax in `z4h help bindkey`. --- Make it safe to continue using an old shell after z4h has been updated in another shell. Assuming that flock works, it can be done as follows. Rename `Z4H` to `Z4H_CACHE_DIR` in `~/.zshenv`. Within `$Z4H_CACHE_DIR` store: - `z4h.zsh` - `last-update-ts` - `no-chsh` - `snapshot-00000000` through `snapshot-ffffffff` `z4h.zsh` should point `Z4H` to the latest snapshot. If there are none, it should create a unique temporary snapshot which would later be transformed into a regular snapshot by `main.zsh`. Preferably this should be the same code path as in `z4h update`. `Z4H_CACHE_DIR` should not propagate through `zsh` the way `Z4H` currently propagates. `Z4H` should still propagate. It seems like there shouldn't be a requirement that `Z4H_CACHE_DIR` gets set to the same value in the child shell created by `z4h update` as in the parent. `main.zsh` should reader-flock its snapshot. If that fails due to the directory being deleted (see below), it should `exec zsh`. Whenever `main.zsh` creates a new snapshot, it should do this while holding a writer-flock on `$Z4H_CACHE_DIR`. `main.zsh` should scan the existing snapshots while holding a writer-flock on `$Z4H_CACHE_DIR` and delete all that can be writer-flocked. On a system where flock always succeeds (WSL1, see https://github.com/Microsoft/WSL/issues/1927), this would make matters much worse than currently thanks to `main.zsh` thinking that all snapshots are unused and deleting them. Special code is required in this case. --- Make this: ```zsh % ls foo/.. ``` Complete to this: ```zsh % ls foo/../ ``` However, `..` should never appear in the listing. In addition, this should work as before: ```zsh touch ..x ls .. ``` It should complete to `ls ..x `. --- The three minor issues with the integrated tmux that I've mentioned in https://github.com/romkatv/zsh4humans/issues/35#issuecomment-719639084 are here: ```text 3a8eb6f08fb26ffdad79dae6f00c9a80ba30ecc0f0ee0a142322005f1d28710a */home/romka/notes/z4h-tmuw-issues.md ``` --- See if it's feasible to fix https://github.com/romkatv/powerlevel10k#horrific-mess-when-resizing-terminal-window by patching tmux. --- `kitty @ launch cat` doesn't work. See https://github.com/romkatv/zsh4humans/issues/35#issuecomment-720134760. --- `new_os_window_with_cwd` doesn't work in Kitty. See https://github.com/romkatv/zsh4humans/issues/35#issuecomment-720134760. --- Make `z4h ssh` work when the target machine doesn't have internet. Implement `z4h fetch` that on a local machine would be a wrapper around `curl`/`wget` and on a remote machine would send a request via the marker to the local. Local machine would fetch the file (via `z4h fetch`, naturally) and upload it via `ssh host 'cat >$dst.$$ && mv $dst.$$ $dst`. The file should have error code, stderr and finally the file. There is `curl` in `~/.zshenv`. In order to deal with that, add one more condition to `~/.zshenv`: ```zsh if command -v z4h >/dev/null 2>&1; then z4h fetch "$Z4H_URL"/z4h.zsh >"$Z4H"/z4h.zsh.$$ elif ... fi ``` `z4h` will be a function that can handle nothing but this command. `z4h fetch` should have a whitelist of URLs it can handle (for security). --- Implement `z4h clipboard-{cut,copy,paste}` that can work over ssh. Add this to `.zshrc`: ```zsh # Should clipboard-related z4h commands on the local host use # the OS clipboard ('system') or a file ('file')? zstyle :z4h: clipboard system # Allow remote hosts access to the clipboard of the client? If set to 'no', # clipboard-related z4h functions on the remote host will use a file. zstyle ':z4h:ssh:*' client-clipboard no # Copy the current command line to clipboard. z4h bindkey z4h-copy-bufer-to-clipboard Ctrl+X alias x='z4h clipboard-copy' # write stdin to clipboard alias c='z4h clipboard-copy' # write stdin to clipboard and to stdout alias v='z4h clipboard-paste' # write clipboard to stdout ``` --- Add `z4h {slurp,barf}` similar to `z4h clipboard-{cut,copy,paste}`. --- Make Ctrl+R display the preview right on the command line. Before opening it, set `BUFFER` to `$'..\n\n\n'` so that it scrolls a bit. --- Set `TERM=screen-256color` by default. Make it easy to override it per-app and the default as well. ```zsh zstyle :z4h:terminfo: term screen-256color zstyle :z4h:terminfo:ssh term screen-256color zstyle :z4h:terminfo:sudo term screen-256color ``` These styles should be consulted only when using tmux with 256 colors. Hm, those styles won't work because we need to define functions for all apps (`ssh`, `sudo`, etc.). This, then? ```zsh zstyle :z4h:tmux term screen-256color zstyle :z4h:tmux force-screen-256color ssh sudo zstyle :z4h:tmux force-tmux-256color kak vi ``` Or maybe hook `TRAPDEBUG` and use the first syntax? Or do it like this: ```zsh zstyle :z4h: term-spec {ssh,sudo,docker}:{tmux-256color:screen-256color,alacritty:xterm-256color} ``` This isn't good. Figure out how to make it possible to add commands without wiping the default ones. --- Profile tmux when printing a ton of data to the terminal and see if there is an easy way to speed it up (likely not). --- `$TTY` is not writable when doing something like this: ```zsh % sudo useradd -ms =zsh test % sudo -iu test % [[ -w $TTY ]] || echo 'not writable' ``` This breaks a bunch of things. For example, Tab doesn't work. To fix this, `dup` one of the standard file descriptors into `_z4h_tty_fd` on startup and use it through the code instead of `$TTY`. --- Change the way Up/Down work with multi-line commands. Pressing Up twice should always have the effect of fetching from history twice, whether the command line was empty or not to begin with. --- Consider changing Up/Down so that it searches for individual words. There is `HISTORY_SUBSTRING_SEARCH_FUZZY=1` for it. --- Add a banner to `~/.zshrc` that requires confirmation. Add the same banner to `install`. When the user consents during the installation, remove the banner from `~/.zshrc`. The banner should say that this is bleeding edge, blah, blah. --- Do not install zsh-bin if the only thing missing from the stock is terminfo. Also remove the requirement for `zsh/pcre`. Better yet, add a `zstyle` for required modules. The goal here is to avoid installing zsh-bin when using macOS Big Sur or having zsh from brew. --- Make zsh-bin work like `tmux -u`. That is, assume UTF-8 always. If there is no UTF-8 locale on the machine (or maybe if the current locale is not UTF-8) require zsh-bin. --- Make integrated tmux work with `TERM=xterm-256color`. --- Remove client-server architecture from the integrated tmux. Would be nice to put it in the same process as zsh but it might make it more difficult to update tmux. For starters it's probably a good idea to have zsh in one process and everything else in another (`z4hd`). Actually, maybe this is a bad idea. Maybe it's better to run `z4hd` the way `tmux` currently runs. Just add `version` to the socket name. The latter can be done right now, without any architectural changes. --- Add a special escape code to the integrated tmux that would allow identifying via a roundtrip to the TTY. Since other terminals won't reply, the logic should be like this: 1. Write "are you integrated tmux". 2. Write "where is cursor". 3. Read the cursor positions. If a special response preceeds it, this is integrated tmux. --- Add `z4h [-r] output` that prints the output of the last command. With `-r` the output is printed without styling (no colors, etc.). Print a warning if the output has more than `N` bytes (or terminal lines?). `N` should be configurable. Implement this by printing a marker in preexec and another in precmd. --- Complain if users override `TERM` when using integrated tmux. --- Figure out better key bindings for macOS. --- If using iTerm2 with the default color scheme, change it to Tango Dark with dark-grey for black. Do it in `p10k configure` for now. --- `z4h ssh` should backup remote files to `~/zsh-backup/ssh`. Each file/directory just once. When backing up, write a message to the tty saying so. Have a `zstyle` to control this. --- List `~/.tmux.conf` in `~/.zshrc` among the files to send over ssh. --- Make it possible for users to tell which commit their zsh4humans is synced to. --- Implement a benchmark that measures the startup time. ```zsh print 'print foo""bar; exit' | script -E never -qec "script -E never -f -T /tmp/timing -qe /tmp/script" /dev/null >/dev/null ``` --- Add a `zstyle` to disable VTE integration. --- Run recovery code from `z4h.zsh` on `precmd` to lower startup lag (perhaps by defining `-z4h-post-init` and later redefining it). This should also solve the problem with custom `HISTFILE` -- just `fc -R` it on recovery. --- When using `su blah -` with the source and the target users both having z4h with integrated tmux, screen gets cleared unnecessarily. See https://github.com/romkatv/zsh4humans/issues/159. This can be fixed by creating world-writable directory `/tmp/z4h-tty` with world-writabable files in it. The names of the files would be derived from `$TTY` of tmux (both integrated and real) and the content would have `$TTY`, `$_Z4H_TMUX`, etc. Note that `$_Z4H_TMUX_CMD` may be unaccessible, so some fallback would be needed. If `$_Z4H_TMUX_CMD` is integrated tmux, then it should be OK to use the integrated tmux from the target user provided that it's compatible. So some version would need to be included in the file. --- Disable builtin `log` in v6. --- Add an ability to set `ZDOTDIR` for remote machines: ```zsh zstyle :z4h:ssh:some-host zdotdir '~/.config/zsh' ``` Consider setting the default value to something other than `$HOME`. A naive solution will break this: ```zsh sudo -su $USER ``` No one's gonna do *that* but there might be other ways of losing `ZDOTDIR` even when it's exported. --- Make the list of traversed directories in `z4h-cd-down` configurable. ```zsh zstyle ':z4h:cd-down' dirs history descendants:. descendants:~ children:/ ``` Could use better naming. Make sure that the `find` command that corresponds to `descendants:~` prunes `.`. Entries from history can be filtered out at the end. --- Add `undo-repeat` action (or a better name) to fzf widgets. It should completely undo `repeat`. Great to bind on Shift+Tab. --- Delete (uninstall) stuff that was installed with `z4h install` and no longer has the corresponding directive. --- When generating a config in p10k under z4h, create trampoline files for more powerful terminals. E.g., when generating `.p10k-ascii-8color.zsh`, create all the other variants that don't exist yet. Adjust the welcome message about tmux. --- Add every `.p10k*.zsh` variant that doesn't exist locally to `z4h_ssh_receive_files`. The idea is to pull configs that get generated remotely. --- If there is no correct `.p10k*.zsh` variant for the TTY but there are variants for less powerful terminals, automatically create trampoline files. --- If there is no correct `.p10k*.zsh` variant for the TTY but there are variants for more powerful terminals, print a message explaning why the configuration wizard is about to start. Maybe also ask for other options? Maybe use a predefined simple config and print a message? --- Create `.tmux.conf` in the installer if there is no existing config and the user chooses "always tmux". --- Find a better solution w.r.t. functions `docker` and `sudo`. --- Change the default values of `:z4h:term-title:ssh` in v6 to these: ```zsh zstyle ':z4h:term-title:ssh' precmd ${${${Z4H_SSH##*:}//\%/%%}:-%m}': %~' zstyle ':z4h:term-title:ssh' preexec ${${${Z4H_SSH##*:}//\%/%%}:-%m}': ${1//\%/%%}' ``` --- Make p10k display `${${${Z4H_SSH##*:}//\%/%%}:-%m}` instead of `%m` in `context`. Not sure how to achieve this without making the default p10k configs more complex. --- When replacing instant prompt with the real thing, it's not necessary to print `ed`. Zsh will do it on its own. Removing this `ed` might reduce the magnitude of blinking. It also might make it possible to get rid of the function call in `PS1`. --- Implement rzw (Roman's Zsh Widgets) in a separate repo. ```zsh # zwords has an even number of elements, all of which are indices into $PREBUFFER$BUFFER. # All odd words (one-based) are whitespace. # $zwords[2*izword-1] is the start position of the word the cursor is pointing to. # $zwords[2*izword] is the end position. # $zword is the actual word. It is technically redundant. rzw-parse-buffer -a zwords -i izword -w zword # Returns 1 if there are no non-whitespace words in $PREBUFFER$BUFFER. # Otherwise returns 0 and sets the specified parameters to the current word, or # the one before it if the current word is whitespace, or the one after it if # there is no previous word. rzw-get-prev-zword -s istart -e iend -w zword # Finds the difference between two strings using Levenshtein distance. # # % rzw-string-diff -a parts -- 'sunday!' 'saturday' # % printf '%-5s => %s\n' ${(qq)parts} # 's' => 's' # '' => 'at' # 'u' => 'u' # 'n' => 'r' # 'day' => 'day' # '!' => '' # # The default values of -m and -M are set like this: # # zstyle :rzw:WIDGET: string-diff-max-complexity 10000 1000000 # # If only one value is set, the second defaults to it. If neither is set, the # values default to 10000 and 1000000. TODO: verify that the second value is # adequate. # # If -c is not specified, it is fetched like this: # # zstyle :rzw:WIDGET: string-diff-cache-file # # Which in turn defaults to this: # # ${XDG_CACHE_HOME:-$HOME/.cache}/rzw-string-diff-$OSTYPE-$CPUTYPE rzw-string-diff -m 10000 -M 1000000 -c CACHE -a parts -- s1 s2 # Compile a C implementation of rzw-string-diff into CACHE (a file). # Does nothing if CACHE is a readable and executable file. # # Refuses to create directories whose parent isn't owned by $USER. # If -c is not specified, its value is resolved as described above. rzw-string-diff -C -c CACHE # Does nothing if istart lies outside of $BUFFER. Otherwise replaces the # specified range with the specified content while keeping the cursor # pointing to the same content as before. rzw-replace-buffer -- istart iend content # Returns 0 if the script is a valid body of a function with the current # options, aliases, etc. Otherwise returns 1. rzw-is-valid-script -- script # Quotes the shell word to the left of the cursor with double or single quotes. # Prefers quotes with the shorter result or double quotes if there is no # difference. If already quoted, changes quotes. If there is an unterminated # quote, terminates it and quotes the resulting word with the same kind of # quotes. Keeps the cursor on the content it was pointing to before the widget # was invoked. # Replaces the shell word to the left of the cursor with the result of the # specified transformation. Keeps the cursor on the content it was pointing to # before the widget was invoked. # # Prior to the transformation the shell word is unquoted. Afterwards it is # quoted while preferring the same kind of quoting that already existed prior # to the transformation. # # bar => /foo/bar # 'bar' => '/foo/bar' # 'bar => '/foo/bar' # $'b\x20r' => $'/foo/b r' # $'b\141r' => $'/foo/bar' # # Note: Pass the original unquoted word as $2? rzw-transform-prev-zword -- 'REPLY=${1:a}' # Example function convert-prev-zword-to-abolute-path() { rzw-transform-prev-zword -- 'REPLY=${1:a}' } zle -N convert-prev-zword-to-abolute-path bindkey '^A' convert-prev-zword-to-abolute-path ``` The buffer is always `$PREBUFFER$BUFFER` and all buffer indices are within it.