Compare commits

...
Sign in to create a new pull request.

3 commits

Author SHA256 Message Date
ce5a34a110
Serious changes 2025-10-10 09:58:16 -04:00
c3415d6f22
btop 2025-10-05 18:07:00 -04:00
fa382a225b
mksh-only 2025-10-05 18:00:36 -04:00
449 changed files with 697 additions and 25843 deletions

257
btop/.config/btop/btop.conf Normal file
View file

@ -0,0 +1,257 @@
#? Config file for btop v. 1.4.5
#* Name of a btop++/bpytop/bashtop formatted ".theme" file, "Default" and "TTY" for builtin themes.
#* Themes should be placed in "../share/btop/themes" relative to binary or "$HOME/.config/btop/themes"
color_theme = "mine"
#* If the theme set background should be shown, set to False if you want terminal background transparency.
theme_background = True
#* Sets if 24-bit truecolor should be used, will convert 24-bit colors to 256 color (6x6x6 color cube) if false.
truecolor = True
#* Set to true to force tty mode regardless if a real tty has been detected or not.
#* Will force 16-color mode and TTY theme, set all graph symbols to "tty" and swap out other non tty friendly symbols.
force_tty = False
#* Define presets for the layout of the boxes. Preset 0 is always all boxes shown with default settings. Max 9 presets.
#* Format: "box_name:P:G,box_name:P:G" P=(0 or 1) for alternate positions, G=graph symbol to use for box.
#* Use whitespace " " as separator between different presets.
#* Example: "cpu:0:default,mem:0:tty,proc:1:default cpu:0:braille,proc:0:tty"
presets = "cpu:1:default,proc:0:default cpu:0:default,mem:0:default,net:0:default cpu:0:block,net:0:tty"
#* Set to True to enable "h,j,k,l,g,G" keys for directional control in lists.
#* Conflicting keys for h:"help" and k:"kill" is accessible while holding shift.
vim_keys = False
#* Rounded corners on boxes, is ignored if TTY mode is ON.
rounded_corners = True
#* Default symbols to use for graph creation, "braille", "block" or "tty".
#* "braille" offers the highest resolution but might not be included in all fonts.
#* "block" has half the resolution of braille but uses more common characters.
#* "tty" uses only 3 different symbols but will work with most fonts and should work in a real TTY.
#* Note that "tty" only has half the horizontal resolution of the other two, so will show a shorter historical view.
graph_symbol = "braille"
# Graph symbol to use for graphs in cpu box, "default", "braille", "block" or "tty".
graph_symbol_cpu = "default"
# Graph symbol to use for graphs in gpu box, "default", "braille", "block" or "tty".
graph_symbol_gpu = "default"
# Graph symbol to use for graphs in cpu box, "default", "braille", "block" or "tty".
graph_symbol_mem = "default"
# Graph symbol to use for graphs in cpu box, "default", "braille", "block" or "tty".
graph_symbol_net = "default"
# Graph symbol to use for graphs in cpu box, "default", "braille", "block" or "tty".
graph_symbol_proc = "default"
#* Manually set which boxes to show. Available values are "cpu mem net proc" and "gpu0" through "gpu5", separate values with whitespace.
shown_boxes = "cpu mem net proc"
#* Update time in milliseconds, recommended 2000 ms or above for better sample times for graphs.
update_ms = 2000
#* Processes sorting, "pid" "program" "arguments" "threads" "user" "memory" "cpu lazy" "cpu direct",
#* "cpu lazy" sorts top process over time (easier to follow), "cpu direct" updates top process directly.
proc_sorting = "cpu lazy"
#* Reverse sorting order, True or False.
proc_reversed = False
#* Show processes as a tree.
proc_tree = False
#* Use the cpu graph colors in the process list.
proc_colors = True
#* Use a darkening gradient in the process list.
proc_gradient = True
#* If process cpu usage should be of the core it's running on or usage of the total available cpu power.
proc_per_core = False
#* Show process memory as bytes instead of percent.
proc_mem_bytes = True
#* Show cpu graph for each process.
proc_cpu_graphs = True
#* Use /proc/[pid]/smaps for memory information in the process info box (very slow but more accurate)
proc_info_smaps = False
#* Show proc box on left side of screen instead of right.
proc_left = False
#* (Linux) Filter processes tied to the Linux kernel(similar behavior to htop).
proc_filter_kernel = False
#* In tree-view, always accumulate child process resources in the parent process.
proc_aggregate = False
#* Sets the CPU stat shown in upper half of the CPU graph, "total" is always available.
#* Select from a list of detected attributes from the options menu.
cpu_graph_upper = "Auto"
#* Sets the CPU stat shown in lower half of the CPU graph, "total" is always available.
#* Select from a list of detected attributes from the options menu.
cpu_graph_lower = "Auto"
#* If gpu info should be shown in the cpu box. Available values = "Auto", "On" and "Off".
show_gpu_info = "Auto"
#* Toggles if the lower CPU graph should be inverted.
cpu_invert_lower = True
#* Set to True to completely disable the lower CPU graph.
cpu_single_graph = False
#* Show cpu box at bottom of screen instead of top.
cpu_bottom = False
#* Shows the system uptime in the CPU box.
show_uptime = True
#* Shows the CPU package current power consumption in watts. Requires running `make setcap` or `make setuid` or running with sudo.
show_cpu_watts = True
#* Show cpu temperature.
check_temp = True
#* Which sensor to use for cpu temperature, use options menu to select from list of available sensors.
cpu_sensor = "Auto"
#* Show temperatures for cpu cores also if check_temp is True and sensors has been found.
show_coretemp = True
#* Set a custom mapping between core and coretemp, can be needed on certain cpus to get correct temperature for correct core.
#* Use lm-sensors or similar to see which cores are reporting temperatures on your machine.
#* Format "x:y" x=core with wrong temp, y=core with correct temp, use space as separator between multiple entries.
#* Example: "4:0 5:1 6:3"
cpu_core_map = ""
#* Which temperature scale to use, available values: "celsius", "fahrenheit", "kelvin" and "rankine".
temp_scale = "celsius"
#* Use base 10 for bits/bytes sizes, KB = 1000 instead of KiB = 1024.
base_10_sizes = False
#* Show CPU frequency.
show_cpu_freq = True
#* Draw a clock at top of screen, formatting according to strftime, empty string to disable.
#* Special formatting: /host = hostname | /user = username | /uptime = system uptime
clock_format = "%X"
#* Update main ui in background when menus are showing, set this to false if the menus is flickering too much for comfort.
background_update = True
#* Custom cpu model name, empty string to disable.
custom_cpu_name = ""
#* Optional filter for shown disks, should be full path of a mountpoint, separate multiple values with whitespace " ".
#* Only disks matching the filter will be shown. Prepend exclude= to only show disks not matching the filter. Examples: disk_filter="/boot /home/user", disks_filter="exclude=/boot /home/user"
disks_filter = ""
#* Show graphs instead of meters for memory values.
mem_graphs = True
#* Show mem box below net box instead of above.
mem_below_net = False
#* Count ZFS ARC in cached and available memory.
zfs_arc_cached = True
#* If swap memory should be shown in memory box.
show_swap = True
#* Show swap as a disk, ignores show_swap value above, inserts itself after first disk.
swap_disk = True
#* If mem box should be split to also show disks info.
show_disks = True
#* Filter out non physical disks. Set this to False to include network disks, RAM disks and similar.
only_physical = True
#* Read disks list from /etc/fstab. This also disables only_physical.
use_fstab = True
#* Setting this to True will hide all datasets, and only show ZFS pools. (IO stats will be calculated per-pool)
zfs_hide_datasets = False
#* Set to true to show available disk space for privileged users.
disk_free_priv = False
#* Toggles if io activity % (disk busy time) should be shown in regular disk usage view.
show_io_stat = True
#* Toggles io mode for disks, showing big graphs for disk read/write speeds.
io_mode = False
#* Set to True to show combined read/write io graphs in io mode.
io_graph_combined = False
#* Set the top speed for the io graphs in MiB/s (100 by default), use format "mountpoint:speed" separate disks with whitespace " ".
#* Example: "/mnt/media:100 /:20 /boot:1".
io_graph_speeds = ""
#* Set fixed values for network graphs in Mebibits. Is only used if net_auto is also set to False.
net_download = 100
net_upload = 100
#* Use network graphs auto rescaling mode, ignores any values set above and rescales down to 10 Kibibytes at the lowest.
net_auto = True
#* Sync the auto scaling for download and upload to whichever currently has the highest scale.
net_sync = True
#* Starts with the Network Interface specified here.
net_iface = ""
#* "True" shows bitrates in base 10 (Kbps, Mbps). "False" shows bitrates in binary sizes (Kibps, Mibps, etc.). "Auto" uses base_10_sizes.
base_10_bitrate = "Auto"
#* Show battery stats in top right if battery is present.
show_battery = True
#* Which battery to use if multiple are present. "Auto" for auto detection.
selected_battery = "Auto"
#* Show power stats of battery next to charge indicator.
show_battery_watts = True
#* Set loglevel for "~/.config/btop/btop.log" levels are: "ERROR" "WARNING" "INFO" "DEBUG".
#* The level set includes all lower levels, i.e. "DEBUG" will show all logging info.
log_level = "WARNING"
#* Measure PCIe throughput on NVIDIA cards, may impact performance on certain cards.
nvml_measure_pcie_speeds = True
#* Measure PCIe throughput on AMD cards, may impact performance on certain cards.
rsmi_measure_pcie_speeds = True
#* Horizontally mirror the GPU graph.
gpu_mirror_graph = True
#* Custom gpu0 model name, empty string to disable.
custom_gpu_name0 = ""
#* Custom gpu1 model name, empty string to disable.
custom_gpu_name1 = ""
#* Custom gpu2 model name, empty string to disable.
custom_gpu_name2 = ""
#* Custom gpu3 model name, empty string to disable.
custom_gpu_name3 = ""
#* Custom gpu4 model name, empty string to disable.
custom_gpu_name4 = ""
#* Custom gpu5 model name, empty string to disable.
custom_gpu_name5 = ""

View file

@ -0,0 +1,83 @@
# Main background, empty for terminal default, need to be empty if you want transparent background
theme[main_bg]="#1b1e2c"
# Main text color
theme[main_fg]="#bfbcb7"
# Title color for boxes
theme[title]="#bfbcb7"
# Highlight color for keyboard shortcuts
theme[hi_fg]="#A55354"
# Background color of selected item in processes box
theme[selected_bg]="#314C52"
# Foreground color of selected item in processes box
theme[selected_fg]="#bfbcb7"
# Color of inactive/disabled text
theme[inactive_fg]="#858380"
# Color of text appearing on top of graphs, i.e uptime and current network graph scaling
theme[graph_text]="#bfbcb7"
# Background color of the percentage meters
theme[meter_bg]="#314C52"
# Misc colors for processes box including mini cpu graphs, details memory graph and details status text
theme[proc_misc]="#446B6E"
# CPU, Memory, Network, Proc box outline colors
theme[cpu_box]="#395E62"
theme[mem_box]="#446B6E"
theme[net_box]="#4E5259"
theme[proc_box]="#395E62"
# Box divider line and small boxes line color
theme[div_line]="#4E5259"
# Temperature graph color (Green -> Yellow -> Red)
theme[temp_start]="#395E62"
theme[temp_mid]="#4E5259"
theme[temp_end]="#A34346"
# CPU graph colors (Teal/Cyan gradient)
theme[cpu_start]="#314C52"
theme[cpu_mid]="#395E62"
theme[cpu_end]="#446B6E"
# Mem/Disk free meter (Teal gradient)
theme[free_start]="#314C52"
theme[free_mid]="#395E62"
theme[free_end]="#446B6E"
# Mem/Disk cached meter (Gray to teal)
theme[cached_start]="#858380"
theme[cached_mid]="#4E5259"
theme[cached_end]="#395E62"
# Mem/Disk available meter (Teal gradient)
theme[available_start]="#395E62"
theme[available_mid]="#446B6E"
theme[available_end]="#446B6E"
# Mem/Disk used meter (Red gradient)
theme[used_start]="#A34346"
theme[used_mid]="#A55354"
theme[used_end]="#A55354"
# Download graph colors (Teal gradient)
theme[download_start]="#314C52"
theme[download_mid]="#395E62"
theme[download_end]="#446B6E"
# Upload graph colors (Rose/Red gradient)
theme[upload_start]="#A34346"
theme[upload_mid]="#A55354"
theme[upload_end]="#A55354"
# Process box color gradient for threads, mem and cpu usage (Teal to Rose)
theme[process_start]="#395E62"
theme[process_mid]="#446B6E"
theme[process_end]="#A55354"

View file

@ -10,7 +10,7 @@
[user] [user]
email = alister@kamikishi.net email = alister@kamikishi.net
name = riomoo name = riomoo
signingkey = /home/moo/.config/ssh/gpg/alisteratkamikishi/id_ed25519.pub signingkey = /home/moo/.local/ssh/alister@kamikishi/id_ed25519.pub
#signingkey = 554AF2CEAE26AC80 #signingkey = 554AF2CEAE26AC80
#email = the7772howaboutyou@protonmail.com #email = the7772howaboutyou@protonmail.com

View file

@ -0,0 +1,11 @@
pinentry-program /usr/bin/pinentry-curses
# Enable OpenSSH Agent (ssh-agent) protocol support.
enable-ssh-support
# Set number of seconds for which cache entries are valid.
default-cache-ttl 99999900 # 5 minutes.
default-cache-ttl-ssh 99999900 # 5 minutes.
max-cache-ttl 99999900 # 15 minutes.
max-cache-ttl-ssh 99999900 # 15 minutes.
#1800

View file

@ -0,0 +1,57 @@
no-greeting
# Use UTF-8 character encoding everywhere.
display-charset utf-8
utf8-strings
# Use GnuPG Agent (gpg-agent) for secret key management.
use-agent
# Don't leak comments or software version information.
no-comments
no-emit-version
fixed-list-mode
verify-options show-uid-validity
list-options show-uid-validity
# Display full fingerprints.
keyid-format long
with-fingerprint
# Default key to use since more than one private key is in the keyring.
# Get public key ID with: gpg --list-secret-keys
# default-key FEC86E49B4437D4D
# default-recipient-self
# flag S
default-key 5A1343DB4CBA9A07FC1FFC02554AF2CEAE26AC80
# flag E
default-recipient A399D6326B9ABB73D81493E74F6CCC6CEFA6DC86
# flag S
#default-key C1CF0AE7E541971401B1DFAFB3E5A185195B76E2
# flag E
#default-recipient 75CA8B25F520599BEF51E2C3B9DB44CC474365B8
# When verifying a signature made from a subkey, require that the
# cross-certification "back signature" on the subkey is present and valid.
require-cross-certification
s2k-mode 3
s2k-count 65011712
s2k-digest-algo SHA512
s2k-cipher-algo AES256
personal-cipher-preferences AES256
personal-digest-preferences SHA512
personal-compress-preferences Uncompressed
cert-digest-algo SHA512
default-preference-list AES256 SHA512 Uncompressed
keyserver hkps://keys.openpgp.org
keyserver-options no-honor-keyserver-url
keyserver-options include-revoked
keyserver-options auto-key-retrieve

View file

@ -0,0 +1,13 @@
# List of allowed ssh keys. Only keys present in this file are used
# in the SSH protocol. The ssh-add tool may add new entries to this
# file to enable them; you may also add them manually. Comment
# lines, like this one, as well as empty lines are ignored. Lines do
# have a certain length limit but this is not serious limitation as
# the format of the entries is fixed and checked by gpg-agent. A
# non-comment line starts with optional white spaces, followed by the
# keygrip of the key given as 40 hex digits, optionally followed by a
# caching TTL in seconds, and another optional field for arbitrary
# flags. Prepend the keygrip with an '!' mark to disable it.
B6A59A97A6A43590F8D1B4486E3C76D8175C2B7D
649CBE230450F01BBC5C9515268468C57D5CAFF2

259
mksh/.config/mksh/mkshrc Normal file
View file

@ -0,0 +1,259 @@
# Place this in: /etc/profile
#export ENV="$HOME/.config/mksh/mkshrc"
# XDG Base Directory variables
export XDG_CONFIG_HOME="${XDG_CONFIG_HOME:-$HOME/.config}"
export XDG_DATA_HOME="${XDG_DATA_HOME:-$HOME/.local/share}"
export XDG_STATE_HOME="${XDG_STATE_HOME:-$HOME/.local/state}"
export XDG_CACHE_HOME="/tmp/${USER}/.cache"
export XINITRC="$XDG_CONFIG_HOME/X11/xinitrc"
export GNUPGHOME="$XDG_DATA_HOME/gnupg"
export XDG_RUNTIME_DIR="$XDG_DATA_HOME/runtime"
export XAUTHORITY="$XDG_RUNTIME_DIR/Xauthority"
export VIMINIT='let $MYVIMRC="$XDG_CONFIG_HOME/vim/vimrc" | source $MYVIMRC'
export PKINIT_ANCHORS="${XDG_DATA_HOME:-$HOME/.local/share}/pki"
export VISUAL=vim
export EDITOR=vim
export QT_QPA_PLATFORMTHEME=qt5ct
export QT_STYLE_OVERRIDE=kvantum
# For GTK apps - use a matching GTK theme
export GTK_THEME=Adwaita:dark # or another GTK theme
# mksh-specific XDG paths
export MKSH_CONFIG_DIR="$XDG_CONFIG_HOME/mksh"
export INPUTRC="$XDG_CONFIG_HOME/readline/inputrc"
export HISTFILE="$XDG_STATE_HOME/mksh/history"
HISTSIZE=5000
# Add local bin to PATH
export PATH="$HOME/.local/bin:$PATH"
# Create directories if they don't exist
[[ -d "$MKSH_CONFIG_DIR" ]] || mkdir -p "$MKSH_CONFIG_DIR"
[[ -d "$XDG_STATE_HOME/mksh" ]] || mkdir -p "$XDG_STATE_HOME/mksh"
[[ -d "$XDG_CACHE_HOME" ]] || mkdir -p "$XDG_CACHE_HOME"
# Source pywal colors if available
if [[ -f "$HOME/.config/themes/using/colors.sh" ]]; then
. "$HOME/.config/themes/using/colors.sh"
# Use standard ANSI colors (compatible everywhere: SSH, TTY, X11)
COLOR_BLUE='\033[34m'
COLOR_GREEN='\033[32m'
COLOR_CYAN='\033[36m'
COLOR_RED='\033[31m'
COLOR_YELLOW='\033[33m'
COLOR_MAGENTA='\033[35m'
COLOR_RESET='\033[0m'
else
# Fallback to basic ANSI colors if pywal colors not available
COLOR_BLUE='\033[34m'
COLOR_GREEN='\033[32m'
COLOR_CYAN='\033[36m'
COLOR_RED='\033[31m'
COLOR_YELLOW='\033[33m'
COLOR_MAGENTA='\033[35m'
COLOR_RESET='\033[0m'
fi
# Git prompt function
git_prompt_info() {
# Check if we're in a git repository
if ! git rev-parse --git-dir >/dev/null 2>&1; then
return
fi
# Get current branch or commit
local branch
branch=$(git symbolic-ref --short HEAD 2>/dev/null || git rev-parse --short HEAD 2>/dev/null)
if [[ -z "$branch" ]]; then
return
fi
# Check if we're in a worktree
local worktree=""
if git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
local git_dir=$(git rev-parse --git-dir 2>/dev/null)
if [[ "$git_dir" == *".git/worktrees"* ]]; then
worktree=" \033[35m[wt]\033[0m"
fi
fi
# Check for dirty status
local dirty=""
if ! git diff --quiet 2>/dev/null || ! git diff --cached --quiet 2>/dev/null; then
dirty="\033[31m*\033[0m"
fi
# Check for untracked files
if [[ -n $(git ls-files --others --exclude-standard 2>/dev/null) ]]; then
dirty="${dirty}\033[33m?\033[0m"
fi
# Check ahead/behind
local ahead_behind=""
local upstream=$(git rev-parse --abbrev-ref @{upstream} 2>/dev/null)
if [[ -n "$upstream" ]]; then
local ahead=$(git rev-list --count @{upstream}..HEAD 2>/dev/null)
local behind=$(git rev-list --count HEAD..@{upstream} 2>/dev/null)
if [[ $ahead -gt 0 ]]; then
ahead_behind="${ahead_behind}\033[32m↑${ahead}\033[0m"
fi
if [[ $behind -gt 0 ]]; then
ahead_behind="${ahead_behind}\033[31m↓${behind}\033[0m"
fi
fi
# Combine everything
print -n " \033[35m(\033[36m${branch}\033[0m${dirty}${ahead_behind}\033[35m)\033[0m${worktree}"
}
# Colorful prompt using ANSI colors with Git info
PS1='$(
# User color (green for normal user, red for root)
if [[ $USER = root ]]; then
print -n "\033[31m$USER\033[0m"
else
print -n "\033[32m$USER\033[0m"
fi
print -n "\033[36m@\033[34m$HOSTNAME\033[0m:"
# Path handling
if [[ "$PWD" = "$HOME" ]]; then
print -n "\033[33m~\033[0m"
elif [[ "$PWD" = "$HOME/"* ]]; then
print -n "\033[33m~${PWD#$HOME}\033[0m"
else
print -n "\033[33m$PWD\033[0m"
fi
# Git info
git_prompt_info
# Prompt character ($ for user, # for root)
if [[ $USER = root ]]; then
print " \033[31m#\033[0m "
else
print " \033[32m\$\033[0m "
fi
)'
# Enable command line editing (emacs-style or vi-style)
set -o emacs # Change to 'set -o vi' for vi-style editing
# Tab completion settings
set -o vi-tabcomplete # Show list of completions
# Enhanced history search
# Ctrl-R for reverse history search (default)
# Ctrl-S for forward history search
bind -m '^S'='^R' # Make Ctrl-S work like Ctrl-R in opposite direction
# Up/Down arrow keys search history based on what you've typed
bind '^[[A'=search-history-up
bind '^[[B'=search-history-down
bind '^[OA'=search-history-up
bind '^[OB'=search-history-down
# Page Up/Down for beginning/end of history
bind '^[[5~'=beginning-of-history
bind '^[[6~'=end-of-history
# Tab completion - cycle through options
bind '^I'=complete
# Custom completions are disabled for speed
# You can enable specific ones if needed, but they slow down shell startup
# Aliases - Basic
alias ls='ls --color=auto'
alias ll='ls -lh'
alias la='ls -lah'
alias l='ls -CF'
alias grep='grep --color=auto'
alias ..='cd ..'
alias ...='cd ../..'
alias ....='cd ../../..'
# Aliases - Safety
alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'
# Aliases - Void Linux specific
alias xi='doas xbps-install -S'
alias xu='doas xbps-install -Su'
alias xr='doas xbps-remove -R'
alias xq='xbps-query'
alias xqs='xbps-query -Rs'
# Aliases - System
alias df='df -h'
alias du='du -h'
alias free='free -h'
alias psg='ps aux | grep -v grep | grep -i -e VSZ -e'
alias sudo='doas'
alias sudoedit='doas rvim'
# FZF Configuration
export FZF_DEFAULT_OPTS=$FZF_DEFAULT_OPTS'
--multi
--height=50%
--margin=5%,2%,2%,5%
--layout=reverse-list
--border=double
--info=inline
--prompt="Æ>"
--pointer="→"
--marker="♡"
--header="CTRL-c or ESC to quit"
--color="dark,fg:magenta"'
# FZF functions (simple approach that works in mksh)
# Usage: Press Ctrl+X then Ctrl+R for history search
# FZF history search - just use this directly
alias fh='fc -l 1 | fzf --tac --no-sort | sed "s/^[ ]*[0-9]*[ ]*//" | sh'
# FZF file finder
alias ff='find . -type f 2>/dev/null | fzf --preview "head -100 {}"'
# FZF directory navigation
fcd() {
local dir
dir=$(find . -type d 2>/dev/null | fzf --preview 'ls -la {}')
[[ -n "$dir" ]] && cd "$dir"
}
# Functions
mkcd() {
mkdir -p "$1" && cd "$1"
}
extract() {
if [[ -f "$1" ]]; then
case "$1" in
*.tar.bz2) tar xjf "$1" ;;
*.tar.gz) tar xzf "$1" ;;
*.bz2) bunzip2 "$1" ;;
*.rar) unrar x "$1" ;;
*.gz) gunzip "$1" ;;
*.tar) tar xf "$1" ;;
*.tbz2) tar xjf "$1" ;;
*.tgz) tar xzf "$1" ;;
*.zip) unzip "$1" ;;
*.Z) uncompress "$1" ;;
*.7z) 7z x "$1" ;;
*) print "'$1' cannot be extracted via extract()" ;;
esac
else
print "'$1' is not a valid file"
fi
}
# Source additional configuration files if they exist
if [[ -d "$MKSH_CONFIG_DIR/conf.d" ]]; then
for conf in "$MKSH_CONFIG_DIR/conf.d/"*.mksh; do
[[ -r "$conf" ]] && . "$conf"
done
fi
# Local machine-specific configuration
[[ -f "$MKSH_CONFIG_DIR/local.mksh" ]] && . "$MKSH_CONFIG_DIR/local.mksh"

View file

@ -0,0 +1,3 @@
#!/bin/mksh
selected=$(find . -type d 2>/dev/null | fzf --preview 'ls -la {}')
[[ -n "$selected" ]] && cd "$selected" && pwd

View file

@ -0,0 +1,3 @@
#!/bin/mksh
selected=$(find . -type f 2>/dev/null | fzf --preview 'head -100 {}')
[[ -n "$selected" ]] && print "$selected"

View file

@ -0,0 +1,3 @@
#!/bin/mksh
selected=$(fc -l 1 | fzf --tac --no-sort | sed 's/^[ ]*[0-9]*[ ]*//')
[[ -n "$selected" ]] && print -s "$selected" && eval "$selected"

View file

@ -1,413 +0,0 @@
#################################
# Shadows #
#################################
# Enabled client-side shadows on windows. Note desktop windows
# (windows with '_NET_WM_WINDOW_TYPE_DESKTOP') never get shadow,
# unless explicitly requested using the wintypes option.
#
# shadow = false
shadow = false;
# The blur radius for shadows, in pixels. (defaults to 12)
# shadow-radius = 12
shadow-radius = 7;
# The opacity of shadows. (0.0 - 1.0, defaults to 0.75)
# shadow-opacity = .75
# The left offset for shadows, in pixels. (defaults to -15)
# shadow-offset-x = -15
shadow-offset-x = -7;
# The top offset for shadows, in pixels. (defaults to -15)
# shadow-offset-y = -15
shadow-offset-y = -7;
# Red color value of shadow (0.0 - 1.0, defaults to 0).
# shadow-red = 0
# Green color value of shadow (0.0 - 1.0, defaults to 0).
# shadow-green = 0
# Blue color value of shadow (0.0 - 1.0, defaults to 0).
# shadow-blue = 0
# Hex string color value of shadow (#000000 - #FFFFFF, defaults to #000000). This option will override options set shadow-(red/green/blue)
# shadow-color = "#000000"
# Specify a list of conditions of windows that should have no shadow.
#
# examples:
# shadow-exclude = "n:e:Notification";
#
# shadow-exclude = []
shadow-exclude = [
"name = 'Notification'",
"class_g = 'Conky'",
"class_g ?= 'Notify-osd'",
"class_g = 'Cairo-clock'",
"_GTK_FRAME_EXTENTS@:c"
];
# Specify a list of conditions of windows that should have no shadow painted over, such as a dock window.
# clip-shadow-above = []
# Specify a X geometry that describes the region in which shadow should not
# be painted in, such as a dock window region. Use
# shadow-exclude-reg = "x10+0+0"
# for example, if the 10 pixels on the bottom of the screen should not have shadows painted on.
#
# shadow-exclude-reg = ""
# Crop shadow of a window fully on a particular Xinerama screen to the screen.
# xinerama-shadow-crop = false
#################################
# Fading #
#################################
# Fade windows in/out when opening/closing and when opacity changes,
# unless no-fading-openclose is used.
# fading = false
fading = false;
# Opacity change between steps while fading in. (0.01 - 1.0, defaults to 0.028)
# fade-in-step = 0.028
fade-in-step = 0.03;
# Opacity change between steps while fading out. (0.01 - 1.0, defaults to 0.03)
# fade-out-step = 0.03
fade-out-step = 0.03;
# The time between steps in fade step, in milliseconds. (> 0, defaults to 10)
# fade-delta = 10
# Specify a list of conditions of windows that should not be faded.
# fade-exclude = []
# Do not fade on window open/close.
# no-fading-openclose = false
# Do not fade destroyed ARGB windows with WM frame. Workaround of bugs in Openbox, Fluxbox, etc.
# no-fading-destroyed-argb = false
#################################
# Transparency / Opacity #
#################################
# Opacity of inactive windows. (0.1 - 1.0, defaults to 1.0)
# inactive-opacity = 1
inactive-opacity = 1;
# Opacity of window titlebars and borders. (0.1 - 1.0, disabled by default)
# frame-opacity = 1.0
frame-opacity = 1;
# Let inactive opacity set by -i override the '_NET_WM_WINDOW_OPACITY' values of windows.
# inactive-opacity-override = true
inactive-opacity-override = false;
# Default opacity for active windows. (0.0 - 1.0, defaults to 1.0)
# active-opacity = 1.0
# Dim inactive windows. (0.0 - 1.0, defaults to 0.0)
# inactive-dim = 0.0
# Specify a list of conditions of windows that should never be considered focused.
# focus-exclude = []
focus-exclude = [ "class_g = 'Cairo-clock'" ];
# Use fixed inactive dim value, instead of adjusting according to window opacity.
# inactive-dim-fixed = 1.0
# Specify a list of opacity rules, in the format `PERCENT:PATTERN`,
# like `50:name *= "Firefox"`. picom-trans is recommended over this.
# Note we don't make any guarantee about possible conflicts with other
# programs that set '_NET_WM_WINDOW_OPACITY' on frame or client windows.
# example:
# opacity-rule = [ "80:class_g = 'URxvt'" ];
#
# opacity-rule = []
#################################
# Corners #
#################################
# Sets the radius of rounded window corners. When > 0, the compositor will
# round the corners of windows. Does not interact well with
# `transparent-clipping`.
corner-radius = 0
# Exclude conditions for rounded corners.
rounded-corners-exclude = [
"window_type = 'dock'",
"window_type = 'desktop'"
];
#################################
# Background-Blurring #
#################################
# Parameters for background blurring, see the *BLUR* section for more information.
# blur-method =
# blur-size = 12
#
# blur-deviation = false
#
# blur-strength = 5
# Blur background of semi-transparent / ARGB windows.
# Bad in performance, with driver-dependent behavior.
# The name of the switch may change without prior notifications.
#
# blur-background = false
# Blur background of windows when the window frame is not opaque.
# Implies:
# blur-background
# Bad in performance, with driver-dependent behavior. The name may change.
#
# blur-background-frame = false
# Use fixed blur strength rather than adjusting according to window opacity.
# blur-background-fixed = false
# Specify the blur convolution kernel, with the following format:
# example:
# blur-kern = "5,5,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1";
#
# blur-kern = ""
blur-kern = "3x3box";
# Exclude conditions for background blur.
# blur-background-exclude = []
blur-background-exclude = [
"window_type = 'dock'",
"window_type = 'desktop'",
"_GTK_FRAME_EXTENTS@:c"
];
#################################
# General Settings #
#################################
# Daemonize process. Fork to background after initialization. Causes issues with certain (badly-written) drivers.
# daemon = false
# Specify the backend to use: `xrender`, `glx`, or `xr_glx_hybrid`.
# `xrender` is the default one.
#
# backend = "glx"
backend = "glx";
# Enable/disable VSync.
# vsync = false
vsync = true;
# Enable remote control via D-Bus. See the *D-BUS API* section below for more details.
# dbus = false
# Try to detect WM windows (a non-override-redirect window with no
# child that has 'WM_STATE') and mark them as active.
#
# mark-wmwin-focused = false
mark-wmwin-focused = true;
# Mark override-redirect windows that doesn't have a child window with 'WM_STATE' focused.
# mark-ovredir-focused = false
mark-ovredir-focused = true;
# Try to detect windows with rounded corners and don't consider them
# shaped windows. The accuracy is not very high, unfortunately.
#
# detect-rounded-corners = false
detect-rounded-corners = true;
# Detect '_NET_WM_WINDOW_OPACITY' on client windows, useful for window managers
# not passing '_NET_WM_WINDOW_OPACITY' of client windows to frame windows.
#
# detect-client-opacity = false
detect-client-opacity = true;
# Use EWMH '_NET_ACTIVE_WINDOW' to determine currently focused window,
# rather than listening to 'FocusIn'/'FocusOut' event. Might have more accuracy,
# provided that the WM supports it.
#
# use-ewmh-active-win = false
# Unredirect all windows if a full-screen opaque window is detected,
# to maximize performance for full-screen windows. Known to cause flickering
# when redirecting/unredirecting windows.
#
# unredir-if-possible = false
# Delay before unredirecting the window, in milliseconds. Defaults to 0.
# unredir-if-possible-delay = 0
# Conditions of windows that shouldn't be considered full-screen for unredirecting screen.
# unredir-if-possible-exclude = []
# Use 'WM_TRANSIENT_FOR' to group windows, and consider windows
# in the same group focused at the same time.
#
# detect-transient = false
detect-transient = true;
# Use 'WM_CLIENT_LEADER' to group windows, and consider windows in the same
# group focused at the same time. This usually means windows from the same application
# will be considered focused or unfocused at the same time.
# 'WM_TRANSIENT_FOR' has higher priority if detect-transient is enabled, too.
#
# detect-client-leader = false
# Resize damaged region by a specific number of pixels.
# A positive value enlarges it while a negative one shrinks it.
# If the value is positive, those additional pixels will not be actually painted
# to screen, only used in blur calculation, and such. (Due to technical limitations,
# with use-damage, those pixels will still be incorrectly painted to screen.)
# Primarily used to fix the line corruption issues of blur,
# in which case you should use the blur radius value here
# (e.g. with a 3x3 kernel, you should use `--resize-damage 1`,
# with a 5x5 one you use `--resize-damage 2`, and so on).
# May or may not work with *--glx-no-stencil*. Shrinking doesn't function correctly.
#
# resize-damage = 1
# Specify a list of conditions of windows that should be painted with inverted color.
# Resource-hogging, and is not well tested.
#
# invert-color-include = []
# GLX backend: Avoid using stencil buffer, useful if you don't have a stencil buffer.
# Might cause incorrect opacity when rendering transparent content (but never
# practically happened) and may not work with blur-background.
# My tests show a 15% performance boost. Recommended.
#
glx-no-stencil = true;
# GLX backend: Avoid rebinding pixmap on window damage.
# Probably could improve performance on rapid window content changes,
# but is known to break things on some drivers (LLVMpipe, xf86-video-intel, etc.).
# Recommended if it works.
#
# glx-no-rebind-pixmap = false
# Disable the use of damage information.
# This cause the whole screen to be redrawn everytime, instead of the part of the screen
# has actually changed. Potentially degrades the performance, but might fix some artifacts.
# The opposing option is use-damage
#
# no-use-damage = false
use-damage = true;
# Use X Sync fence to sync clients' draw calls, to make sure all draw
# calls are finished before picom starts drawing. Needed on nvidia-drivers
# with GLX backend for some users.
#
# xrender-sync-fence = false
# GLX backend: Use specified GLSL fragment shader for rendering window contents.
# See `compton-default-fshader-win.glsl` and `compton-fake-transparency-fshader-win.glsl`
# in the source tree for examples.
#
# glx-fshader-win = ""
# Force all windows to be painted with blending. Useful if you
# have a glx-fshader-win that could turn opaque pixels transparent.
#
# force-win-blend = false
# Do not use EWMH to detect fullscreen windows.
# Reverts to checking if a window is fullscreen based only on its size and coordinates.
#
# no-ewmh-fullscreen = false
# Dimming bright windows so their brightness doesn't exceed this set value.
# Brightness of a window is estimated by averaging all pixels in the window,
# so this could comes with a performance hit.
# Setting this to 1.0 disables this behaviour. Requires --use-damage to be disabled. (default: 1.0)
#
# max-brightness = 1.0
# Make transparent windows clip other windows like non-transparent windows do,
# instead of blending on top of them.
#
# transparent-clipping = false
# Set the log level. Possible values are:
# "trace", "debug", "info", "warn", "error"
# in increasing level of importance. Case doesn't matter.
# If using the "TRACE" log level, it's better to log into a file
# using *--log-file*, since it can generate a huge stream of logs.
#
# log-level = "debug"
log-level = "warn";
# Set the log file.
# If *--log-file* is never specified, logs will be written to stderr.
# Otherwise, logs will to written to the given file, though some of the early
# logs might still be written to the stderr.
# When setting this option from the config file, it is recommended to use an absolute path.
#
# log-file = "/path/to/your/log/file"
# Show all X errors (for debugging)
# show-all-xerrors = false
# Write process ID to a file.
# write-pid-path = "/path/to/your/log/file"
# Window type settings
#
# 'WINDOW_TYPE' is one of the 15 window types defined in EWMH standard:
# "unknown", "desktop", "dock", "toolbar", "menu", "utility",
# "splash", "dialog", "normal", "dropdown_menu", "popup_menu",
# "tooltip", "notification", "combo", and "dnd".
#
# Following per window-type options are available: ::
#
# fade, shadow:::
# Controls window-type-specific shadow and fade settings.
#
# opacity:::
# Controls default opacity of the window type.
#
# focus:::
# Controls whether the window of this type is to be always considered focused.
# (By default, all window types except "normal" and "dialog" has this on.)
#
# full-shadow:::
# Controls whether shadow is drawn under the parts of the window that you
# normally won't be able to see. Useful when the window has parts of it
# transparent, and you want shadows in those areas.
#
# clip-shadow-above:::
# Controls wether shadows that would have been drawn above the window should
# be clipped. Useful for dock windows that should have no shadow painted on top.
#
# redir-ignore:::
# Controls whether this type of windows should cause screen to become
# redirected again after been unredirected. If you have unredir-if-possible
# set, and doesn't want certain window to cause unnecessary screen redirection,
# you can set this to `true`.
#
wintypes:
{
tooltip = { fade = true; shadow = true; opacity = 0.75; focus = true; full-shadow = false; };
dock = { shadow = false; clip-shadow-above = true; }
dnd = { shadow = false; }
popup_menu = { opacity = 0.8; }
dropdown_menu = { opacity = 0.8; }
};

View file

@ -1 +1,2 @@
the7772howaboutyou@protonmail.com namespaces="git" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKQ5H8l8Aevqf1wdAe2E2UiBvUXf/UO1A1zaD6buG4+o openpgp:0x340C78B5 the7772howaboutyou@protonmail.com namespaces="git" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKQ5H8l8Aevqf1wdAe2E2UiBvUXf/UO1A1zaD6buG4+o openpgp:0x340C78B5
alister@kamikishi.net namespaces="git" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJbC8fBoLS4ZWYHK4dPGtgDEbxko1STNU1mWmZSDt4GD openpgp:0x1D877CD6

View file

@ -5,19 +5,6 @@ Host vpn-access
IdentityFile ~/.config/ssh/gpg/the7772/id_ed25519.pub IdentityFile ~/.config/ssh/gpg/the7772/id_ed25519.pub
IdentitiesOnly yes # see NOTES below IdentitiesOnly yes # see NOTES below
Host mine
HostName 192.168.0.157
User moo
Port 22
IdentityFile ~/.config/ssh/websitesmaster/main/id_ed25519
IdentitiesOnly yes # see NOTES below
Host desi
HostName 100.64.0.3
User moo
Port 22
IdentityFile ~/.config/ssh/gpg/the7772/id_ed25519.pub
IdentitiesOnly yes # see NOTES below
Host desi-root Host desi-root
HostName 192.168.0.109 HostName 192.168.0.109
@ -35,13 +22,6 @@ Host convertlaptop-*
RequestTTY yes RequestTTY yes
RemoteCommand tmux new-session -A -s ${%n} RemoteCommand tmux new-session -A -s ${%n}
Host laptop-sync
HostName 192.168.0.208
User moo
Port 22
IdentityFile ~/.config/ssh/gpg/the7772/id_ed25519.pub
IdentitiesOnly yes # see NOTES below
Host convertserver-* Host convertserver-*
HostName 192.168.0.165 HostName 192.168.0.165
User moo User moo
@ -65,55 +45,6 @@ Host websitemaster
IdentityFile ~/.config/ssh/gpg/the7772/id_ed25519.pub IdentityFile ~/.config/ssh/gpg/the7772/id_ed25519.pub
IdentitiesOnly yes # see NOTES below IdentitiesOnly yes # see NOTES below
Host rev-proxy-first-moo-full
HostName 102.223.180.41
User moo
Port 443
IdentityFile ~/.config/ssh/rev-proxy-first/pass/id_ed25519
IdentitiesOnly yes # see NOTES below
Host rev-proxy-first-moo-gpg
HostName 102.223.180.41
User moo
Port 443
IdentityFile ~/.config/ssh/gpg/the7772/id_ed25519.pub
IdentitiesOnly yes # see NOTES below
Host rev-proxy-two-gpg
HostName 184.174.96.157
User moo
Port 443
IdentityFile ~/.config/ssh/gpg/the7772/id_ed25519.pub
IdentitiesOnly yes # see NOTES below
Host rev-proxy-two-sync
HostName 135.148.76.69
User syncy
Port 443
IdentityFile ~/.config/ssh/rev-proxy-first/main/id_ed25519
IdentitiesOnly yes # see NOTES below
Host rev-proxy-first-sync
HostName 102.223.180.41
User syncy
Port 443
IdentityFile ~/.config/ssh/rev-proxy-first/main/id_ed25519
IdentitiesOnly yes # see NOTES below
Host rev-proxy-second-moo-gpg
HostName 161.35.111.10
User moo
Port 443
IdentityFile ~/.config/ssh/gpg/the7772/id_ed25519.pub
IdentitiesOnly yes # see NOTES below
Host rev-proxy-second-sync
HostName 161.35.111.10
User syncy
Port 443
IdentityFile ~/.config/ssh/rev-proxy-second/main/id_ed25519
IdentitiesOnly yes # see NOTES below
Host rev-proxy-third-root Host rev-proxy-third-root
HostName 198.98.62.236 HostName 198.98.62.236
User moo User moo
@ -142,13 +73,6 @@ Host cdnsync
IdentityFile ~/.config/ssh/cdn/main/id_ed25519 IdentityFile ~/.config/ssh/cdn/main/id_ed25519
IdentitiesOnly yes # see NOTES below IdentitiesOnly yes # see NOTES below
Host cdnfull
HostName vids.rioluroom.com
User moo
Port 443
IdentityFile ~/.config/ssh/cdn/pass/id_ed25519
IdentitiesOnly yes # see NOTES below
Host cdn-gpg Host cdn-gpg
HostName vids.rioluroom.com HostName vids.rioluroom.com
User moo User moo
@ -156,27 +80,6 @@ Host cdn-gpg
IdentityFile ~/.config/ssh/gpg/the7772/id_ed25519.pub IdentityFile ~/.config/ssh/gpg/the7772/id_ed25519.pub
IdentitiesOnly yes # see NOTES below IdentitiesOnly yes # see NOTES below
Host cdn-gpg-tail
HostName 100.64.0.5
User moo
Port 443
IdentityFile ~/.config/ssh/gpg/the7772/id_ed25519.pub
IdentitiesOnly yes # see NOTES below
Host cdnipv6
HostName 2605:6400:20:1ff8::1
User moo
Port 443
IdentityFile ~/.config/ssh/cdn/pass/id_ed25519
IdentitiesOnly yes # see NOTES below
Host gitty2up
HostName 135.148.76.69
User git
Port 443
IdentityFile ~/.config/ssh/gpg/the7772/id_ed25519.pub
#IdentityFile ~/.config/ssh/old/id_ed25519
IdentitiesOnly yes # see NOTES below
Host kakiup Host kakiup
HostName git.kaki87.net HostName git.kaki87.net
@ -194,20 +97,6 @@ Host gittyup
#IdentityFile ~/.config/ssh/old/id_ed25519 #IdentityFile ~/.config/ssh/old/id_ed25519
IdentitiesOnly yes # see NOTES below IdentitiesOnly yes # see NOTES below
Host testyyup
HostName localhost
User moo
Port 22
IdentityFile ~/.config/ssh/gpg/the7772/id_ed25519.pub
#IdentityFile ~/.config/ssh/old/id_ed25519
IdentitiesOnly yes # see NOTES below
Host kiwiup
HostName git.kiwifarms.net
User git
Port 22
IdentityFile ~/.config/ssh/old/id_ed25519
IdentitiesOnly yes # see NOTES below
#backup.local #backup.local
Host backup.local Host backup.local
@ -240,16 +129,3 @@ Host riolutv.local
Port 22 Port 22
IdentityFile ~/.config/ssh/old/id_ed25519 IdentityFile ~/.config/ssh/old/id_ed25519
IdentitiesOnly yes # see NOTES below IdentitiesOnly yes # see NOTES below
Host tutorial.local-gpg
HostName 192.168.122.75
User moo
Port 443
IdentityFile ~/.config/ssh/gpg/the7772/id_ed25519.pub
IdentitiesOnly yes
Host tutorial.local
HostName 192.168.122.75
User moo
IdentityFile ~/.config/ssh/gpg/the7772/id_ed25519.pub
IdentitiesOnly yes

View file

@ -1 +1,2 @@
192.168.0.100 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICNFyL6rb/ksObeVeDkUeh2e+g9eAYfD6SRT5hHMjNa8 192.168.0.100 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICNFyL6rb/ksObeVeDkUeh2e+g9eAYfD6SRT5hHMjNa8
192.168.122.1 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBeJXvvopl4NzIYXRP5E+UmUs9j/4UYaZzgh20cMH/2e

@ -0,0 +1 @@
Subproject commit 89139a977271df9b3ae3b26515384a96ad7de88c000000000000000000000000

View file

@ -3,16 +3,6 @@ set -g @plugin 'tmux-plugins/tmux-sensible'
set -g @plugin 'christoomey/vim-tmux-navigator' set -g @plugin 'christoomey/vim-tmux-navigator'
set -g @plugin 'pschmitt/tmux-ssh-split' set -g @plugin 'pschmitt/tmux-ssh-split'
# Other examples:
# set -g @plugin 'github_username/plugin_name'
# set -g @plugin 'github_username/plugin_name#branch'
# set -g @plugin 'git@github.com:user/plugin'
# set -g @plugin 'git@bitbucket.com:user/plugin'
#set -g @plugin "arcticicestudio/nord-tmux"
#set -g default-terminal "st-256color"
#set -g @plugin 'wfxr/tmux-power'
#set -g @tmux_power_theme 'default'
#set -g status-style fg=white,bg=black
# ---------------------- # ----------------------
# Status Bar # Status Bar
@ -40,15 +30,8 @@ set -g status-right-length 60
set -g status-right "#[fg=blue]#S #I:#P #[fg=yellow]: %d %b %Y #[fg=green]: %l:%M %p : #(date -u | awk '{print $4}') :" set -g status-right "#[fg=blue]#S #I:#P #[fg=yellow]: %d %b %Y #[fg=green]: %l:%M %p : #(date -u | awk '{print $4}') :"
set -g status-right "#[fg=blue]#(tmux-cpu --no-color)" set -g status-right "#[fg=blue]#(tmux-cpu --no-color)"
# mouse mode (commented lines for old versions of tmux)
# setw -g mode-mouse on
# set -g mouse-resize-pane on
# set -g mouse-select-pane on
# set -g mouse-select-window on
# key bindings
# divider color # divider color
set -g default-terminal "xterm-256color" set -g default-terminal "st-256color"
unbind r unbind r
bind r source-file /home/moo/.config/tmux/tmux.conf bind r source-file /home/moo/.config/tmux/tmux.conf

View file

@ -1,2 +0,0 @@
Xcursor.theme: oreo_nord_snow_1_cursors
Xcursor.size: 16

10
x11/.config/X11/xinitrc Executable file → Normal file
View file

@ -1,9 +1,5 @@
#!/bin/sh if test -z "$DBUS_SESSION_BUS_ADDRESS"; then
XDG_SESSION_TYPE="x11" eval $(dbus-launch --sh-syntax --exit-with-session)
USERXSESSION="$XDG_CACHE_HOME/X11/xsession" fi
USERXSESSIONRC="$XDG_CACHE_HOME/X11/xsessionrc"
ALTUSERXSESSION="$XDG_CACHE_HOME/X11/Xsession"
ERRFILE="$XDG_CACHE_HOME/X11/xsession-errors"
[ -f ~/.config/X11/xprofile ] && . ~/.config/X11/xprofile [ -f ~/.config/X11/xprofile ] && . ~/.config/X11/xprofile
#exec dminiwm
exec dwm exec dwm

View file

@ -1,11 +1,6 @@
#paperview $HOME/.local/media/vids/Backgrounds/ankha-walk 10 &
#xgifwallpaper -d 3 -s FILL /home/moo/.local/media/pics/Backgrounds/background.gif &
#dunst &
#xcompmgr -c &
fastcompmgr -o 0.4 -r 12 -c -C & fastcompmgr -o 0.4 -r 12 -c -C &
setxkbmap -option ctrl:nocaps & setxkbmap -option ctrl:nocaps &
dwmblocks & dwmblocks &
#xrandr --verbose --output eDP --mode 2560x1440
hsetroot -full $HOME/.local/media/pics/wallpapers/default & hsetroot -full $HOME/.local/media/pics/wallpapers/default &
xset s off xset s off
xset -dpms xset -dpms

File diff suppressed because it is too large Load diff

View file

@ -1,43 +0,0 @@
if [ ${USER} ]; then
export ZDOTDIR="$HOME/.config/zsh"
export BUP_DIR="/mnt/major/.bup"
export XCURSOR_PATH=/usr/share/icons:${XDG_DATA_HOME}/icons
#export XCURSOR_THEME="oreo_nord_snow_3_cursors"
export XCURSOR_SIZE="16"
export PATH="$(find $HOME/.local/bin $HOME/.local/share/cargo/bin -type d | tr '\n' ':' | sed 's/:$//'):$PATH"
export XDG_DATA_HOME="$HOME/.local/share"
export XDG_CONFIG_HOME="$HOME/.config"
export XDG_STATE_HOME="$HOME/.local/state"
export XDG_CACHE_HOME="/tmp/${USER}/.cache"
#export XDG_CACHE_HOME="$HOME/.cache"
export XINITRC="$XDG_CONFIG_HOME/X11/xinitrc"
export GNUPGHOME="$XDG_DATA_HOME/gnupg"
export WINEPREFIX="$XDG_DATA_HOME/wine"
export VIMINIT='let $MYVIMRC="$XDG_CONFIG_HOME/vim/vimrc" | source $MYVIMRC'
export GTK2_RC_FILES="$XDG_CONFIG_HOME/gtk-2.0/gtkrc"
export GTK_THEME="oomox-colors-oomox"
export ELECTRUMDIR="$XDG_DATA_HOME/electrum"
export CARGO_HOME="$XDG_DATA_HOME/cargo"
export WGETRC="$XDG_CONFIG_HOME/wgetrc"
export XAUTHORITY="$XDG_RUNTIME_DIR/Xauthority"
export NPM_CONFIG_USERCONFIG="$XDG_CONFIG_HOME/npm/config/.npmrc"
#export QT_STYLE_OVERRIDE=kvantum
export QT_QPA_PLATFORMTHEME=gtk2
export QT_STYLE_OVERRIDE=gtk2
export XDG_CURRENT_DESKTOP=KDE
export NB_ENCRYPTION_TOOL=gpg
export NB_DIR="$XDG_DATA_HOME/nb"
export NBRC_PATH="$XDG_CONFIG_HOME/nbrc"
export BAT_THEME="base16"
unset SSH_AGENT_PID
if [ "${gnupg_SSH_AUTH_SOCK_by:-0}" -ne $$ ]; then
export SSH_AUTH_SOCK="$(gpgconf --list-dirs agent-ssh-socket)"
fi
export GPG_TTY=$(tty)
gpg-connect-agent updatestartuptty /bye >/dev/null
#export GPG_AGENT_INFO=""
export PASS=$HOME/.local/media/mnt/cont/.tmp/.bmpass
export DMY=$(date +%y-%b-%d-%a-week-%U_%H-%M-%S)
export PASSWORD_STORE_DIR="$XDG_DATA_HOME/password-store"
#export CLUTTER_PAINT=disable-clipped-redraws:disable-culling
fi

View file

@ -1,113 +0,0 @@
# export ZDOTDIR=$HOME/.config/zsh
# source "$HOME/.config/zsh/.zshrc"
#!/bin/sh
export PF_SEP=" ~"
export PF_INFO="ascii os kernel wm editor shell pkgs"
source /home/moo/.config/themes/using/colors.sh
export FZF_DEFAULT_OPTS=$FZF_DEFAULT_OPTS'
--multi
--height=50%
--margin=5%,2%,2%,5%
--layout=reverse-list
--border=double
--info=inline
--prompt="Ɛ>"
--pointer="→"
--marker="♡"
--header="CTRL-c or ESC to quit"
--color="dark,fg:magenta"'
#export FZF_DEFAULT_OPTS=$FZF_DEFAULT_OPTS'
# --color=fg:#d8dee9,bg:-1,hl:#5e81ac
# --color=fg+:#d8dee9,bg+:#4c566a,hl+:#81a1c1
# --color=info:#ebcb8b,prompt:#5e81ac,pointer:#5e81ac
# --color=marker:#d8dee9,spinner:#5e81ac,header:#5e81ac
# --color=border:#d8dee9'
#sleep 0.05
pfetch
#echo " REMEMBER YOU IDIOT!"
#echo "  $($HOME/.local/bin/batterycheck)"
#files=( /home/moo/dox/txt-files/banners/*(noe['REPLY=$RANDOM']) )
#cat $files # or $files[1]
#cat $files[1]
HISTFILE="$XDG_DATA_HOME"/zsh/history
HISTSIZE=10000000
SAVEHIST=10000000
setopt share_history
# some useful options (man zshoptions)
setopt autocd extendedglob nomatch menucomplete
setopt interactive_comments
stty stop undef # Disable ctrl-s to freeze terminal.
zle_highlight=('paste:none')
# beeping is annoying
unsetopt BEEP
# completions
autoload -Uz compinit
zstyle ':completion:*' menu select
# zstyle ':completion::complete:lsof:*' menu yes select
zmodload zsh/complist
# compinit
_comp_options+=(globdots) # Include hidden files.
autoload -U up-line-or-beginning-search
autoload -U down-line-or-beginning-search
zle -N up-line-or-beginning-search
zle -N down-line-or-beginning-search
# Colors
autoload -Uz colors && colors
# Useful Functions
source "$ZDOTDIR/zsh-functions"
# Normal files to source
zsh_add_file "zsh-exports"
zsh_add_file "zsh-vim-mode"
zsh_add_file "zsh-aliases"
zsh_add_file "zsh-prompt"
# Plugins
zsh_add_plugin "zsh-users/zsh-autosuggestions"
zsh_add_plugin "zsh-users/zsh-syntax-highlighting"
zsh_add_plugin "hlissner/zsh-autopair"
zsh_add_completion "esc/conda-zsh-completion" false
# For more plugins: https://github.com/unixorn/awesome-zsh-plugins
# More completions https://github.com/zsh-users/zsh-completions
# Key-bindings
bindkey -s '^o' 'fzffm^M'
bindkey -s '^f' 'zi^M'
bindkey -s '^s' 'ncdu^M'
# bindkey -s '^n' 'nvim $(fzf)^M'
# bindkey -s '^v' 'nvim\n'
bindkey -s '^z' 'zi^M'
bindkey '^[[P' delete-char
bindkey "^p" up-line-or-beginning-search # Up
bindkey "^n" down-line-or-beginning-search # Down
bindkey "^k" up-line-or-beginning-search # Up
bindkey "^j" down-line-or-beginning-search # Down
bindkey -r "^u"
bindkey -r "^d"
# FZF
# TODO update for mac
[ -f $ZDOTDIR/completion/_fnm ] && fpath+="$ZDOTDIR/completion/"
# export FZF_DEFAULT_COMMAND='rg --hidden -l ""'
compinit
# Edit line in vim with ctrl-e:
autoload edit-command-line; zle -N edit-command-line
# bindkey '^e' edit-command-line
# Environment variables set everywhere
export EDITOR="vim"
export TERMINAL="st"
export BROWSER="firefox"
# For QT Themes
export QT_QPA_PLATFORMTHEME=qt5ct
#[[ -e $HOME/.config/.dircolors ]] && eval "`dircolors --sh $HOME/.config/.dircolors`"
#[ -f ~/.fzf.zsh ] && source ~/.fzf.zsh

View file

@ -1,357 +0,0 @@
#compdef fnm
autoload -U is-at-least
_fnm() {
typeset -A opt_args
typeset -a _arguments_options
local ret=1
if is-at-least 5.2; then
_arguments_options=(-s -S -C)
else
_arguments_options=(-s -C)
fi
local context curcontext="$curcontext" state line
_arguments "${_arguments_options[@]}" \
'--node-dist-mirror=[https://nodejs.org/dist/ mirror]' \
'--fnm-dir=[The root directory of fnm installations]' \
'--multishell-path=[Where the current node version link is stored. This value will be populated automatically by evaluating `fnm env` in your shell profile. Read more about it using `fnm help env`]' \
'--log-level=[The log level of fnm commands]' \
'--arch=[Override the architecture of the installed Node binary. Defaults to arch of fnm binary]' \
'-h[Prints help information]' \
'--help[Prints help information]' \
'-V[Prints version information]' \
'--version[Prints version information]' \
":: :_fnm_commands" \
"*::: :->fnm" \
&& ret=0
case $state in
(fnm)
words=($line[1] "${words[@]}")
(( CURRENT += 1 ))
curcontext="${curcontext%:*:*}:fnm-command-$line[1]:"
case $line[1] in
(ls-remote)
_arguments "${_arguments_options[@]}" \
'--node-dist-mirror=[https://nodejs.org/dist/ mirror]' \
'--fnm-dir=[The root directory of fnm installations]' \
'--log-level=[The log level of fnm commands]' \
'--arch=[Override the architecture of the installed Node binary. Defaults to arch of fnm binary]' \
'-h[Prints help information]' \
'--help[Prints help information]' \
'-V[Prints version information]' \
'--version[Prints version information]' \
&& ret=0
;;
(list-remote)
_arguments "${_arguments_options[@]}" \
'--node-dist-mirror=[https://nodejs.org/dist/ mirror]' \
'--fnm-dir=[The root directory of fnm installations]' \
'--log-level=[The log level of fnm commands]' \
'--arch=[Override the architecture of the installed Node binary. Defaults to arch of fnm binary]' \
'-h[Prints help information]' \
'--help[Prints help information]' \
'-V[Prints version information]' \
'--version[Prints version information]' \
&& ret=0
;;
(ls)
_arguments "${_arguments_options[@]}" \
'--node-dist-mirror=[https://nodejs.org/dist/ mirror]' \
'--fnm-dir=[The root directory of fnm installations]' \
'--log-level=[The log level of fnm commands]' \
'--arch=[Override the architecture of the installed Node binary. Defaults to arch of fnm binary]' \
'-h[Prints help information]' \
'--help[Prints help information]' \
'-V[Prints version information]' \
'--version[Prints version information]' \
&& ret=0
;;
(list)
_arguments "${_arguments_options[@]}" \
'--node-dist-mirror=[https://nodejs.org/dist/ mirror]' \
'--fnm-dir=[The root directory of fnm installations]' \
'--log-level=[The log level of fnm commands]' \
'--arch=[Override the architecture of the installed Node binary. Defaults to arch of fnm binary]' \
'-h[Prints help information]' \
'--help[Prints help information]' \
'-V[Prints version information]' \
'--version[Prints version information]' \
&& ret=0
;;
(install)
_arguments "${_arguments_options[@]}" \
'--node-dist-mirror=[https://nodejs.org/dist/ mirror]' \
'--fnm-dir=[The root directory of fnm installations]' \
'--log-level=[The log level of fnm commands]' \
'--arch=[Override the architecture of the installed Node binary. Defaults to arch of fnm binary]' \
'--lts[Install latest LTS]' \
'-h[Prints help information]' \
'--help[Prints help information]' \
'-V[Prints version information]' \
'--version[Prints version information]' \
'::version -- A version string. Can be a partial semver or a LTS version name by the format lts/NAME:_files' \
&& ret=0
;;
(use)
_arguments "${_arguments_options[@]}" \
'--node-dist-mirror=[https://nodejs.org/dist/ mirror]' \
'--fnm-dir=[The root directory of fnm installations]' \
'--log-level=[The log level of fnm commands]' \
'--arch=[Override the architecture of the installed Node binary. Defaults to arch of fnm binary]' \
'--install-if-missing[Install the version if it isn'\''t installed yet]' \
'-h[Prints help information]' \
'--help[Prints help information]' \
'-V[Prints version information]' \
'--version[Prints version information]' \
'::version:_files' \
&& ret=0
;;
(env)
_arguments "${_arguments_options[@]}" \
'--shell=[The shell syntax to use. Infers when missing]: :(bash zsh fish powershell)' \
'--node-dist-mirror=[https://nodejs.org/dist/ mirror]' \
'--fnm-dir=[The root directory of fnm installations]' \
'--log-level=[The log level of fnm commands]' \
'--arch=[Override the architecture of the installed Node binary. Defaults to arch of fnm binary]' \
'--multi[Deprecated. This is the default now]' \
'--use-on-cd[Print the script to change Node versions every directory change]' \
'-h[Prints help information]' \
'--help[Prints help information]' \
'-V[Prints version information]' \
'--version[Prints version information]' \
&& ret=0
;;
(completions)
_arguments "${_arguments_options[@]}" \
'--shell=[The shell syntax to use. Infers when missing]: :(zsh bash fish powershell elvish)' \
'--node-dist-mirror=[https://nodejs.org/dist/ mirror]' \
'--fnm-dir=[The root directory of fnm installations]' \
'--log-level=[The log level of fnm commands]' \
'--arch=[Override the architecture of the installed Node binary. Defaults to arch of fnm binary]' \
'-h[Prints help information]' \
'--help[Prints help information]' \
'-V[Prints version information]' \
'--version[Prints version information]' \
&& ret=0
;;
(alias)
_arguments "${_arguments_options[@]}" \
'--node-dist-mirror=[https://nodejs.org/dist/ mirror]' \
'--fnm-dir=[The root directory of fnm installations]' \
'--log-level=[The log level of fnm commands]' \
'--arch=[Override the architecture of the installed Node binary. Defaults to arch of fnm binary]' \
'-h[Prints help information]' \
'--help[Prints help information]' \
'-V[Prints version information]' \
'--version[Prints version information]' \
':to-version:_files' \
':name:_files' \
&& ret=0
;;
(default)
_arguments "${_arguments_options[@]}" \
'--node-dist-mirror=[https://nodejs.org/dist/ mirror]' \
'--fnm-dir=[The root directory of fnm installations]' \
'--log-level=[The log level of fnm commands]' \
'--arch=[Override the architecture of the installed Node binary. Defaults to arch of fnm binary]' \
'-h[Prints help information]' \
'--help[Prints help information]' \
'-V[Prints version information]' \
'--version[Prints version information]' \
':version:_files' \
&& ret=0
;;
(current)
_arguments "${_arguments_options[@]}" \
'--node-dist-mirror=[https://nodejs.org/dist/ mirror]' \
'--fnm-dir=[The root directory of fnm installations]' \
'--log-level=[The log level of fnm commands]' \
'--arch=[Override the architecture of the installed Node binary. Defaults to arch of fnm binary]' \
'-h[Prints help information]' \
'--help[Prints help information]' \
'-V[Prints version information]' \
'--version[Prints version information]' \
&& ret=0
;;
(exec)
_arguments "${_arguments_options[@]}" \
'--using=[Either an explicit version, or a filename with the version written in it]' \
'--node-dist-mirror=[https://nodejs.org/dist/ mirror]' \
'--fnm-dir=[The root directory of fnm installations]' \
'--log-level=[The log level of fnm commands]' \
'--arch=[Override the architecture of the installed Node binary. Defaults to arch of fnm binary]' \
'--using-file[Deprecated. This is the default now]' \
'-h[Prints help information]' \
'--help[Prints help information]' \
'-V[Prints version information]' \
'--version[Prints version information]' \
'::arguments -- The command to run:_files' \
&& ret=0
;;
(uninstall)
_arguments "${_arguments_options[@]}" \
'--node-dist-mirror=[https://nodejs.org/dist/ mirror]' \
'--fnm-dir=[The root directory of fnm installations]' \
'--log-level=[The log level of fnm commands]' \
'--arch=[Override the architecture of the installed Node binary. Defaults to arch of fnm binary]' \
'-h[Prints help information]' \
'--help[Prints help information]' \
'-V[Prints version information]' \
'--version[Prints version information]' \
'::version:_files' \
&& ret=0
;;
(help)
_arguments "${_arguments_options[@]}" \
'--node-dist-mirror=[https://nodejs.org/dist/ mirror]' \
'--fnm-dir=[The root directory of fnm installations]' \
'--log-level=[The log level of fnm commands]' \
'--arch=[Override the architecture of the installed Node binary. Defaults to arch of fnm binary]' \
'-h[Prints help information]' \
'--help[Prints help information]' \
'-V[Prints version information]' \
'--version[Prints version information]' \
&& ret=0
;;
esac
;;
esac
}
(( $+functions[_fnm_commands] )) ||
_fnm_commands() {
local commands; commands=(
"list-remote:List all remote Node.js versions" \
"ls-remote:List all remote Node.js versions" \
"list:List all locally installed Node.js versions" \
"ls:List all locally installed Node.js versions" \
"install:Install a new Node.js version" \
"use:Change Node.js version" \
"env:Print and set up required environment variables for fnm" \
"completions:Print shell completions to stdout" \
"alias:Alias a version to a common name" \
"default:Set a version as the default version" \
"current:Print the current Node.js version" \
"exec:Run a command within fnm context" \
"uninstall:Uninstall a Node.js version" \
"help:Prints this message or the help of the given subcommand(s)" \
)
_describe -t commands 'fnm commands' commands "$@"
}
(( $+functions[_fnm__alias_commands] )) ||
_fnm__alias_commands() {
local commands; commands=(
)
_describe -t commands 'fnm alias commands' commands "$@"
}
(( $+functions[_fnm__completions_commands] )) ||
_fnm__completions_commands() {
local commands; commands=(
)
_describe -t commands 'fnm completions commands' commands "$@"
}
(( $+functions[_fnm__current_commands] )) ||
_fnm__current_commands() {
local commands; commands=(
)
_describe -t commands 'fnm current commands' commands "$@"
}
(( $+functions[_fnm__default_commands] )) ||
_fnm__default_commands() {
local commands; commands=(
)
_describe -t commands 'fnm default commands' commands "$@"
}
(( $+functions[_fnm__env_commands] )) ||
_fnm__env_commands() {
local commands; commands=(
)
_describe -t commands 'fnm env commands' commands "$@"
}
(( $+functions[_fnm__exec_commands] )) ||
_fnm__exec_commands() {
local commands; commands=(
)
_describe -t commands 'fnm exec commands' commands "$@"
}
(( $+functions[_fnm__help_commands] )) ||
_fnm__help_commands() {
local commands; commands=(
)
_describe -t commands 'fnm help commands' commands "$@"
}
(( $+functions[_fnm__install_commands] )) ||
_fnm__install_commands() {
local commands; commands=(
)
_describe -t commands 'fnm install commands' commands "$@"
}
(( $+functions[_fnm__list_commands] )) ||
_fnm__list_commands() {
local commands; commands=(
)
_describe -t commands 'fnm list commands' commands "$@"
}
(( $+functions[_fnm__list-remote_commands] )) ||
_fnm__list-remote_commands() {
local commands; commands=(
)
_describe -t commands 'fnm list-remote commands' commands "$@"
}
(( $+functions[_fnm__ls_commands] )) ||
_fnm__ls_commands() {
local commands; commands=(
)
_describe -t commands 'fnm ls commands' commands "$@"
}
(( $+functions[_ls_commands] )) ||
_ls_commands() {
local commands; commands=(
)
_describe -t commands 'ls commands' commands "$@"
}
(( $+functions[_fnm__ls-remote_commands] )) ||
_fnm__ls-remote_commands() {
local commands; commands=(
)
_describe -t commands 'fnm ls-remote commands' commands "$@"
}
(( $+functions[_ls-remote_commands] )) ||
_ls-remote_commands() {
local commands; commands=(
)
_describe -t commands 'ls-remote commands' commands "$@"
}
(( $+functions[_fnm__uninstall_commands] )) ||
_fnm__uninstall_commands() {
local commands; commands=(
)
_describe -t commands 'fnm uninstall commands' commands "$@"
}
(( $+functions[_fnm__use_commands] )) ||
_fnm__use_commands() {
local commands; commands=(
)
_describe -t commands 'fnm use commands' commands "$@"
}
_fnm "$@"

View file

@ -1,13 +0,0 @@
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
Version 2, December 2004
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
Everyone is permitted to copy and distribute verbatim or modified
copies of this license document, and changing it is allowed as long
as the name is changed.
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. You just DO WHAT THE FUCK YOU WANT TO.

View file

@ -1,9 +0,0 @@
conda-zsh-completion
--------------------
Please see the top of the ``_conda`` file for more info.
:License: |license|
.. |license| image:: http://www.wtfpl.net/wp-content/uploads/2012/12/wtfpl-badge-4.png
:target: http://www.wtfpl.net/

View file

@ -1,721 +0,0 @@
#compdef conda mamba
#description:conda package manager
#
# ZSH Completion for conda (http://conda.pydata.org/)
#
# Author: Valentin Haenel <valentin@haenel.co> (https://github.com/esc/)
# Licence: WTFPL (http://sam.zoy.org/wtfpl/)
# Version: 0.10-dev
# Homepage: https://github.com/esc/conda-zsh-completion
# Demo: https://asciinema.org/a/16516
#
# This completion depends on Python for a json parser, sorry. Unfortunately
# there is no such thing in zsh (yet).
#
# To use this completion, install it somewhere on your hard drive:
#
# $ git clone https://github.com/esc/conda-zsh-completion
#
# And then add it to your $fpath in ~/.zshrc before you call compinit:
#
# fpath+=/path/to/where/you/installed/conda-zsh-completion
# compinit
#
# If you're using oh-my-zsh or Prezto, they will call compinit for you, so
# just add it to your $fpath before calling the OMZ or Prezto initialization
# functions. For example:
#
# git clone https://github.com/esc/conda-zsh-completion ${ZSH_CUSTOM:=~/.oh-my-zsh/custom}/plugins/conda-zsh-completion
#
# And add lines in `.zshrc`
# plugins=(… conda-zsh-completion)
# autoload -U compinit && compinit
#
# If you use oh-my-zsh, you might have to move the "autoload" line to after you sourced
# oh-my-zsh.sh.
#
# To activate the completion cache for packages, add the following to your
# '.zshrc':
#
# zstyle ':completion::complete:*' use-cache 1
#
# To display subcommand completion in groups, please add the following to your
# '.zshrc':
#
# zstyle ":conda_zsh_completion:*" use-groups true
#
# To display unnamed environments and prefixes of environments, add the following
# to your '.zshrc':
#
# zstyle ":conda_zsh_completion:*" show-unnamed true
#
# To display environments autocompletion sorted in creation order add the following
# to your '.zshrc':
#
# zstyle ":conda_zsh_completion:*" sort-envs-by-time true
#
# The completion will display both global environments (envs located in conda_dir/envs and base env)
# and local environments (located in ~/.conda/envs).
# If enables sort-envs-by-time, it will display local environments first.
# To display global environments first, add the following to your '.zshrc':
#
# zstyle ":conda_zsh_completion:*" show-global-envs-first true
#
# If not enables sort-envs-by-time, then all environments will be sorted by alphabetical order,
# and this option is useless.
#
# To forcefully clean the completion cache, look in '~/.zcompcache' and remove
# file starting with 'conda_'. And/or do 'rm ~/.zcompdump*'.
#
# When developing, you can use the following to reload the completion after
# having modified it:
#
# $ unfunction _conda && autoload -U _conda
#
# Please report any issues at:
# https://github.com/esc/conda-zsh-completion/issues
#
# CHANGELOG
# ---------
# * v0.10
#
# * XXX
#
# * v0.9
#
# * Improved the completion speed for completing environments, thanks to
# Niels Mündler.
# * Various minor improvements and documentation upgrades
#
# * v0.8
#
# * Updated installation instructions and added a license file, thanks to
# Andrew Janke
#
# * v0.7
#
# * Fix alignment during menu-completion
#
# * v0.6
#
# * conda activate and conda deactivate can now be completed, thanks to
# Taylor Kang Beck
#
# * v0.5
#
# * conda-env can now be completed
# * conda-build can now be completed
#
# * v0.4
#
# * conda info can complete available packages
# * conda install and create have rudimentary package version completion
# * remove caching for local package list, it's fast enough
# * conda remove and update are aware of -n or similar and complete only
# packages in the given environment
# * list of packages excludes those installed with pip
#
# * v0.3
#
# * overhaul of the completion for config
#
# * complete only existing keys
# * complete only existing values
# * differentiate between list and boolean config
# * reader and writer options mutually exclusive
# * complete multiple keys for --get
#
# * -n,--name and -p,--prefix are now mutually exclusive
#
# * v0.2
#
# * completion cache for packages
# * complete all channels defined in .condarc
#
# * v0.1
#
# * inital release
#
# TODO
# ----
#
# * Subcommand grouping is still alpha.
# * Example of activating cache only for conda completion
# * Make cache policy configurable
# * Completion for version numbers is rudimentary:
# only 'install' can complete them and only for a single '=' sign
# * Configuration for external commands: only build and env supported
# * Properly handle package specs on the command line
# * Don't continue to complete options once -- is given
# * None of the commands are aware of channels
local state line context
local -A opt_args
__conda_envs(){
local -a envs unnamed sort globalfirst localenvs globalenvs
local -a ls_opts=("-1")
local -a describe_opts
# only parse environments.txt (including unnamed envs) if asked by the user
zstyle -s ":conda_zsh_completion:*" show-unnamed unnamed
zstyle -s ":conda_zsh_completion:*" sort-envs-by-time sort
zstyle -s ":conda_zsh_completion:*" show-global-envs-first globalfirst
if test -n "$sort"; then
ls_opts+=("-t")
describe_opts+=("-V")
fi
# global envs (if exists) and base env.
globalenvs=($([[ -d "${${CONDA_EXE}%bin/conda}/envs" ]] && ls $ls_opts ${${CONDA_EXE}%bin/conda}/envs))
globalenvs+=("base")
# local envs (if exists).
localenvs=($([[ -d "${HOME:?}/.conda/envs" ]] && ls $ls_opts ${HOME:?}/.conda/envs))
if test -n "$globalfirst"; then
envs=($globalenvs $localenvs)
else
envs=($localenvs $globalenvs)
fi
# unmaned envs (if show-unammed).
if test -n "$unnamed"; then
envs+=($( (test -n "$unnamed" && cat ${HOME:?}/.conda/environments.txt) | cut -f1 -d' ' | sed -e "s|^${HOME:?}/.conda/envs/||"))
fi
_describe $describe_opts -t envs 'conda environments' envs
}
__conda_packages_installed(){
local -a installed_packages option environment additional_message
# check for command line overrides
[[ -n "$1" ]] && option="$1"
[[ -n "$2" ]] && environment="$2"
installed_packages=($( conda list --no-pip $option $environment | sed 1,2d | cut -f1 -d' ' ))
[[ -n $option ]] && [[ -n $environment ]] && additional_message=" in environment: '$environment'"
_describe -t installed_packages "installed packages$additional_message" installed_packages
}
__conda_package_available(){
zstyle ":completion:${curcontext}:" cache-policy __conda_caching_policy
local -a available_packages
if _cache_invalid conda_available_packages || ! _retrieve_cache conda_available_packages ; then
available_packages=($(conda search --use-index-cache --json |
python -c "
import json, sys
parsed = json.load(sys.stdin)
for k in parsed.keys():
print(k)
"))
_store_cache conda_available_packages available_packages
fi
print -l $available_packages
}
__describe_conda_package_available(){
local -a available_packages
available_packages=($( __conda_package_available))
_describe -t available_packages 'available packages' available_packages
}
__conda_existing_config_keys(){
local -a config_keys
config_keys=($(conda config --json --get |
python -c "
import json, sys
keys = json.load(sys.stdin)['get'].keys()
for k in keys:
print(k)
"))
print -l $config_keys
}
__conda_describe_existing_config_keys(){
local -a config_keys
config_keys=($( __conda_existing_config_keys ))
if [ "${#config_keys}" == 0 ] ; then
_message "no keys found!"
else
_describe -t config_keys 'existing configuration keys' config_keys
fi
}
__conda_describe_existing_list_config_keys(){
local -a config_keys existing_list_config_keys
config_keys=($( __conda_existing_config_keys ))
existing_list_config_keys=()
for k in $config_keys; do
if (( ${__conda_list_config_keys[(I)$k]} )) ; then
existing_list_config_keys+=$k
fi
done
if [ "${#existing_list_config_keys}" == 0 ] ; then
_message "no keys found!"
else
_describe -t existing_list_config_keys 'existing list configuration keys' existing_list_config_keys
fi
}
__conda_existing_config_values(){
local -a config_values search_term
search_term="$1"
config_values=($(conda config --json --get "$search_term" 2> /dev/null |
python -c "
import json, sys
try:
values = json.load(sys.stdin)['get']['$search_term']
for v in values:
print(v)
except KeyError:
pass
except ValueError:
pass
"))
print -l $config_values
}
__conda_describe_existing_config_values(){
local -a config_values search_term
search_term="$1"
config_values=($( __conda_existing_config_values $search_term ))
if [ "${#config_values}" == 0 ] ; then
_message "no values found for '$search_term'!"
else
_describe -t config_values 'configuration values' config_values
fi
}
__conda_describe_boolean_config_values(){
local -a config_values
config_values=(True False)
_describe -t config_values 'boolean configuration values' config_values
}
__conda_channels(){
local -a channels
channels=($( __conda_existing_config_values "channels" ))
channels+=(system)
_describe -t channels 'conda channels' channels
}
local -a __conda_boolean_config_keys __conda_list_config_keys __conda_config_keys
__conda_boolean_config_keys=(
'add_binstar_token'
'always_yes'
'allow_softlinks'
'changeps1'
'use_pip'
'offline'
'binstar_upload'
'binstar_personal'
'show_channel_urls'
'allow_other_channels'
'ssl_verify'
)
__conda_list_config_keys=(
'channels'
'disallow'
'create_default_packages'
'track_features'
'envs_dirs'
)
__conda_config_keys=($__conda_boolean_config_keys $__conda_list_config_keys)
__conda_describe_boolean_config_keys(){
_describe -t __conda_boolean_config_keys 'boolean keys' __conda_boolean_config_keys
}
__conda_describe_list_config_keys(){
_describe -t __conda_list_config_keys 'list keys' __conda_list_config_keys
}
__conda_describe_config_keys(){
_describe -t __conda_config_keys 'conda configuration keys' __conda_config_keys
}
#__conda_package_specs=('<' '>' '<=' '>=' '==' '!=')
__conda_package_specs=('=')
__conda_describe_package_specs(){
_describe -t __conda_package_specs 'conda package specs' __conda_package_specs
}
__conda_describe_package_version(){
local -a current_package versions
current_package="$1"
versions=($( conda search --json --use-index-cache $current_package | python -c "
import json,sys
try:
versions = set((e['version'] for e in json.load(sys.stdin)['$current_package']))
for v in versions:
print(v)
except KeyError:
pass
"))
_describe -t versions "$current_package version" versions
}
__conda_commands(){
local -a package maint environment help config special tmp
package=(
search:'Search for packages and display their information.'
install:'Install a list of packages into a specified conda environment.'
)
maint=(
update:'Update conda packages.'
clean:'Remove unused packages and caches.'
)
environment=(
info:'Display information about current conda install.'
create:'Create a new conda environment from a list of specified packages.'
list:'List linked packages in a conda environment.'
remove:'Remove a list of packages from a specified conda environment.'
uninstall:'Alias for conda remove'
activate:'Activate an environment; alias for source activate'
deactivate:'Deactivate an environment; alias for source deactivate'
)
help=(
help:'Displays a list of available conda commands and their help strings.'
)
config=(
config:'Modify configuration values in .condarc.'
)
special=(
run:'Launches an application installed with Conda.'
init:'Initialize conda into a regular environment. (EXPERIMENTAL)'
package:'Low-level conda package utility. (EXPERIMENTAL)'
bundle:'Create or extract a "bundle package" (EXPERIMENTAL)'
)
external=(
env:'Manage environments.'
build:'tool for building conda packages'
)
# This takes care of alignment if the user wanted the subcommand completion
# to be split into groups.
zstyle -s ":conda_zsh_completion:*" use-groups tmp
if [[ -n $tmp ]] ; then
_describe -t package_commands "package commands" package
_describe -t maint_commands "maint commands" maint
_describe -t environment_commands "environment commands" environment
_describe -t help_commands "help commands" help
_describe -t config_commands "config commands" config
_describe -t special_commands "special commands" special
_describe -t external_commands "external commands" external
else
_describe "conda commands" package -- maint -- environment -- help -- config -- special -- external
fi
}
__conda_caching_policy() {
local -a oldp
oldp=( "$1"(Nmh+12) ) # 12 hour
(( $#oldp ))
}
local -a opts help_opts json_opts env_opts channel_opts install_opts
opts=(
'(-h --help)'{-h,--help}'[show this help message and exit]'
'(-V --version)'{-V,--version}'[show program''s version number and exit]'
)
help_opts=(
'(-h --help)'{-h,--help}'[show this help message and exit]' \
)
json_opts=(
'--json[report all output as json.]' \
)
env_opts=(
'(-n --name -p --prefix)'{-n,--name}'[name of environment]:environment:__conda_envs' \
'(-n --name -p --prefix)'{-p,--prefix}'[full path to environment prefix]:path:_path_files' \
)
channel_opts=(
'(-c --channel)'{-c,--channel}'[additional channel to search for packages]:channel:__conda_channels'\
'--override-channels [do not search default or .condarc channels]' \
'--use-index-cache[use cache of channel index files]' \
'--use-local[use locally built packages]' \
)
install_opts=(
'(-y --yes)'{-y,--yes}'[do not ask for confirmation]' \
'--dry-run[only display what would have been done]' \
'(-f --force)'{-f,--force}'[force install]' \
'--file[read package versions from file]:file:_path_files' \
'--no-deps[do not install dependencies]' \
'(-m --mkdir)'{-m,--mkdir}'[create prefix directory if necessary]' \
'--offline[offline mode, don''t connect to internet]' \
'--no-pin[ignore pinned file]' \
'(-q --quiet)'{-q,--quiet}'[do not display progress bar]'\
'--copy[Install all packages using copies instead of hard- or soft-linking]' \
'--alt-hint[Use an alternate algorithm to generate an unsatisfiable hint]' \
)
_arguments -C $opts \
': :->command' \
'*:: :->subcmd'
# the magic function, complete either a package or a package and it's version
__magic(){
local -a last_item available_packages current_package
last_item=$line[$CURRENT]
available_packages=($( __conda_package_available ))
if compset -P "*=" ; then
current_package="$IPREFIX[1,-2]"
__conda_describe_package_version $current_package
else
__describe_conda_package_available
if [[ -n $last_item ]] && (( ${available_packages[(I)$last_item]} )); then
compset -P '*'
__conda_describe_package_specs
fi
fi
}
case $state in
(command)
__conda_commands
;;
(subcmd)
case ${line[1]} in
(info)
_arguments -C $help_opts \
'--json[report all output as json.]' \
'(-a --all)'{-a,--all}'[show all information, (environments, license, and system information]' \
'(-e --envs)'{-e,--envs}'[list all known conda environments]' \
'(-l --license)'{-l,--license}'[display information about local conda licenses list]' \
'(-s --system)'{-s,--system}'[list environment variables]' \
'--root[display root environment path]' \
'*:packages:__describe_conda_package_available' \
;;
(help)
_arguments -C $help_opts \
'*:commands:__conda_commands' \
;;
(list)
_arguments -C $help_opts \
$env_opts \
$json_opts \
'(-c --canonical)'{-c,--canonical}'[output canonical names of packages only]' \
'(-e --export)'{-e,--export}'[output requirement string only]' \
'(-r --revisions)'{-r,--revision}'[list the revision history and exit]' \
'--no-pip[Do not include pip-only installed packages]' \
'*:regex:' \
;;
(search)
_arguments -C $help_opts \
$env_opts \
$json_opts \
$channel_opts \
'(-c --canonical)'{-c,--canonical}'[output canonical names of packages only]' \
'--unknown[use index metadata from the local package cache]' \
'(-o --outdated)'{-o,--outdated}'[only display installed but outdated packages]' \
'(-v --verbose)'{-v,--verbose}'[Show available packages as blocks of data]' \
'--platform[Search the given platform.]' \
'--spec[Treat regex argument as a package specification]' \
'*:regex:' \
;;
(create)
_arguments -C $help_opts \
$env_opts \
$install_opts \
$json_opts \
$channel_opts \
'--unknown[use index metadata from the local package cache]' \
'--clone[path to (or name of) existing local environment]' \
'--no-default-packages[ignore create_default_packages in condarc file]' \
'*:packages:__magic' \
;;
(install)
_arguments -C $help_opts \
$env_opts \
$install_opts \
$json_opts \
$channel_opts \
'--revision[revert to the specified revision]:revision' \
'*:packages:__magic' \
;;
(update)
local -a environment options specifier
options=('-n' '--name' '-p' '--prefix')
for i in $options ; do
(( ${line[(I)$i]} )) && specifier=$i
done
[[ -n $specifier ]] && environment="$line[${line[(i)$specifier]}+1]"
_arguments -C $help_opts \
$env_opts \
$install_opts \
$json_opts \
$channel_opts \
'--unknown[use index metadata from the local package cache]' \
'--all[Update all installed packages in the environment]' \
'*:packages:{__conda_packages_installed $specifier $environment}' \
;;
(remove|uninstall)
local -a environment options specifier
options=('-n' '--name' '-p' '--prefix')
for i in $options ; do
(( ${line[(I)$i]} )) && specifier=$i
done
[[ -n $specifier ]] && environment="$line[${line[(i)$specifier]}+1]"
_arguments -C $help_opts \
$env_opts \
$json_opts \
$channel_opts \
'(-y --yes)'{-y,--yes}'[do not ask for confirmation]' \
'--dry-run[only display what would have been done]' \
'(-a --all)'{-a,--all}'[remove all packages, i.e. the entire environment]' \
'--features[remove features (instead of packages)]' \
'--no-pin[ignore pinned file]' \
'(-q --quiet)'{-q,--quiet}'[do not display progress bar]'\
'--offline[offline mode, don''t connect to internet]' \
'*:packages:{__conda_packages_installed $specifier $environment}' \
;;
(config)
# this allows completing multiple keys when --get is given
local -a last_item get_opts
last_item=$line[$CURRENT-1]
if (( ${line[(I)--get]} )) && (( ${__conda_config_keys[(I)$last_item]} )) ; then
get_opts=('*:keys:__conda_describe_existing_config_keys')
else
get_opts=''
fi
_arguments -C $help_opts \
$json_opts \
'--system[write to the system .condarc file]' \
'--file[write to the given file.]:file:_path_files' \
'( --add --set --remove --remove-key)--get[get the configuration value]:key:__conda_describe_existing_config_keys' \
'(--get --set --remove --remove-key)--add[add one configuration value to a list key]:list key:__conda_describe_list_config_keys:value:' \
'(--get --add --remove --remove-key)--set[set a boolean key]:boolean key:__conda_describe_boolean_config_keys:value:__conda_describe_boolean_config_values' \
'(--get --add --set --remove-key)--remove[remove a configuration value from a list key]:list key:__conda_describe_existing_list_config_keys:value:{__conda_describe_existing_config_values '$last_item'}' \
'(--get --add --set --remove )--remove-key[remove a configuration key (and all its values)]:key:__conda_describe_existing_config_keys' \
'(-f --force)'{-f,--force}'[write to the config file using the yaml parser]' \
$get_opts
;;
(init)
_arguments -C $help_opts \
;;
(clean)
_arguments -C $help_opts \
$json_opts \
'(-y --yes)'{-y,--yes}'[do not ask for confirmation]' \
'--dry-run[only display what would have been done]' \
'(-i --index-cache)'{-i,--index-cache}'[remove index cache]' \
'(-l --lock)'{-l,--lock}'[remove all conda lock files]' \
'(-t --tarballs)'{-t,--tarballs}'[remove cached package tarballs]' \
'(-p --packages)'{-p,--packages}'[remove unused cached packages]' \
'(-s --source-cache)'{-s,--source-cache}'[remove files from the source cache of conda build]' \
;;
(package)
_arguments -C $help_opts \
$env_opts \
'(-w --which)'{-w,--which}'[given some path print which conda package the file came from]:path:_path_files' \
'(-L --ls-files)'{-L,--ls-files}'[list all files belonging to specified package]' \
'(-r --reset)'{-r,--reset}'[remove all untracked files and exit]' \
'(-u --untracked)'{-u,--untracked}'[display all untracked files and exit]' \
'--pkg-name[package name of the created package]:pkg_name:' \
'--pkg-version[package version of the created package]:pkg_version:' \
'--pkg-build[package build number of the created package]:pkg_build:' \
;;
(bundle)
_arguments -C $help_opts \
$env_opts \
$json_opts \
'(-c --create)'{-c,--create}'[create bundle]' \
'(-x --extract)'{-x,--extract}'[extact bundle located at path]:path:_path_files' \
'--metadump[dump metadata of bundle at path]:path:_path_files' \
'(-q --quiet)'{-q,--quiet}'[do not display progress bar]'\
'--bundle-name[name of bundle]:NAME:' \
'--data-path[path to data to be included in bundle]:path:_path_files' \
'--extra-meta[path to json file with additional meta-data no]:path:_path_files' \
'--no-env[no environment]' \
;;
(build)
_arguments -C $help_opts \
'(-c --check)'{-c,--check}'[only check (validate) the recipe]' \
'--no-binstar-upload[do not ask to upload the package to binstar]' \
'--output[output the conda package filename which would have been created and exit]' \
'(-s --source)'{-s,--source}'[only obtain the source (but don''t build)]' \
'(-t --test)'{-t,--test}'[test package (assumes package is already build)]' \
'--no-test[do not test the package]' \
'(-b --build-only)'{-b,--build-only}'[only run the build, without any post processing or testing]' \
'(-p --post)'{-p,--post}'[run the post-build logic]' \
'(-V --version)'{-V,--version}'[show program''s version number and exit]' \
'(-q --quiet)'{-q,--quiet}'[do not display progress bar]' \
'--python[Set the Python version used by conda build]' \
'--perl[Set the Perl version used by conda build]' \
'--numpy[Set the NumPy version used by conda build]' \
'*:recipe_path:_path_files' \
;;
(env)
_arguments -C $opts \
': :->command' \
'*:: :->subcmd'
case $state in
(command)
local -a env
env=(
create:'Create an environment based on an environment file'
export:'Export a given environment'
list:'List the Conda environments'
remove:'Remove an environment'
update:'Update the current environment based on environment file'
)
_describe -t env_commands "help commands" env
;;
(subcmd)
case ${line[1]} in
(create)
_arguments -C $help_opts \
$json_opts \
'(-n --name)'{-n,--name}'[name of environment]:environment:__conda_envs' \
'(-f --file)'{-f,--file}'[environment definition]:file:_path_files' \
'(-q --quiet)'{-q,--quiet}'[]' \
;;
(export)
_arguments -C $help_opts \
'(-n --name)'{-n,--name}'[name of environment]:environment:__conda_envs' \
'(-f --file)'{-f,--file}'[]:file:_path_files' \
;;
(list)
_arguments -C $help_opts \
$json_opts \
;;
(remove)
_arguments -C $help_opts \
$json_opts \
$env_opts \
'(-q --quiet)'{-q,--quiet}'[do not display progress bar]'\
'(-y --yes)'{-y,--yes}'[do not ask for confirmation]' \
'--dry-run[only display what would have been done]' \
;;
(update)
_arguments -C $help_opts \
$json_opts \
'(-n --name)'{-n,--name}'[name of environment]:environment:__conda_envs' \
'(-f --file)'{-f,--file}'[environment definition]:file:_path_files' \
'(-q --quiet)'{-q,--quiet}'[]' \
;;
esac
;;
esac
;;
(activate)
_arguments -C $help_opts \
'--stack[activate this environment on top of the previous environment]' \
'*:environment:__conda_envs'
;;
(deactivate)
_arguments -C $help_opts \
;;
esac
;;
esac

View file

@ -1,10 +0,0 @@
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
indent_style = space
indent_size = 4
[*.md]
indent_style = space

View file

@ -1,35 +0,0 @@
dist: trusty
sudo: required
language: generic
env:
- ZSH_VERSION=5.3.1 URL=https://downloads.sourceforge.net/project/zsh/zsh/5.3.1/zsh-5.3.1.tar.xz
- ZSH_VERSION=5.2 URL=https://downloads.sourceforge.net/project/zsh/zsh/5.2/zsh-5.2.tar.xz
- ZSH_VERSION=5.1.1 URL=https://downloads.sourceforge.net/project/zsh/zsh/5.1.1/zsh-5.1.1.tar.xz
- ZSH_VERSION=5.0.8 URL=https://downloads.sourceforge.net/project/zsh/zsh/5.0.8/zsh-5.0.8.tar.gz
addons:
apt:
packages:
- build-essential
before_install:
- export LOCAL="$(mktemp --directory --tmpdir=${TMPDIR:/tmp} local.bin.XXXXXX)"
- wget $URL
- tar -xf zsh-$ZSH_VERSION.tar.*
- cd zsh-$ZSH_VERSION
- ./configure --prefix=$LOCAL
- make
- make install
- cd -
- export PATH="$LOCAL/bin:$HOME/bin:$PATH"
before_script:
- mkdir -p ~/bin
- curl -L https://github.com/zunit-zsh/zunit/releases/download/v0.8.1/zunit > ~/bin/zunit
- curl -L https://raw.githubusercontent.com/molovo/revolver/master/revolver > ~/bin/revolver
- chmod u+x ~/bin/{revolver,zunit}
script:
- zunit --verbose

View file

@ -1,8 +0,0 @@
tap: false
directories:
tests: tests
output: tests/_output
support: tests/_support
time_limit: 0
fail_fast: false
allow_risky: false

View file

@ -1,22 +0,0 @@
The MIT License (MIT)
Copyright (c) 2016-21 Henrik Lissner.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View file

@ -1,212 +0,0 @@
[![Made with Doom Emacs](https://img.shields.io/badge/Made_with-Doom_Emacs-blueviolet.svg?style=flat-square&logo=GNU%20Emacs&logoColor=white)](https://github.com/hlissner/doom-emacs)
[![MIT License](https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square)](./LICENSE)
![ZSH 5.0.2+](https://img.shields.io/badge/zsh-v5.0.2-orange.svg?style=flat-square)
[![Build Status](https://img.shields.io/travis/hlissner/zsh-autopair/master.svg?label=master&style=flat-square)](https://travis-ci.org/hlissner/zsh-autopair)
# zsh-autopair
A simple plugin that auto-closes, deletes and skips over matching delimiters in
zsh intelligently. Hopefully.
> NOTE: zsh-autopair is untested for versions of Zsh below 5.0.2. Please report
> any issues you have in earlier versions!
Specifically, zsh-autopair does 5 things for you:
1. It inserts matching pairs (by default, that means brackets, quotes and
spaces):
e.g. `echo |` => <kbd>"</kbd> => `echo "|"`
2. It skips over matched pairs:
e.g. `cat ./*.{py,rb|}` => <kbd>}</kbd> => `cat ./*.{py,rb}|`
3. It auto-deletes pairs on backspace:
e.g. `git commit -m "|"` => <kbd>backspace</kbd> => `git commit -m |`
4. And does all of the above only when it makes sense to do so. e.g. when the
pair is balanced and when the cursor isn't next to a boundary character:
e.g. `echo "|""` => <kbd>backspace</kbd> => `echo |""` (doesn't aggressively eat up too many quotes)
5. Spaces between brackets are expanded and contracted.
e.g. `echo [|]` => <kbd>space</kbd> => `echo [ | ]` => <kbd>backspace</kbd> => `echo [|]`
<!-- markdown-toc start - Don't edit this section. Run M-x markdown-toc-refresh-toc -->
**Table of Contents**
- [Install](#install)
- [Antigen](#antigen)
- [zgen](#zgen)
- [zplug](#zplug)
- [Configuration](#configuration)
- [Adding/Removing pairs](#addingremoving-pairs)
- [Troubleshooting & compatibility issues](#troubleshooting--compatibility-issues)
- [zgen & prezto compatibility](#zgen--prezto-compatibility)
- [text on right-side of cursor interfere with completion](#text-on-right-side-of-cursor-interfere-with-completion)
- [zsh-autopair & isearch?](#zsh-autopair--isearch)
- [Midnight Commander](#midnight-commander)
- [Other resources](#other-resources)
<!-- markdown-toc end -->
## Install
Download and source `autopair.zsh`
```bash
if [[ ! -d ~/.zsh-autopair ]]; then
git clone https://github.com/hlissner/zsh-autopair ~/.zsh-autopair
fi
source ~/.zsh-autopair/autopair.zsh
autopair-init
```
### Antigen
`antigen bundle hlissner/zsh-autopair`
### zgen
```bash
if ! zgen saved; then
echo "Creating a zgen save"
# ... other plugins
zgen load hlissner/zsh-autopair
zgen save
fi
```
### zplug
Load autopair _after compinit_, otherwise, the plugin won't work.
```bash
zplug "hlissner/zsh-autopair", defer:2
```
## Configuration
zsh-autopair sets itself up. You can prevent this by setting
`AUTOPAIR_INHIBIT_INIT`.
**Options:**
* `AUTOPAIR_BETWEEN_WHITESPACE` (default: blank): if set, regardless of whether
delimiters are unbalanced or do not meet a boundary check, pairs will be
auto-closed if surrounded by whitespace, BOL or EOL.
* `AUTOPAIR_INHIBIT_INIT` (default: blank): if set, autopair will not
automatically set up keybinds. [Check out the initialization
code](autopair.zsh#L118) if you want to know what it does.
* `AUTOPAIR_PAIRS` (default: ``('`' '`' "'" "'" '"' '"' '{' '}' '[' ']' '(' ')'
' ' ' ')``): An associative array that map pairs. Only one-character pairs are
supported. To modify this, see the "Adding/Removing pairs" section.
* `AUTOPAIR_LBOUNDS`/`AUTOPAIR_RBOUNDS` (default: see below): Associative lists
of regex character groups dictating the 'boundaries' for autopairing depending
on the delimiter. These are their default values:
```bash
AUTOPAIR_LBOUNDS=(all '[.:/\!]')
AUTOPAIR_LBOUNDS+=(quotes '[]})a-zA-Z0-9]')
AUTOPAIR_LBOUNDS+=(spaces '[^{([]')
AUTOPAIR_LBOUNDS+=(braces '')
AUTOPAIR_LBOUNDS+=('`' '`')
AUTOPAIR_LBOUNDS+=('"' '"')
AUTOPAIR_LBOUNDS+=("'" "'")
AUTOPAIR_RBOUNDS=(all '[[{(<,.:?/%$!a-zA-Z0-9]')
AUTOPAIR_RBOUNDS+=(quotes '[a-zA-Z0-9]')
AUTOPAIR_RBOUNDS+=(spaces '[^]})]')
AUTOPAIR_RBOUNDS+=(braces '')
```
For example, if `$AUTOPAIR_LBOUNDS[braces]="[a-zA-Z]"`, then braces (`{([`) won't be
autopaired if the cursor follows an alphabetical character.
Individual delimiters can be used too. Setting `$AUTOPAIR_RBOUNDS['{']="[0-9]"` will
cause <kbd>{</kbd> specifically to not be autopaired when the cursor precedes a number.
### Adding/Removing pairs
You can change the designated pairs in zsh-autopair by modifying the
`AUTOPAIR_PAIRS` envvar. This can be done _before_ initialization like so:
``` sh
typeset -gA AUTOPAIR_PAIRS
AUTOPAIR_PAIRS+=("<" ">")
```
Or after initialization; however, you'll have to bind keys to `autopair-insert`
manually:
```sh
AUTOPAIR_PAIRS+=("<" ">")
bindkey "<" autopair-insert
# prevents breakage in isearch
bindkey -M isearch "<" self-insert
```
To _remove_ pairs, use `unset 'AUTOPAIR_PAIRS[<]'`. Unbinding is optional.
## Troubleshooting & compatibility issues
### zgen & prezto compatibility
Prezto's Editor module is known to reset autopair's bindings. A workaround is to
_defer autopair from initializing_ (by setting `AUTOPAIR_INHIBIT_INIT=1`) and
initialize it manually (by calling `autopair-init`):
``` sh
source "$HOME/.zgen/zgen.zsh"
# Add this
AUTOPAIR_INHIBIT_INIT=1
if ! zgen saved; then
zgen prezto
# ...
zgen load hlissner/zsh-autopair 'autopair.zsh'
#...
zgen save
fi
# And this
autopair-init
```
### text on right-side of cursor interfere with completion
Bind <kbd>Tab</kbd> to `expand-or-complete-prefix` and completion will ignore
what's to the right of cursor:
`bindkey '^I' expand-or-complete-prefix`
This has the unfortunate side-effect of overwriting whatever's right of the
cursor, however.
### zsh-autopair & isearch?
zsh-autopair silently disables itself in isearch, as the two are incompatible.
### Midnight Commander
MC hangs when zsh-autopair tries to bind the space key. This also breaks the MC
subshell.
Disable space expansion to work around this: `unset 'AUTOPAIR_PAIRS[ ]'`
## Other resources
* Works wonderfully with [zsh-syntax-highlight] and
`ZSH_HIGHLIGHT_HIGHLIGHTERS+=brackets`, but zsh-syntax-highlight must be
loaded *after* zsh-autopair.
* Mixes well with these vi-mode zsh modules: [surround], [select-quoted], and
[select-bracketed] (they're built into zsh as of zsh-5.0.8)
* Other relevant repositories of mine:
+ [dotfiles]
+ [emacs.d]
+ [vimrc]
+ [zshrc]
[dotfiles]: https://github.com/hlissner/dotfiles
[vimrc]: https://github.com/hlissner/.vim
[emacs.d]: https://github.com/hlissner/doom-emacs
[zshrc]: https://github.com/hlissner/dotfiles/tree/master/shell/%2Bzsh
[zsh-syntax-highlighting]: https://github.com/zsh-users/zsh-syntax-highlighting/blob/master/docs/highlighters/pattern.md
[surround]: https://github.com/zsh-users/zsh/blob/master/Functions/Zle/surround
[select-quoted]: https://github.com/zsh-users/zsh/blob/master/Functions/Zle/select-quoted
[select-bracketed]: https://github.com/zsh-users/zsh/blob/master/Functions/Zle/select-bracketed

View file

@ -1,218 +0,0 @@
#!/usr/bin/env zsh
AUTOPAIR_INHIBIT_INIT=${AUTOPAIR_INHIBIT_INIT:-}
AUTOPAIR_BETWEEN_WHITESPACE=${AUTOPAIR_BETWEEN_WHITESPACE:-}
AUTOPAIR_SPC_WIDGET=${AUTOPAIR_SPC_WIDGET:-"$(bindkey " " | cut -c5-)"}
AUTOPAIR_BKSPC_WIDGET=${AUTOPAIR_BKSPC_WIDGET:-"$(bindkey "^?" | cut -c6-)"}
typeset -gA AUTOPAIR_PAIRS
AUTOPAIR_PAIRS=('`' '`' "'" "'" '"' '"' '{' '}' '[' ']' '(' ')' ' ' ' ')
typeset -gA AUTOPAIR_LBOUNDS
AUTOPAIR_LBOUNDS=(all '[.:/\!]')
AUTOPAIR_LBOUNDS+=(quotes '[]})a-zA-Z0-9]')
AUTOPAIR_LBOUNDS+=(spaces '[^{([]')
AUTOPAIR_LBOUNDS+=(braces '')
AUTOPAIR_LBOUNDS+=('`' '`')
AUTOPAIR_LBOUNDS+=('"' '"')
AUTOPAIR_LBOUNDS+=("'" "'")
typeset -gA AUTOPAIR_RBOUNDS
AUTOPAIR_RBOUNDS=(all '[[{(<,.:?/%$!a-zA-Z0-9]')
AUTOPAIR_RBOUNDS+=(quotes '[a-zA-Z0-9]')
AUTOPAIR_RBOUNDS+=(spaces '[^]})]')
AUTOPAIR_RBOUNDS+=(braces '')
### Helpers ############################
# Returns the other pair for $1 (a char), blank otherwise
_ap-get-pair() {
if [[ -n $1 ]]; then
echo $AUTOPAIR_PAIRS[$1]
elif [[ -n $2 ]]; then
local i
for i in ${(@k)AUTOPAIR_PAIRS}; do
[[ $2 == $AUTOPAIR_PAIRS[$i] ]] && echo $i && break
done
fi
}
# Return 0 if cursor's surroundings match either regexp: $1 (left) or $2 (right)
_ap-boundary-p() {
[[ -n $1 && $LBUFFER =~ "$1$" ]] || [[ -n $2 && $RBUFFER =~ "^$2" ]]
}
# Return 0 if the surrounding text matches any of the AUTOPAIR_*BOUNDS regexps
_ap-next-to-boundary-p() {
local -a groups
groups=(all)
case $1 in
\'|\"|\`) groups+=quotes ;;
\{|\[|\(|\<) groups+=braces ;;
" ") groups+=spaces ;;
esac
groups+=$1
local group
for group in $groups; do
_ap-boundary-p $AUTOPAIR_LBOUNDS[$group] $AUTOPAIR_RBOUNDS[$group] && return 0
done
return 1
}
# Return 0 if there are the same number of $1 as there are $2 (chars; a
# delimiter pair) in the buffer.
_ap-balanced-p() {
local lbuf="${LBUFFER//\\$1}"
local rbuf="${RBUFFER//\\$2}"
local llen="${#lbuf//[^$1]}"
local rlen="${#rbuf//[^$2]}"
if (( rlen == 0 && llen == 0 )); then
return 0
elif [[ $1 == $2 ]]; then
if [[ $1 == " " ]]; then
# Silence WARN_CREATE_GLOBAL errors
local match=
local mbegin=
local mend=
# Balancing spaces is unnecessary. If there is at least one space on
# either side of the cursor, it is considered balanced.
[[ $LBUFFER =~ "[^'\"]([ ]+)$" && $RBUFFER =~ "^${match[1]}" ]] && return 0
return 1
elif (( llen == rlen || (llen + rlen) % 2 == 0 )); then
return 0
fi
else
local l2len="${#lbuf//[^$2]}"
local r2len="${#rbuf//[^$1]}"
local ltotal=$((llen - l2len))
local rtotal=$((rlen - r2len))
(( ltotal < 0 )) && ltotal=0
(( ltotal < rtotal )) && return 1
return 0
fi
return 1
}
# Return 0 if the last keypress can be auto-paired.
_ap-can-pair-p() {
local rchar="$(_ap-get-pair $KEYS)"
[[ -n $rchar ]] || return 1
if [[ $rchar != " " ]]; then
# Force pair if surrounded by space/[BE]OL, regardless of
# boundaries/balance
[[ -n $AUTOPAIR_BETWEEN_WHITESPACE && \
$LBUFFER =~ "(^|[ ])$" && \
$RBUFFER =~ "^($|[ ])" ]] && return 0
# Don't pair quotes if the delimiters are unbalanced
! _ap-balanced-p $KEYS $rchar && return 1
elif [[ $RBUFFER =~ "^[ ]*$" ]]; then
# Don't pair spaces surrounded by whitespace
return 1
fi
# Don't pair when in front of characters that likely signify the start of a
# string, path or undesirable boundary.
_ap-next-to-boundary-p $KEYS $rchar && return 1
return 0
}
# Return 0 if the adjacent character (on the right) can be safely skipped over.
_ap-can-skip-p() {
if [[ -z $LBUFFER ]]; then
return 1
elif [[ $1 == $2 ]]; then
if [[ $1 == " " ]]; then
return 1
elif ! _ap-balanced-p $1 $2; then
return 1
fi
fi
if ! [[ -n $2 && $RBUFFER[1] == $2 && $LBUFFER[-1] != '\' ]]; then
return 1
fi
return 0
}
# Return 0 if the adjacent character (on the right) can be safely deleted.
_ap-can-delete-p() {
local lchar="$LBUFFER[-1]"
local rchar="$(_ap-get-pair $lchar)"
! [[ -n $rchar && $RBUFFER[1] == $rchar ]] && return 1
if [[ $lchar == $rchar ]]; then
if [[ $lchar == ' ' && ( $LBUFFER =~ "[^{([] +$" || $RBUFFER =~ "^ +[^]})]" ) ]]; then
# Don't collapse spaces unless in delimiters
return 1
elif ! _ap-balanced-p $lchar $rchar; then
return 1
fi
fi
return 0
}
# Insert $1 and add $2 after the cursor
_ap-self-insert() {
LBUFFER+=$1
RBUFFER="$2$RBUFFER"
}
### Widgets ############################
autopair-insert() {
local rchar="$(_ap-get-pair $KEYS)"
if [[ $KEYS == (\'|\"|\`| ) ]] && _ap-can-skip-p $KEYS $rchar; then
zle forward-char
elif _ap-can-pair-p; then
_ap-self-insert $KEYS $rchar
elif [[ $rchar == " " ]]; then
zle ${AUTOPAIR_SPC_WIDGET:-self-insert}
else
zle self-insert
fi
}
autopair-close() {
if _ap-can-skip-p "$(_ap-get-pair "" $KEYS)" $KEYS; then
zle forward-char
else
zle self-insert
fi
}
autopair-delete() {
_ap-can-delete-p && RBUFFER=${RBUFFER:1}
zle ${AUTOPAIR_BKSPC_WIDGET:-backward-delete-char}
}
### Initialization #####################
autopair-init() {
zle -N autopair-insert
zle -N autopair-close
zle -N autopair-delete
local p
for p in ${(@k)AUTOPAIR_PAIRS}; do
bindkey "$p" autopair-insert
bindkey -M isearch "$p" self-insert
local rchar="$(_ap-get-pair $p)"
if [[ $p != $rchar ]]; then
bindkey "$rchar" autopair-close
bindkey -M isearch "$rchar" self-insert
fi
done
bindkey "^?" autopair-delete
bindkey "^h" autopair-delete
bindkey -M isearch "^?" backward-delete-char
bindkey -M isearch "^h" backward-delete-char
}
[[ -n $AUTOPAIR_INHIBIT_INIT ]] || autopair-init

View file

@ -1,218 +0,0 @@
#!/usr/bin/env zsh
AUTOPAIR_INHIBIT_INIT=${AUTOPAIR_INHIBIT_INIT:-}
AUTOPAIR_BETWEEN_WHITESPACE=${AUTOPAIR_BETWEEN_WHITESPACE:-}
AUTOPAIR_SPC_WIDGET=${AUTOPAIR_SPC_WIDGET:-"$(bindkey " " | cut -c5-)"}
AUTOPAIR_BKSPC_WIDGET=${AUTOPAIR_BKSPC_WIDGET:-"$(bindkey "^?" | cut -c6-)"}
typeset -gA AUTOPAIR_PAIRS
AUTOPAIR_PAIRS=('`' '`' "'" "'" '"' '"' '{' '}' '[' ']' '(' ')' ' ' ' ')
typeset -gA AUTOPAIR_LBOUNDS
AUTOPAIR_LBOUNDS=(all '[.:/\!]')
AUTOPAIR_LBOUNDS+=(quotes '[]})a-zA-Z0-9]')
AUTOPAIR_LBOUNDS+=(spaces '[^{([]')
AUTOPAIR_LBOUNDS+=(braces '')
AUTOPAIR_LBOUNDS+=('`' '`')
AUTOPAIR_LBOUNDS+=('"' '"')
AUTOPAIR_LBOUNDS+=("'" "'")
typeset -gA AUTOPAIR_RBOUNDS
AUTOPAIR_RBOUNDS=(all '[[{(<,.:?/%$!a-zA-Z0-9]')
AUTOPAIR_RBOUNDS+=(quotes '[a-zA-Z0-9]')
AUTOPAIR_RBOUNDS+=(spaces '[^]})]')
AUTOPAIR_RBOUNDS+=(braces '')
### Helpers ############################
# Returns the other pair for $1 (a char), blank otherwise
_ap-get-pair() {
if [[ -n $1 ]]; then
echo $AUTOPAIR_PAIRS[$1]
elif [[ -n $2 ]]; then
local i
for i in ${(@k)AUTOPAIR_PAIRS}; do
[[ $2 == $AUTOPAIR_PAIRS[$i] ]] && echo $i && break
done
fi
}
# Return 0 if cursor's surroundings match either regexp: $1 (left) or $2 (right)
_ap-boundary-p() {
[[ -n $1 && $LBUFFER =~ "$1$" ]] || [[ -n $2 && $RBUFFER =~ "^$2" ]]
}
# Return 0 if the surrounding text matches any of the AUTOPAIR_*BOUNDS regexps
_ap-next-to-boundary-p() {
local -a groups
groups=(all)
case $1 in
\'|\"|\`) groups+=quotes ;;
\{|\[|\(|\<) groups+=braces ;;
" ") groups+=spaces ;;
esac
groups+=$1
local group
for group in $groups; do
_ap-boundary-p $AUTOPAIR_LBOUNDS[$group] $AUTOPAIR_RBOUNDS[$group] && return 0
done
return 1
}
# Return 0 if there are the same number of $1 as there are $2 (chars; a
# delimiter pair) in the buffer.
_ap-balanced-p() {
local lbuf="${LBUFFER//\\$1}"
local rbuf="${RBUFFER//\\$2}"
local llen="${#lbuf//[^$1]}"
local rlen="${#rbuf//[^$2]}"
if (( rlen == 0 && llen == 0 )); then
return 0
elif [[ $1 == $2 ]]; then
if [[ $1 == " " ]]; then
# Silence WARN_CREATE_GLOBAL errors
local match=
local mbegin=
local mend=
# Balancing spaces is unnecessary. If there is at least one space on
# either side of the cursor, it is considered balanced.
[[ $LBUFFER =~ "[^'\"]([ ]+)$" && $RBUFFER =~ "^${match[1]}" ]] && return 0
return 1
elif (( llen == rlen || (llen + rlen) % 2 == 0 )); then
return 0
fi
else
local l2len="${#lbuf//[^$2]}"
local r2len="${#rbuf//[^$1]}"
local ltotal=$((llen - l2len))
local rtotal=$((rlen - r2len))
(( ltotal < 0 )) && ltotal=0
(( ltotal < rtotal )) && return 1
return 0
fi
return 1
}
# Return 0 if the last keypress can be auto-paired.
_ap-can-pair-p() {
local rchar="$(_ap-get-pair $KEYS)"
[[ -n $rchar ]] || return 1
if [[ $rchar != " " ]]; then
# Force pair if surrounded by space/[BE]OL, regardless of
# boundaries/balance
[[ -n $AUTOPAIR_BETWEEN_WHITESPACE && \
$LBUFFER =~ "(^|[ ])$" && \
$RBUFFER =~ "^($|[ ])" ]] && return 0
# Don't pair quotes if the delimiters are unbalanced
! _ap-balanced-p $KEYS $rchar && return 1
elif [[ $RBUFFER =~ "^[ ]*$" ]]; then
# Don't pair spaces surrounded by whitespace
return 1
fi
# Don't pair when in front of characters that likely signify the start of a
# string, path or undesirable boundary.
_ap-next-to-boundary-p $KEYS $rchar && return 1
return 0
}
# Return 0 if the adjacent character (on the right) can be safely skipped over.
_ap-can-skip-p() {
if [[ -z $LBUFFER ]]; then
return 1
elif [[ $1 == $2 ]]; then
if [[ $1 == " " ]]; then
return 1
elif ! _ap-balanced-p $1 $2; then
return 1
fi
fi
if ! [[ -n $2 && $RBUFFER[1] == $2 && $LBUFFER[-1] != '\' ]]; then
return 1
fi
return 0
}
# Return 0 if the adjacent character (on the right) can be safely deleted.
_ap-can-delete-p() {
local lchar="$LBUFFER[-1]"
local rchar="$(_ap-get-pair $lchar)"
! [[ -n $rchar && $RBUFFER[1] == $rchar ]] && return 1
if [[ $lchar == $rchar ]]; then
if [[ $lchar == ' ' && ( $LBUFFER =~ "[^{([] +$" || $RBUFFER =~ "^ +[^]})]" ) ]]; then
# Don't collapse spaces unless in delimiters
return 1
elif ! _ap-balanced-p $lchar $rchar; then
return 1
fi
fi
return 0
}
# Insert $1 and add $2 after the cursor
_ap-self-insert() {
LBUFFER+=$1
RBUFFER="$2$RBUFFER"
}
### Widgets ############################
autopair-insert() {
local rchar="$(_ap-get-pair $KEYS)"
if [[ $KEYS == (\'|\"|\`| ) ]] && _ap-can-skip-p $KEYS $rchar; then
zle forward-char
elif _ap-can-pair-p; then
_ap-self-insert $KEYS $rchar
elif [[ $rchar == " " ]]; then
zle ${AUTOPAIR_SPC_WIDGET:-self-insert}
else
zle self-insert
fi
}
autopair-close() {
if _ap-can-skip-p "$(_ap-get-pair "" $KEYS)" $KEYS; then
zle forward-char
else
zle self-insert
fi
}
autopair-delete() {
_ap-can-delete-p && RBUFFER=${RBUFFER:1}
zle ${AUTOPAIR_BKSPC_WIDGET:-backward-delete-char}
}
### Initialization #####################
autopair-init() {
zle -N autopair-insert
zle -N autopair-close
zle -N autopair-delete
local p
for p in ${(@k)AUTOPAIR_PAIRS}; do
bindkey "$p" autopair-insert
bindkey -M isearch "$p" self-insert
local rchar="$(_ap-get-pair $p)"
if [[ $p != $rchar ]]; then
bindkey "$rchar" autopair-close
bindkey -M isearch "$rchar" self-insert
fi
done
bindkey "^?" autopair-delete
bindkey "^h" autopair-delete
bindkey -M isearch "^?" backward-delete-char
bindkey -M isearch "^h" backward-delete-char
}
[[ -n $AUTOPAIR_INHIBIT_INIT ]] || autopair-init

View file

@ -1,15 +0,0 @@
#!/usr/bin/env zsh
source autopair.zsh
export KEYS=
export LBUFFER=
export RBUFFER=
assert_true() {
run $@
assert $state equals 0
}
assert_false() {
run $@
assert $state equals 1
}

View file

@ -1,16 +0,0 @@
#!/usr/bin/env zunit
@test 'basic boundary tests' {
LBUFFER="abc"
RBUFFER="123"
assert_false _ap-boundary-p " " " "
assert_true _ap-boundary-p "[^3]" "[^a]"
assert_false _ap-boundary-p "[^c]" "[^1]"
assert_true _ap-boundary-p "c" " "
assert_true _ap-boundary-p " " "1"
}
@test 'no boundary on blank line' {
LBUFFER=
RBUFFER=
assert_false _ap-next-to-boundary-p "{"
}

View file

@ -1,24 +0,0 @@
#!/usr/bin/env zunit
@test 'delete if next to space and pair' {
LBUFFER="[ " RBUFFER=" ]" assert_true _ap-can-delete-p
}
@test 'delete if next to homogeneous counter-pair' {
LBUFFER="'" RBUFFER="'" assert_true _ap-can-delete-p
}
@test 'delete if next to heterogeneous counter-pair' {
LBUFFER="(" RBUFFER=")" assert_true _ap-can-delete-p
}
@test 'do not delete if at eol' {
LBUFFER="'" assert_false _ap-can-delete-p
}
@test 'do not delete if within too many spaces' {
LBUFFER="[ " RBUFFER=" ]" assert_false _ap-can-delete-p
}
@test 'do not delete if only next to space' {
LBUFFER=" " RBUFFER=" " assert_false _ap-can-delete-p
}

View file

@ -1,59 +0,0 @@
#!/usr/bin/env zunit
@test 'pair if blank line' {
KEYS="'" LBUFFER="" RBUFFER="" assert_true _ap-can-pair-p
}
@test 'pair if next to balanced delimiter' { # {{|}}
KEYS="{" LBUFFER="{" RBUFFER="}" assert_true _ap-can-pair-p
}
@test 'pair space if next to brackets' { # { | }
KEYS=" "
LBUFFER="{" RBUFFER="}" assert_true _ap-can-pair-p
LBUFFER="[" RBUFFER="]" assert_true _ap-can-pair-p
LBUFFER="(" RBUFFER=")" assert_true _ap-can-pair-p
}
@test 'pair brackets at the end of a word' { # abc{|}
KEYS='{' LBUFFER="hello" assert_true _ap-can-pair-p
}
@test 'do not pair brackets at the beginning of a word' { # {|abc
KEYS='{' RBUFFER="hello" assert_false _ap-can-pair-p
}
@test 'do not pair quotes next to a word' {
KEYS="'"
LBUFFER="hello" assert_false _ap-can-pair-p # abc"|
RBUFFER="hello" assert_false _ap-can-pair-p # "|abc
}
@test 'do not pair the same quotes from inside quotes' { # ""|"
KEYS='"' LBUFFER='"' RBUFFER='"' assert_false _ap-can-pair-p
}
@test 'do not pair if delimiter is invalid' {
KEYS="<" LBUFFER="<" RBUFFER=">" assert_false _ap-can-pair-p
}
@test 'do not pair if next to unbalanced delimiter' { # {|}
KEYS="{" LBUFFER="" RBUFFER="}" assert_false _ap-can-pair-p
}
@test 'do not pair if next to unbalanced delimiter after space' { # {| }
AUTOPAIR_BETWEEN_WHITESPACE=
KEYS="{" LBUFFER="" RBUFFER=" }" assert_false _ap-can-pair-p
KEYS="{" LBUFFER="" RBUFFER=" }" assert_false _ap-can-pair-p
KEYS="{" LBUFFER=" " RBUFFER=" }" assert_false _ap-can-pair-p
}
@test 'do not pair space if next to non-brackets/spaces' {
KEYS=" "
LBUFFER="'" RBUFFER="'" assert_false _ap-can-pair-p # ' |'
LBUFFER="abc" RBUFFER="xyz" assert_false _ap-can-pair-p # abc |xyz'
LBUFFER="[ " RBUFFER=" ]" assert_false _ap-can-pair-p # [ | ]
}
@test 'AUTOPAIR_BETWEEN_WHITESPACE=1' {
AUTOPAIR_BETWEEN_WHITESPACE=1 KEYS='{' LBUFFER=" " RBUFFER=" }" assert_true _ap-can-pair-p
}

View file

@ -1,25 +0,0 @@
#!/usr/bin/env zunit
@test 'fail skip-check on blank line' {
LBUFFER='' RBUFFER='' assert_false _ap-can-skip-p '{' '}'
}
@test 'fail skip-check on wrong pair' {
LBUFFER='"' RBUFFER='"' assert_false _ap-can-skip-p '{' '}'
}
@test 'skip if next to homogeneous counter-pair' {
LBUFFER='"' RBUFFER='"' assert_true _ap-can-skip-p '"' '"'
}
@test 'skip if next to heterogeneous counter-pair' {
LBUFFER='{' RBUFFER='}' assert_true _ap-can-skip-p '{' '}'
}
@test 'do not skip if next to unbalanced, homogeneous counter-pair' {
LBUFFER='' RBUFFER='"' assert_false _ap-can-skip-p '"' '"'
}
@test 'do not skip if next to unbalanced, heterogeneous counter-pair' {
LBUFFER='' RBUFFER='}' assert_false _ap-can-skip-p '{' '}'
}

View file

@ -1,26 +0,0 @@
#!/usr/bin/env zunit
@test 'existing pair' {
assert $(_ap-get-pair "{") same_as "}"
}
@test 'existing right-pair' {
assert $(_ap-get-pair "" "}") same_as "{"
}
@test 'non-existent pair' {
assert $(_ap-get-pair "<") same_as ""
}
@test 'non-existent right-pair' {
assert $(_ap-get-pair "" ">") same_as ""
}
@test 'all default pairs' {
assert '"' in ${(@k)AUTOPAIR_PAIRS}
assert "'" in ${(@k)AUTOPAIR_PAIRS}
assert '`' in ${(@k)AUTOPAIR_PAIRS}
assert '{' in ${(@k)AUTOPAIR_PAIRS}
assert '[' in ${(@k)AUTOPAIR_PAIRS}
assert '(' in ${(@k)AUTOPAIR_PAIRS}
assert ' ' in ${(@k)AUTOPAIR_PAIRS}
}

View file

@ -1,218 +0,0 @@
#!/usr/bin/env zsh
AUTOPAIR_INHIBIT_INIT=${AUTOPAIR_INHIBIT_INIT:-}
AUTOPAIR_BETWEEN_WHITESPACE=${AUTOPAIR_BETWEEN_WHITESPACE:-}
AUTOPAIR_SPC_WIDGET=${AUTOPAIR_SPC_WIDGET:-"$(bindkey " " | cut -c5-)"}
AUTOPAIR_BKSPC_WIDGET=${AUTOPAIR_BKSPC_WIDGET:-"$(bindkey "^?" | cut -c6-)"}
typeset -gA AUTOPAIR_PAIRS
AUTOPAIR_PAIRS=('`' '`' "'" "'" '"' '"' '{' '}' '[' ']' '(' ')' ' ' ' ')
typeset -gA AUTOPAIR_LBOUNDS
AUTOPAIR_LBOUNDS=(all '[.:/\!]')
AUTOPAIR_LBOUNDS+=(quotes '[]})a-zA-Z0-9]')
AUTOPAIR_LBOUNDS+=(spaces '[^{([]')
AUTOPAIR_LBOUNDS+=(braces '')
AUTOPAIR_LBOUNDS+=('`' '`')
AUTOPAIR_LBOUNDS+=('"' '"')
AUTOPAIR_LBOUNDS+=("'" "'")
typeset -gA AUTOPAIR_RBOUNDS
AUTOPAIR_RBOUNDS=(all '[[{(<,.:?/%$!a-zA-Z0-9]')
AUTOPAIR_RBOUNDS+=(quotes '[a-zA-Z0-9]')
AUTOPAIR_RBOUNDS+=(spaces '[^]})]')
AUTOPAIR_RBOUNDS+=(braces '')
### Helpers ############################
# Returns the other pair for $1 (a char), blank otherwise
_ap-get-pair() {
if [[ -n $1 ]]; then
echo $AUTOPAIR_PAIRS[$1]
elif [[ -n $2 ]]; then
local i
for i in ${(@k)AUTOPAIR_PAIRS}; do
[[ $2 == $AUTOPAIR_PAIRS[$i] ]] && echo $i && break
done
fi
}
# Return 0 if cursor's surroundings match either regexp: $1 (left) or $2 (right)
_ap-boundary-p() {
[[ -n $1 && $LBUFFER =~ "$1$" ]] || [[ -n $2 && $RBUFFER =~ "^$2" ]]
}
# Return 0 if the surrounding text matches any of the AUTOPAIR_*BOUNDS regexps
_ap-next-to-boundary-p() {
local -a groups
groups=(all)
case $1 in
\'|\"|\`) groups+=quotes ;;
\{|\[|\(|\<) groups+=braces ;;
" ") groups+=spaces ;;
esac
groups+=$1
local group
for group in $groups; do
_ap-boundary-p $AUTOPAIR_LBOUNDS[$group] $AUTOPAIR_RBOUNDS[$group] && return 0
done
return 1
}
# Return 0 if there are the same number of $1 as there are $2 (chars; a
# delimiter pair) in the buffer.
_ap-balanced-p() {
local lbuf="${LBUFFER//\\$1}"
local rbuf="${RBUFFER//\\$2}"
local llen="${#lbuf//[^$1]}"
local rlen="${#rbuf//[^$2]}"
if (( rlen == 0 && llen == 0 )); then
return 0
elif [[ $1 == $2 ]]; then
if [[ $1 == " " ]]; then
# Silence WARN_CREATE_GLOBAL errors
local match=
local mbegin=
local mend=
# Balancing spaces is unnecessary. If there is at least one space on
# either side of the cursor, it is considered balanced.
[[ $LBUFFER =~ "[^'\"]([ ]+)$" && $RBUFFER =~ "^${match[1]}" ]] && return 0
return 1
elif (( llen == rlen || (llen + rlen) % 2 == 0 )); then
return 0
fi
else
local l2len="${#lbuf//[^$2]}"
local r2len="${#rbuf//[^$1]}"
local ltotal=$((llen - l2len))
local rtotal=$((rlen - r2len))
(( ltotal < 0 )) && ltotal=0
(( ltotal < rtotal )) && return 1
return 0
fi
return 1
}
# Return 0 if the last keypress can be auto-paired.
_ap-can-pair-p() {
local rchar="$(_ap-get-pair $KEYS)"
[[ -n $rchar ]] || return 1
if [[ $rchar != " " ]]; then
# Force pair if surrounded by space/[BE]OL, regardless of
# boundaries/balance
[[ -n $AUTOPAIR_BETWEEN_WHITESPACE && \
$LBUFFER =~ "(^|[ ])$" && \
$RBUFFER =~ "^($|[ ])" ]] && return 0
# Don't pair quotes if the delimiters are unbalanced
! _ap-balanced-p $KEYS $rchar && return 1
elif [[ $RBUFFER =~ "^[ ]*$" ]]; then
# Don't pair spaces surrounded by whitespace
return 1
fi
# Don't pair when in front of characters that likely signify the start of a
# string, path or undesirable boundary.
_ap-next-to-boundary-p $KEYS $rchar && return 1
return 0
}
# Return 0 if the adjacent character (on the right) can be safely skipped over.
_ap-can-skip-p() {
if [[ -z $LBUFFER ]]; then
return 1
elif [[ $1 == $2 ]]; then
if [[ $1 == " " ]]; then
return 1
elif ! _ap-balanced-p $1 $2; then
return 1
fi
fi
if ! [[ -n $2 && $RBUFFER[1] == $2 && $LBUFFER[-1] != '\' ]]; then
return 1
fi
return 0
}
# Return 0 if the adjacent character (on the right) can be safely deleted.
_ap-can-delete-p() {
local lchar="$LBUFFER[-1]"
local rchar="$(_ap-get-pair $lchar)"
! [[ -n $rchar && $RBUFFER[1] == $rchar ]] && return 1
if [[ $lchar == $rchar ]]; then
if [[ $lchar == ' ' && ( $LBUFFER =~ "[^{([] +$" || $RBUFFER =~ "^ +[^]})]" ) ]]; then
# Don't collapse spaces unless in delimiters
return 1
elif ! _ap-balanced-p $lchar $rchar; then
return 1
fi
fi
return 0
}
# Insert $1 and add $2 after the cursor
_ap-self-insert() {
LBUFFER+=$1
RBUFFER="$2$RBUFFER"
}
### Widgets ############################
autopair-insert() {
local rchar="$(_ap-get-pair $KEYS)"
if [[ $KEYS == (\'|\"|\`| ) ]] && _ap-can-skip-p $KEYS $rchar; then
zle forward-char
elif _ap-can-pair-p; then
_ap-self-insert $KEYS $rchar
elif [[ $rchar == " " ]]; then
zle ${AUTOPAIR_SPC_WIDGET:-self-insert}
else
zle self-insert
fi
}
autopair-close() {
if _ap-can-skip-p "$(_ap-get-pair "" $KEYS)" $KEYS; then
zle forward-char
else
zle self-insert
fi
}
autopair-delete() {
_ap-can-delete-p && RBUFFER=${RBUFFER:1}
zle ${AUTOPAIR_BKSPC_WIDGET:-backward-delete-char}
}
### Initialization #####################
autopair-init() {
zle -N autopair-insert
zle -N autopair-close
zle -N autopair-delete
local p
for p in ${(@k)AUTOPAIR_PAIRS}; do
bindkey "$p" autopair-insert
bindkey -M isearch "$p" self-insert
local rchar="$(_ap-get-pair $p)"
if [[ $p != $rchar ]]; then
bindkey "$rchar" autopair-close
bindkey -M isearch "$rchar" self-insert
fi
done
bindkey "^?" autopair-delete
bindkey "^h" autopair-delete
bindkey -M isearch "^?" backward-delete-char
bindkey -M isearch "^h" backward-delete-char
}
[[ -n $AUTOPAIR_INHIBIT_INIT ]] || autopair-init

View file

@ -1,15 +0,0 @@
version: 2
jobs:
build:
parallelism: 4
shell: /bin/bash --login
docker:
- image: ericfreese/zsh-autosuggestions-test:latest
steps:
- checkout
- run:
name: Running tests
command: |
for v in $(grep "^[^#]" ZSH_VERSIONS | awk "(NR + $CIRCLE_NODE_INDEX) % $CIRCLE_NODE_TOTAL == 0"); do
TEST_ZSH_BIN=zsh-$v make test || exit 1
done

View file

@ -1,18 +0,0 @@
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
indent_style = tab
indent_size = 4
[*.md]
indent_style = space
[*.rb]
indent_style = space
indent_size = 2
[*.yml]
indent_style = space
indent_size = 2

View file

@ -1,3 +0,0 @@
--color
--require spec_helper
--format documentation

View file

@ -1,30 +0,0 @@
# Rails:
# Enabled: true
AllCops:
TargetRubyVersion: 2.3
Include:
- '**/Rakefile'
- '**/config.ru'
- '**/Gemfile'
Metrics/LineLength:
Max: 120
Style/Documentation:
Enabled: false
Style/DotPosition:
EnforcedStyle: trailing
Style/FrozenStringLiteralComment:
Enabled: false
Style/Lambda:
Enabled: false
Style/MultilineMethodCallIndentation:
EnforcedStyle: indented
Style/TrailingUnderscoreVariable:
Enabled: false

View file

@ -1,117 +0,0 @@
# Changelog
## v0.7.0
- Enable asynchronous mode by default (#498)
- No longer wrap user widgets starting with `autosuggest-` prefix (#496)
- Fix a bug wrapping widgets that modify the buffer (#541)
## v0.6.4
- Fix `vi-forward-char` triggering a bell when using it to accept a suggestion (#488)
- New configuration option to skip completion suggestions when buffer matches a pattern (#487)
- New configuration option to ignore history entries matching a pattern (#456)
## v0.6.3
- Fixed bug moving cursor to end of buffer after accepting suggestion (#453)
## v0.6.2
- Fixed bug deleting the last character in the buffer in vi mode (#450)
- Degrade gracefully when user doesn't have `zsh/system` module installed (#447)
## v0.6.1
- Fixed bug occurring when `_complete` had been aliased (#443)
## v0.6.0
- Added `completion` suggestion strategy powered by completion system (#111)
- Allow setting `ZSH_AUTOSUGGEST_BUFFER_MAX_SIZE` to an empty string (#422)
- Don't fetch suggestions after copy-earlier-word (#439)
- Allow users to unignore zle-\* widgets (e.g. zle-line-init) (#432)
## v0.5.2
- Allow disabling automatic widget re-binding for better performance (#418)
- Fix async suggestions when `SH_WORD_SPLIT` is set
- Refactor async mode to use process substitution instead of zpty (#417)
## v0.5.1
- Speed up widget rebinding (#413)
- Clean up global variable creations (#403)
- Respect user's set options when running original widget (#402)
## v0.5.0
- Don't overwrite config with default values (#335)
- Support fallback strategies by supplying array to suggestion config var
- Rename "default" suggestion strategy to "history" to name it based on what it actually does
- Reset opts in some functions affected by `GLOB_SUBST` (#334)
- Support widgets starting with dashes (ex: `-a-widget`) (#337)
- Skip async tests in zsh versions less than 5.0.8 because of reliability issues
- Fix handling of newline + carriage return in async pty (#333)
## v0.4.3
- Avoid bell when accepting suggestions with `autosuggest-accept` (#228)
- Don't fetch suggestions after [up,down]-line-or-beginning-search (#227, #241)
- We are now running CI against new 5.5.1 version
- Fix partial-accept in vi mode (#188)
- Fix suggestion disappearing on fast movement after switching to `vicmd` mode (#290)
- Fix issue rotating through kill ring with `yank-pop` (#301)
- Fix issue creating new pty for async mode when previous pty is not properly cleaned up (#249)
## v0.4.2
- Fix bug in zsh versions older than 5.0.8 (#296)
- Officially support back to zsh v4.3.11
## v0.4.1
- Switch to [[ and (( conditionals instead of [ (#257)
- Avoid warnnestedvar warnings with `typeset -g` (#275)
- Replace tabs with spaces in yaml (#268)
- Clean up and fix escaping of special characters (#267)
- Add `emacs-forward-word` to default list of partial accept widgets (#246)
## v0.4.0
- High-level integration tests using RSpec and tmux
- Add continuous integration with Circle CI
- Experimental support for asynchronous suggestions (#170)
- Fix problems with multi-line suggestions (#225)
- Optimize case where manually typing in suggestion
- Avoid wrapping any zle-\* widgets (#206)
- Remove support for deprecated options from v0.0.x
- Handle history entries that begin with dashes
- Gracefully handle being sourced multiple times (#126)
- Add enable/disable/toggle widgets to disable/enable suggestions (#219)
## v0.3.3
- Switch from $history array to fc builtin for better performance with large HISTFILEs (#164)
- Fix tilde handling when extended_glob is set (#168)
- Add config option for maximum buffer length to fetch suggestions for (#178)
- Add config option for list of widgets to ignore (#184)
- Don't fetch a new suggestion unless a modification widget actually modifies the buffer (#183)
## v0.3.2
- Test runner now supports running specific tests and choosing zsh binary
- Return code from original widget is now correctly passed through (#135)
- Add `vi-add-eol` to list of accept widgets (#143)
- Escapes widget names within evals to fix problems with irregular widget names (#152)
- Plugin now clears suggestion while within a completion menu (#149)
- .plugin file no longer relies on symbolic link support, fixing issues on Windows (#156)
## v0.3.1
- Fixes issue with `vi-next-char` not accepting suggestion (#137).
- Fixes global variable warning when WARN_CREATE_GLOBAL option enabled (#133).
- Split out a separate test file for each widget.
## v0.3.0
- Adds `autosuggest-execute` widget (PR #124).
- Adds concept of suggestion "strategies" for different ways of fetching suggestions.
- Adds "match_prev_cmd" strategy (PR #131).
- Uses git submodules for testing dependencies.
- Lots of test cleanup.
- Various bug fixes for zsh 5.0.x and `sh_word_split` option.
## v0.2.17
Start of changelog.

View file

@ -1 +0,0 @@
Fish-like fast/unobtrusive autosuggestions for zsh.

View file

@ -1,20 +0,0 @@
FROM ruby:2.5.3-alpine
RUN apk add --no-cache autoconf
RUN apk add --no-cache libtool
RUN apk add --no-cache libcap-dev
RUN apk add --no-cache pcre-dev
RUN apk add --no-cache curl
RUN apk add --no-cache build-base
RUN apk add --no-cache ncurses-dev
RUN apk add --no-cache tmux
WORKDIR /zsh-autosuggestions
ADD ZSH_VERSIONS /zsh-autosuggestions/ZSH_VERSIONS
ADD install_test_zsh.sh /zsh-autosuggestions/install_test_zsh.sh
RUN ./install_test_zsh.sh
ADD Gemfile /zsh-autosuggestions/Gemfile
ADD Gemfile.lock /zsh-autosuggestions/Gemfile.lock
RUN bundle install

View file

@ -1,5 +0,0 @@
source 'https://rubygems.org'
gem 'rspec'
gem 'rspec-wait'
gem 'pry-byebug'

View file

@ -1,41 +0,0 @@
GEM
remote: https://rubygems.org/
specs:
byebug (9.0.5)
coderay (1.1.1)
diff-lcs (1.3)
method_source (0.8.2)
pry (0.10.4)
coderay (~> 1.1.0)
method_source (~> 0.8.1)
slop (~> 3.4)
pry-byebug (3.4.0)
byebug (~> 9.0)
pry (~> 0.10)
rspec (3.5.0)
rspec-core (~> 3.5.0)
rspec-expectations (~> 3.5.0)
rspec-mocks (~> 3.5.0)
rspec-core (3.5.4)
rspec-support (~> 3.5.0)
rspec-expectations (3.5.0)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.5.0)
rspec-mocks (3.5.0)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.5.0)
rspec-support (3.5.0)
rspec-wait (0.0.9)
rspec (>= 3, < 4)
slop (3.6.0)
PLATFORMS
ruby
DEPENDENCIES
pry-byebug
rspec
rspec-wait
BUNDLED WITH
1.13.6

View file

@ -1,64 +0,0 @@
# Installation
* [Packages](#packages)
* [Antigen](#antigen)
* [Oh My Zsh](#oh-my-zsh)
* [Manual](#manual-git-clone)
## Packages
| System | Package |
| ------------- | ------------- |
| Debian / Ubuntu | [zsh-autosuggestions OBS repository](https://software.opensuse.org/download.html?project=shells%3Azsh-users%3Azsh-autosuggestions&package=zsh-autosuggestions) |
| Fedora / CentOS / RHEL / Scientific Linux | [zsh-autosuggestions OBS repository](https://software.opensuse.org/download.html?project=shells%3Azsh-users%3Azsh-autosuggestions&package=zsh-autosuggestions) |
| OpenSUSE / SLE | [zsh-autosuggestions OBS repository](https://software.opensuse.org/download.html?project=shells%3Azsh-users%3Azsh-autosuggestions&package=zsh-autosuggestions) |
| Arch Linux / Manjaro / Antergos / Hyperbola | [zsh-autosuggestions](https://www.archlinux.org/packages/zsh-autosuggestions), [zsh-autosuggestions-git](https://aur.archlinux.org/packages/zsh-autosuggestions-git) |
| NixOS | [zsh-autosuggestions](https://github.com/NixOS/nixpkgs/blob/master/pkgs/shells/zsh/zsh-autosuggestions/default.nix) |
| Void Linux | [zsh-autosuggestions](https://github.com/void-linux/void-packages/blob/master/srcpkgs/zsh-autosuggestions/template) |
| Mac OS | [homebrew](https://github.com/Homebrew/homebrew-core/blob/master/Formula/zsh-autosuggestions.rb) |
| NetBSD | [pkgsrc](http://ftp.netbsd.org/pub/pkgsrc/current/pkgsrc/shells/zsh-autosuggestions/README.html) |
## Antigen
1. Add the following to your `.zshrc`:
```sh
antigen bundle zsh-users/zsh-autosuggestions
```
2. Start a new terminal session.
## Oh My Zsh
1. Clone this repository into `$ZSH_CUSTOM/plugins` (by default `~/.oh-my-zsh/custom/plugins`)
```sh
git clone https://github.com/zsh-users/zsh-autosuggestions ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-autosuggestions
```
2. Add the plugin to the list of plugins for Oh My Zsh to load (inside `~/.zshrc`):
```sh
plugins=(
# other plugins...
zsh-autosuggestions
)
```
3. Start a new terminal session.
## Manual (Git Clone)
1. Clone this repository somewhere on your machine. This guide will assume `~/.zsh/zsh-autosuggestions`.
```sh
git clone https://github.com/zsh-users/zsh-autosuggestions ~/.zsh/zsh-autosuggestions
```
2. Add the following to your `.zshrc`:
```sh
source ~/.zsh/zsh-autosuggestions/zsh-autosuggestions.zsh
```
3. Start a new terminal session.

View file

@ -1,23 +0,0 @@
Copyright (c) 2013 Thiago de Arruda
Copyright (c) 2016-2021 Eric Freese
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

View file

@ -1,35 +0,0 @@
SRC_DIR := ./src
SRC_FILES := \
$(SRC_DIR)/config.zsh \
$(SRC_DIR)/util.zsh \
$(SRC_DIR)/bind.zsh \
$(SRC_DIR)/highlight.zsh \
$(SRC_DIR)/widgets.zsh \
$(SRC_DIR)/strategies/*.zsh \
$(SRC_DIR)/fetch.zsh \
$(SRC_DIR)/async.zsh \
$(SRC_DIR)/start.zsh
HEADER_FILES := \
DESCRIPTION \
URL \
VERSION \
LICENSE
PLUGIN_TARGET := zsh-autosuggestions.zsh
all: $(PLUGIN_TARGET)
$(PLUGIN_TARGET): $(HEADER_FILES) $(SRC_FILES)
cat $(HEADER_FILES) | sed -e 's/^/# /g' > $@
cat $(SRC_FILES) >> $@
.PHONY: clean
clean:
rm $(PLUGIN_TARGET)
.PHONY: test
test: all
@test -n "$$TEST_ZSH_BIN" && echo "Testing zsh binary: $(TEST_ZSH_BIN)" || true
bundle exec rspec $(TESTS)

View file

@ -1,191 +0,0 @@
# zsh-autosuggestions
_[Fish](http://fishshell.com/)-like fast/unobtrusive autosuggestions for zsh._
It suggests commands as you type based on history and completions.
Requirements: Zsh v4.3.11 or later
[![CircleCI](https://img.shields.io/circleci/build/github/zsh-users/zsh-autosuggestions.svg)](https://circleci.com/gh/zsh-users/zsh-autosuggestions)
[![Chat on Gitter](https://img.shields.io/gitter/room/zsh-users/zsh-autosuggestions.svg)](https://gitter.im/zsh-users/zsh-autosuggestions)
<a href="https://asciinema.org/a/37390" target="_blank"><img src="https://asciinema.org/a/37390.png" width="400" /></a>
## Installation
See [INSTALL.md](INSTALL.md).
## Usage
As you type commands, you will see a completion offered after the cursor in a muted gray color. This color can be changed by setting the `ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE` variable. See [configuration](#configuration).
If you press the <kbd></kbd> key (`forward-char` widget) or <kbd>End</kbd> (`end-of-line` widget) with the cursor at the end of the buffer, it will accept the suggestion, replacing the contents of the command line buffer with the suggestion.
If you invoke the `forward-word` widget, it will partially accept the suggestion up to the point that the cursor moves to.
## Configuration
You may want to override the default global config variables. Default values of these variables can be found [here](src/config.zsh).
**Note:** If you are using Oh My Zsh, you can put this configuration in a file in the `$ZSH_CUSTOM` directory. See their comments on [overriding internals](https://github.com/robbyrussell/oh-my-zsh/wiki/Customization#overriding-internals).
### Suggestion Highlight Style
Set `ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE` to configure the style that the suggestion is shown with. The default is `fg=8`, which will set the foreground color to color 8 from the [256-color palette](https://upload.wikimedia.org/wikipedia/commons/1/15/Xterm_256color_chart.svg). If your terminal only supports 8 colors, you will need to use a number between 0 and 7.
Background color can also be set, and the suggestion can be styled bold, underlined, or standout. For example, this would show suggestions with bold, underlined, pink text on a cyan background:
```sh
ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE="fg=#ff00ff,bg=cyan,bold,underline"
```
For more info, read the Character Highlighting section of the zsh manual: `man zshzle` or [online](http://zsh.sourceforge.net/Doc/Release/Zsh-Line-Editor.html#Character-Highlighting).
**Note:** Some iTerm2 users have reported [not being able to see the suggestions](https://github.com/zsh-users/zsh-autosuggestions/issues/416#issuecomment-486516333). If this affects you, the problem is likely caused by incorrect color settings. In order to correct this, go into iTerm2's setting, navigate to profile > colors and make sure that the colors for Basic Colors > Background and ANSI Colors > Bright Black are **different**.
### Suggestion Strategy
`ZSH_AUTOSUGGEST_STRATEGY` is an array that specifies how suggestions should be generated. The strategies in the array are tried successively until a suggestion is found. There are currently three built-in strategies to choose from:
- `history`: Chooses the most recent match from history.
- `completion`: Chooses a suggestion based on what tab-completion would suggest. (requires `zpty` module)
- `match_prev_cmd`: Like `history`, but chooses the most recent match whose preceding history item matches the most recently executed command ([more info](src/strategies/match_prev_cmd.zsh)). Note that this strategy won't work as expected with ZSH options that don't preserve the history order such as `HIST_IGNORE_ALL_DUPS` or `HIST_EXPIRE_DUPS_FIRST`.
For example, setting `ZSH_AUTOSUGGEST_STRATEGY=(history completion)` will first try to find a suggestion from your history, but, if it can't find a match, will find a suggestion from the completion engine.
### Widget Mapping
This plugin works by triggering custom behavior when certain [zle widgets](http://zsh.sourceforge.net/Doc/Release/Zsh-Line-Editor.html#Zle-Widgets) are invoked. You can add and remove widgets from these arrays to change the behavior of this plugin:
- `ZSH_AUTOSUGGEST_CLEAR_WIDGETS`: Widgets in this array will clear the suggestion when invoked.
- `ZSH_AUTOSUGGEST_ACCEPT_WIDGETS`: Widgets in this array will accept the suggestion when invoked.
- `ZSH_AUTOSUGGEST_EXECUTE_WIDGETS`: Widgets in this array will execute the suggestion when invoked.
- `ZSH_AUTOSUGGEST_PARTIAL_ACCEPT_WIDGETS`: Widgets in this array will partially accept the suggestion when invoked.
- `ZSH_AUTOSUGGEST_IGNORE_WIDGETS`: Widgets in this array will not trigger any custom behavior.
Widgets that modify the buffer and are not found in any of these arrays will fetch a new suggestion after they are invoked.
**Note:** A widget shouldn't belong to more than one of the above arrays.
### Disabling suggestion for large buffers
Set `ZSH_AUTOSUGGEST_BUFFER_MAX_SIZE` to an integer value to disable autosuggestion for large buffers. The default is unset, which means that autosuggestion will be tried for any buffer size. Recommended value is 20.
This can be useful when pasting large amount of text in the terminal, to avoid triggering autosuggestion for strings that are too long.
### Asynchronous Mode
Suggestions are fetched asynchronously by default in zsh versions 5.0.8 and greater. To disable asynchronous suggestions and fetch them synchronously instead, `unset ZSH_AUTOSUGGEST_USE_ASYNC` after sourcing the plugin.
Alternatively, if you are using a version of zsh older than 5.0.8 and want to enable asynchronous mode, set the `ZSH_AUTOSUGGEST_USE_ASYNC` variable after sourcing the plugin (it can be set to anything). Note that there is [a bug](https://github.com/zsh-users/zsh-autosuggestions/issues/364#issuecomment-481423232) in versions of zsh older than 5.0.8 where <kbd>ctrl</kbd> + <kbd>c</kbd> will fail to reset the prompt immediately after fetching a suggestion asynchronously.
### Disabling automatic widget re-binding
Set `ZSH_AUTOSUGGEST_MANUAL_REBIND` (it can be set to anything) to disable automatic widget re-binding on each precmd. This can be a big boost to performance, but you'll need to handle re-binding yourself if any of the widget lists change or if you or another plugin wrap any of the autosuggest widgets. To re-bind widgets, run `_zsh_autosuggest_bind_widgets`.
### Ignoring history suggestions that match a pattern
Set `ZSH_AUTOSUGGEST_HISTORY_IGNORE` to a [glob pattern](http://zsh.sourceforge.net/Doc/Release/Expansion.html#Glob-Operators) to prevent offering suggestions for history entries that match the pattern. For example, set it to `"cd *"` to never suggest any `cd` commands from history. Or set to `"?(#c50,)"` to never suggest anything 50 characters or longer.
**Note:** This only affects the `history` and `match_prev_cmd` suggestion strategies.
### Skipping completion suggestions for certain cases
Set `ZSH_AUTOSUGGEST_COMPLETION_IGNORE` to a [glob pattern](http://zsh.sourceforge.net/Doc/Release/Expansion.html#Glob-Operators) to prevent offering completion suggestions when the buffer matches that pattern. For example, set it to `"git *"` to disable completion suggestions for git subcommands.
**Note:** This only affects the `completion` suggestion strategy.
### Key Bindings
This plugin provides a few widgets that you can use with `bindkey`:
1. `autosuggest-accept`: Accepts the current suggestion.
2. `autosuggest-execute`: Accepts and executes the current suggestion.
3. `autosuggest-clear`: Clears the current suggestion.
4. `autosuggest-fetch`: Fetches a suggestion (works even when suggestions are disabled).
5. `autosuggest-disable`: Disables suggestions.
6. `autosuggest-enable`: Re-enables suggestions.
7. `autosuggest-toggle`: Toggles between enabled/disabled suggestions.
For example, this would bind <kbd>ctrl</kbd> + <kbd>space</kbd> to accept the current suggestion.
```sh
bindkey '^ ' autosuggest-accept
```
## Troubleshooting
If you have a problem, please search through [the list of issues on GitHub](https://github.com/zsh-users/zsh-autosuggestions/issues?q=) to see if someone else has already reported it.
### Reporting an Issue
Before reporting an issue, please try temporarily disabling sections of your configuration and other plugins that may be conflicting with this plugin to isolate the problem.
When reporting an issue, please include:
- The smallest, simplest `.zshrc` configuration that will reproduce the problem. See [this comment](https://github.com/zsh-users/zsh-autosuggestions/issues/102#issuecomment-180944764) for a good example of what this means.
- The version of zsh you're using (`zsh --version`)
- Which operating system you're running
## Uninstallation
1. Remove the code referencing this plugin from `~/.zshrc`.
2. Remove the git repository from your hard drive
```sh
rm -rf ~/.zsh/zsh-autosuggestions # Or wherever you installed
```
## Development
### Build Process
Edit the source files in `src/`. Run `make` to build `zsh-autosuggestions.zsh` from those source files.
### Pull Requests
Pull requests are welcome! If you send a pull request, please:
- Request to merge into the `develop` branch (*NOT* `master`)
- Match the existing coding conventions.
- Include helpful comments to keep the barrier-to-entry low for people new to the project.
- Write tests that cover your code as much as possible.
### Testing
Tests are written in ruby using the [`rspec`](http://rspec.info/) framework. They use [`tmux`](https://tmux.github.io/) to drive a pseudoterminal, sending simulated keystrokes and making assertions on the terminal content.
Test files live in `spec/`. To run the tests, run `make test`. To run a specific test, run `TESTS=spec/some_spec.rb make test`. You can also specify a `zsh` binary to use by setting the `TEST_ZSH_BIN` environment variable (ex: `TEST_ZSH_BIN=/bin/zsh make test`).
A docker image for testing is available [on docker hub](https://hub.docker.com/r/ericfreese/zsh-autosuggestions-test). It comes with ruby, the bundler dependencies, and all supported versions of zsh installed.
Pull the docker image with:
```sh
docker pull ericfreese/zsh-autosuggestions-test
```
To run the tests for a specific version of zsh (where `<version>` below is substituted with the contents of a line from the [`ZSH_VERSIONS`](ZSH_VERSIONS) file):
```sh
docker run -it -e TEST_ZSH_BIN=zsh-<version> -v $PWD:/zsh-autosuggestions zsh-autosuggestions-test make test
```
## License
This project is licensed under [MIT license](http://opensource.org/licenses/MIT).
For the full text of the license, see the [LICENSE](LICENSE) file.

View file

@ -1 +0,0 @@
https://github.com/zsh-users/zsh-autosuggestions

View file

@ -1 +0,0 @@
v0.7.0

View file

@ -1,17 +0,0 @@
# Zsh releases to run tests against
# See https://github.com/zsh-users/zsh/releases
#
# When modifying this file, rebuild and push docker image:
# $ docker build -t ericfreese/zsh-autosuggestions-test .
# $ docker push ericfreese/zsh-autosuggestions-test
4.3.11
5.0.2
5.0.8
5.1.1
5.2
5.3.1
5.4.2
5.5.1
5.6.2
5.7.1
5.8

View file

@ -1,26 +0,0 @@
#!/bin/sh
set -ex
for v in $(grep "^[^#]" ZSH_VERSIONS); do
mkdir zsh-$v
cd zsh-$v
curl -L https://api.github.com/repos/zsh-users/zsh/tarball/zsh-$v | tar xz --strip=1
./Util/preconfig
./configure --enable-pcre \
--enable-cap \
--enable-multibyte \
--with-term-lib='ncursesw tinfo' \
--with-tcsetpgrp \
--program-suffix="-$v"
make install.bin
make install.modules
make install.fns
cd ..
rm -rf zsh-$v
done

View file

@ -1,70 +0,0 @@
context 'with asynchronous suggestions enabled' do
let(:options) { ["ZSH_AUTOSUGGEST_USE_ASYNC="] }
describe '`up-line-or-beginning-search`' do
let(:before_sourcing) do
-> do
session.
run_command('autoload -U up-line-or-beginning-search').
run_command('zle -N up-line-or-beginning-search').
send_string('bindkey "').
send_keys('C-v').send_keys('up').
send_string('" up-line-or-beginning-search').
send_keys('enter')
end
end
it 'should show previous history entries' do
with_history(
'echo foo',
'echo bar',
'echo baz'
) do
session.clear_screen
3.times { session.send_keys('up') }
wait_for { session.content }.to eq("echo foo")
end
end
end
describe '`copy-earlier-word`' do
let(:before_sourcing) do
-> do
session.
run_command('autoload -Uz copy-earlier-word').
run_command('zle -N copy-earlier-word').
run_command('bindkey "^N" copy-earlier-word')
end
end
it 'should cycle through previous words in the buffer' do
session.clear_screen
session.send_string('foo bar baz')
sleep 0.5
session.send_keys('C-n')
wait_for { session.content }.to eq('foo bar bazbaz')
session.send_keys('C-n')
wait_for { session.content }.to eq('foo bar bazbar')
session.send_keys('C-n')
wait_for { session.content }.to eq('foo bar bazfoo')
end
end
describe 'pressing ^C after fetching a suggestion' do
before do
skip 'Workaround does not work below v5.0.8' if session.zsh_version < Gem::Version.new('5.0.8')
end
it 'terminates the prompt and begins a new one' do
session.send_keys('e')
sleep 0.5
session.send_keys('C-c')
sleep 0.5
session.send_keys('echo')
wait_for { session.content }.to eq("e\necho")
end
end
end

View file

@ -1,14 +0,0 @@
describe 'with `AUTO_CD` option set' do
let(:after_sourcing) do
-> {
session.run_command('setopt AUTO_CD')
session.run_command('autoload compinit && compinit')
}
end
it 'directory names are still completed' do
session.send_string('sr')
session.send_keys('C-i')
wait_for { session.content }.to eq('src/')
end
end

View file

@ -1,43 +0,0 @@
describe 'pasting using bracketed-paste-magic' do
let(:before_sourcing) do
-> do
session.
run_command('autoload -Uz bracketed-paste-magic').
run_command('zle -N bracketed-paste bracketed-paste-magic')
end
end
context 'with suggestions disabled while pasting' do
before do
session.
run_command('bpm_init() { zle autosuggest-disable }').
run_command('bpm_finish() { zle autosuggest-enable }').
run_command('zstyle :bracketed-paste-magic paste-init bpm_init').
run_command('zstyle :bracketed-paste-magic paste-finish bpm_finish')
end
it 'does not show an incorrect suggestion' do
with_history('echo hello') do
session.paste_string("echo #{'a' * 60}")
sleep 1
expect(session.content).to eq("echo #{'a' * 60}")
end
end
end
context 'with `bracketed-paste` added to the list of widgets that clear the suggestion' do
let(:options) { ['ZSH_AUTOSUGGEST_CLEAR_WIDGETS+=(bracketed-paste)'] }
it 'does not retain an old suggestion' do
with_history ('echo foo') do
session.send_string('echo ')
wait_for { session.content }.to eq('echo foo')
session.paste_string('bar')
wait_for { session.content }.to eq('echo bar')
session.send_keys('C-a') # Any cursor movement works
sleep 1
expect(session.content).to eq('echo bar')
end
end
end
end

View file

@ -1,14 +0,0 @@
describe 'a running zpty command' do
let(:before_sourcing) { -> { session.run_command('zmodload zsh/zpty && zpty -b kitty cat') } }
context 'when using `completion` strategy' do
let(:options) { ["ZSH_AUTOSUGGEST_STRATEGY=completion"] }
it 'is not affected' do
session.send_keys('a').send_keys('C-h')
session.run_command('zpty -t kitty; echo $?')
wait_for { session.content }.to end_with("\n0")
end
end
end

View file

@ -1,12 +0,0 @@
describe 'with `GLOB_SUBST` option set' do
let(:after_sourcing) do
-> {
session.run_command('setopt GLOB_SUBST')
}
end
it 'error messages are not printed' do
session.send_string('[[')
wait_for { session.content }.to eq('[[')
end
end

View file

@ -1,13 +0,0 @@
describe 'rebinding [' do
context 'initialized before sourcing the plugin' do
before do
session.run_command("function [ { $commands[\\[] \"$@\" }")
session.clear_screen
end
it 'executes the custom behavior and the built-in behavior' do
session.send_string('asdf')
wait_for { session.content }.to eq('asdf')
end
end
end

View file

@ -1,80 +0,0 @@
describe 'when using vi mode' do
let(:before_sourcing) do
-> do
session.run_command('bindkey -v')
end
end
describe 'moving the cursor after exiting insert mode' do
it 'should not clear the current suggestion' do
with_history('foobar foo') do
session.
send_string('foo').
send_keys('escape').
send_keys('h')
wait_for { session.content }.to eq('foobar foo')
end
end
end
describe '`vi-forward-word-end`' do
it 'should accept through the end of the current word' do
with_history('foobar foo') do
session.
send_string('foo').
send_keys('escape').
send_keys('e'). # vi-forward-word-end
send_keys('a'). # vi-add-next
send_string('baz')
wait_for { session.content }.to eq('foobarbaz')
end
end
end
describe '`vi-forward-word`' do
it 'should accept through the first character of the next word' do
with_history('foobar foo') do
session.
send_string('foo').
send_keys('escape').
send_keys('w'). # vi-forward-word
send_keys('a'). # vi-add-next
send_string('az')
wait_for { session.content }.to eq('foobar faz')
end
end
end
describe '`vi-find-next-char`' do
it 'should accept through the next occurrence of the character' do
with_history('foobar foo') do
session.
send_string('foo').
send_keys('escape').
send_keys('f'). # vi-find-next-char
send_keys('o').
send_keys('a'). # vi-add-next
send_string('b')
wait_for { session.content }.to eq('foobar fob')
end
end
end
describe '`vi-delete`' do
it 'should be able to remove the last character in the buffer' do
skip 'deleting last char did not work below zsh version 5.0.8' if session.zsh_version < Gem::Version.new('5.0.8')
session.
send_string('echo foo').
send_keys('escape').
send_keys('d').
send_keys('l')
wait_for { session.content }.to eq('echo fo')
end
end
end

View file

@ -1,39 +0,0 @@
describe 'a wrapped widget' do
let(:widget) { 'backward-delete-char' }
context 'initialized before sourcing the plugin' do
let(:before_sourcing) do
-> do
session.
run_command("_orig_#{widget}() { zle .#{widget} }").
run_command("zle -N orig-#{widget} _orig_#{widget}").
run_command("#{widget}-magic() { zle orig-#{widget}; BUFFER+=b }").
run_command("zle -N #{widget} #{widget}-magic")
end
end
it 'executes the custom behavior and the built-in behavior' do
with_history('foobar', 'foodar') do
session.send_string('food').send_keys('C-h')
wait_for { session.content }.to eq('foobar')
end
end
end
context 'initialized after sourcing the plugin' do
before do
session.
run_command("zle -N orig-#{widget} ${widgets[#{widget}]#*:}").
run_command("#{widget}-magic() { zle orig-#{widget}; BUFFER+=b }").
run_command("zle -N #{widget} #{widget}-magic").
clear_screen
end
it 'executes the custom behavior and the built-in behavior' do
with_history('foobar', 'foodar') do
session.send_string('food').send_keys('C-h')
wait_for { session.content }.to eq('foobar')
end
end
end
end

View file

@ -1,24 +0,0 @@
describe 'using `zle -U`' do
let(:before_sourcing) do
-> do
session.
run_command('_zsh_autosuggest_strategy_test() { sleep 1; _zsh_autosuggest_strategy_history "$1" }').
run_command('foo() { zle -U - "echo hello" }; zle -N foo; bindkey ^B foo')
end
end
let(:options) { ['unset ZSH_AUTOSUGGEST_USE_ASYNC', 'ZSH_AUTOSUGGEST_STRATEGY=test'] }
# TODO: This is only possible with the $KEYS_QUEUED_COUNT widget parameter, coming soon...
xit 'does not fetch a suggestion for every inserted character' do
session.send_keys('C-b')
wait_for { session.content }.to eq('echo hello')
end
it 'shows a suggestion when the widget completes' do
with_history('echo hello world') do
session.send_keys('C-b')
wait_for { session.content(esc_seqs: true) }.to match(/\Aecho hello\e\[[0-9]+m world/)
end
end
end

View file

@ -1,23 +0,0 @@
context 'with some items in the kill ring' do
before do
session.
send_string('echo foo').
send_keys('C-u').
send_string('echo bar').
send_keys('C-u')
end
describe '`yank-pop`' do
it 'should cycle through all items in the kill ring' do
session.send_keys('C-y')
wait_for { session.content }.to eq('echo bar')
session.send_keys('escape').send_keys('y')
wait_for { session.content }.to eq('echo foo')
session.send_keys('escape').send_keys('y')
wait_for { session.content }.to eq('echo bar')
end
end
end

View file

@ -1,17 +0,0 @@
context 'with zle-line-init unignored' do
let(:after_sourcing) do
-> do
session.
run_command('setopt extendedglob').
run_command('ZSH_AUTOSUGGEST_IGNORE_WIDGETS=(${(@)ZSH_AUTOSUGGEST_IGNORE_WIDGETS:#zle-\*} zle-\^line-init)').
run_command('zle-line-init() { BUFFER="echo" }')
end
end
it 'should fetch a suggestion on each line initialization' do
with_history('echo foo') do
session.run_command('zle -N zle-line-init')
wait_for { session.content }.to end_with('echo foo')
end
end
end

View file

@ -1,8 +0,0 @@
describe 'a multi-line suggestion' do
it 'should be displayed on multiple lines' do
with_history("echo \"\n\"") do
session.send_keys('e')
wait_for { session.content }.to eq("echo \"\n\"")
end
end
end

View file

@ -1,30 +0,0 @@
describe 'a suggestion' do
let(:term_opts) { { width: 200 } }
let(:long_command) { "echo #{'a' * 100}" }
around do |example|
with_history(long_command) { example.run }
end
it 'is provided for any buffer length' do
session.send_string(long_command[0...-1])
wait_for { session.content }.to eq(long_command)
end
context 'when ZSH_AUTOSUGGEST_BUFFER_MAX_SIZE is specified' do
let(:buffer_max_size) { 10 }
let(:options) { ["ZSH_AUTOSUGGEST_BUFFER_MAX_SIZE=#{buffer_max_size}"] }
it 'is provided when the buffer is shorter than the specified length' do
session.send_string(long_command[0...(buffer_max_size - 1)])
wait_for { session.content }.to eq(long_command)
end
it 'is provided when the buffer is equal to the specified length' do
session.send_string(long_command[0...(buffer_max_size)])
wait_for { session.content }.to eq(long_command)
end
it 'is not provided when the buffer is longer than the specified length'
end
end

View file

@ -1,7 +0,0 @@
describe 'a displayed suggestion' do
it 'is shown in the default style'
describe 'when ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE is set to a zle_highlight string' do
it 'is shown in the specified style'
end
end

View file

@ -1,7 +0,0 @@
describe 'an original zle widget' do
context 'is accessible with the default prefix'
context 'when ZSH_AUTOSUGGEST_ORIGINAL_WIDGET_PREFIX is set' do
it 'is accessible with the specified prefix'
end
end

View file

@ -1,55 +0,0 @@
describe 'a suggestion for a given prefix' do
let(:history_strategy) { '_zsh_autosuggest_strategy_history() { suggestion="history" }' }
let(:foobar_strategy) { '_zsh_autosuggest_strategy_foobar() { [[ "foobar baz" = $1* ]] && suggestion="foobar baz" }' }
let(:foobaz_strategy) { '_zsh_autosuggest_strategy_foobaz() { [[ "foobaz bar" = $1* ]] && suggestion="foobaz bar" }' }
let(:after_sourcing) do
-> do
session.run_command(history_strategy)
end
end
it 'by default is determined by calling the `history` strategy function' do
session.send_string('h')
wait_for { session.content }.to eq('history')
end
context 'when ZSH_AUTOSUGGEST_STRATEGY is set to an array' do
let(:after_sourcing) do
-> do
session.
run_command(foobar_strategy).
run_command(foobaz_strategy).
run_command('ZSH_AUTOSUGGEST_STRATEGY=(foobar foobaz)')
end
end
it 'is determined by the first strategy function to return a suggestion' do
session.send_string('foo')
wait_for { session.content }.to eq('foobar baz')
session.send_string('baz')
wait_for { session.content }.to eq('foobaz bar')
end
end
context 'when ZSH_AUTOSUGGEST_STRATEGY is set to a string' do
let(:after_sourcing) do
-> do
session.
run_command(foobar_strategy).
run_command(foobaz_strategy).
run_command('ZSH_AUTOSUGGEST_STRATEGY="foobar foobaz"')
end
end
it 'is determined by the first strategy function to return a suggestion' do
session.send_string('foo')
wait_for { session.content }.to eq('foobar baz')
session.send_string('baz')
wait_for { session.content }.to eq('foobaz bar')
end
end
end

View file

@ -1,121 +0,0 @@
describe 'a zle widget' do
let(:widget) { 'my-widget' }
let(:before_sourcing) { -> { session.run_command("#{widget}() {}; zle -N #{widget}; bindkey ^B #{widget}") } }
context 'when added to ZSH_AUTOSUGGEST_ACCEPT_WIDGETS' do
let(:options) { ["ZSH_AUTOSUGGEST_ACCEPT_WIDGETS+=(#{widget})"] }
it 'accepts the suggestion and moves the cursor to the end of the buffer when invoked' do
with_history('echo hello') do
session.send_string('e')
wait_for { session.content }.to eq('echo hello')
session.send_keys('C-b')
wait_for { session.content(esc_seqs: true) }.to eq('echo hello')
wait_for { session.cursor }.to eq([10, 0])
end
end
end
context 'when added to ZSH_AUTOSUGGEST_CLEAR_WIDGETS' do
let(:options) { ["ZSH_AUTOSUGGEST_CLEAR_WIDGETS+=(#{widget})"] }
it 'clears the suggestion when invoked' do
with_history('echo hello') do
session.send_string('e')
wait_for { session.content }.to eq('echo hello')
session.send_keys('C-b')
wait_for { session.content }.to eq('e')
end
end
end
context 'when added to ZSH_AUTOSUGGEST_EXECUTE_WIDGETS' do
let(:options) { ["ZSH_AUTOSUGGEST_EXECUTE_WIDGETS+=(#{widget})"] }
it 'executes the suggestion when invoked' do
with_history('echo hello') do
session.send_string('e')
wait_for { session.content }.to eq('echo hello')
session.send_keys('C-b')
wait_for { session.content }.to end_with("\nhello")
end
end
end
context 'when added to ZSH_AUTOSUGGEST_IGNORE_WIDGETS' do
let(:options) { ["ZSH_AUTOSUGGEST_IGNORE_WIDGETS=(#{widget})"] }
it 'should not be wrapped with an autosuggest widget' do
session.run_command("echo $widgets[#{widget}]")
wait_for { session.content }.to end_with("\nuser:#{widget}")
end
end
context 'that moves the cursor forward' do
before { session.run_command("#{widget}() { zle forward-char }") }
context 'when added to ZSH_AUTOSUGGEST_PARTIAL_ACCEPT_WIDGETS' do
let(:options) { ["ZSH_AUTOSUGGEST_PARTIAL_ACCEPT_WIDGETS=(#{widget})"] }
it 'accepts the suggestion as far as the cursor is moved when invoked' do
with_history('echo hello') do
session.send_string('e')
wait_for { session.content }.to start_with('echo hello')
session.send_keys('C-b')
wait_for { session.content(esc_seqs: true) }.to match(/\Aec\e\[[0-9]+mho hello/)
end
end
end
end
context 'that modifies the buffer' do
before { session.run_command("#{widget}() { BUFFER=\"foo\" }") }
context 'when not added to any of the widget lists' do
it 'modifies the buffer and fetches a new suggestion' do
with_history('foobar') do
session.send_keys('C-b')
wait_for { session.content }.to eq('foobar')
end
end
end
end
end
describe 'a modification to the widget lists' do
let(:widget) { 'my-widget' }
let(:before_sourcing) { -> { session.run_command("#{widget}() {}; zle -N #{widget}; bindkey ^B #{widget}") } }
before { session.run_command("ZSH_AUTOSUGGEST_ACCEPT_WIDGETS+=(#{widget})") }
it 'takes effect on the next cmd line' do
with_history('echo hello') do
session.send_string('e')
wait_for { session.content }.to eq('echo hello')
session.send_keys('C-b')
wait_for { session.content(esc_seqs: true) }.to eq('echo hello')
end
end
context 'when manual rebind is enabled' do
let(:options) { ["ZSH_AUTOSUGGEST_MANUAL_REBIND=true"] }
it 'does not take effect until bind command is re-run' do
with_history('echo hello') do
session.send_string('e')
wait_for { session.content }.to eq('echo hello')
session.send_keys('C-b')
sleep 1
expect(session.content(esc_seqs: true)).not_to eq('echo hello')
session.send_keys('C-c')
session.run_command('_zsh_autosuggest_bind_widgets').clear_screen
wait_for { session.content }.to eq('')
session.send_string('e')
wait_for { session.content }.to eq('echo hello')
session.send_keys('C-b')
wait_for { session.content(esc_seqs: true) }.to eq('echo hello')
end
end
end
end

View file

@ -1,54 +0,0 @@
require 'pry'
require 'rspec/wait'
require 'terminal_session'
require 'tempfile'
RSpec.shared_context 'terminal session' do
let(:term_opts) { {} }
let(:session) { TerminalSession.new(term_opts) }
let(:before_sourcing) { -> {} }
let(:after_sourcing) { -> {} }
let(:options) { [] }
around do |example|
before_sourcing.call
session.run_command(['source zsh-autosuggestions.zsh', *options].join('; '))
after_sourcing.call
session.clear_screen
example.run
session.destroy
end
def with_history(*commands, &block)
Tempfile.create do |f|
f.write(commands.map{|c| c.gsub("\n", "\\\n")}.join("\n"))
f.flush
session.run_command('fc -p')
session.run_command("fc -R #{f.path}")
session.clear_screen
yield block
session.send_keys('C-c')
session.run_command('fc -P')
end
end
end
RSpec.configure do |config|
config.expect_with :rspec do |expectations|
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
end
config.mock_with :rspec do |mocks|
mocks.verify_partial_doubles = true
end
config.wait_timeout = 2
config.include_context 'terminal session'
end

View file

@ -1,72 +0,0 @@
describe 'the `completion` suggestion strategy' do
let(:options) { ['ZSH_AUTOSUGGEST_STRATEGY=completion'] }
let(:before_sourcing) do
-> do
session.
run_command('autoload compinit && compinit').
run_command('_foo() { compadd bar; compadd bat }').
run_command('_num() { compadd two; compadd three }').
run_command('compdef _foo baz').
run_command('compdef _num one')
end
end
it 'suggests the first completion result' do
session.send_string('baz ')
wait_for { session.content }.to eq('baz bar')
end
it 'does not add extra carriage returns when prefix has a line feed' do
skip '`stty` does not work inside zpty below zsh version 5.0.3' if session.zsh_version < Gem::Version.new('5.0.3')
session.send_string('baz \\').send_keys('C-v', 'C-j')
wait_for { session.content }.to eq("baz \\\nbar")
end
context 'when `_complete` is aliased' do
let(:before_sourcing) do
-> do
session.
run_command('autoload compinit && compinit').
run_command('_foo() { compadd bar; compadd bat }').
run_command('compdef _foo baz').
run_command('alias _complete=_complete')
end
end
it 'suggests the first completion result' do
session.send_string('baz ')
wait_for { session.content }.to eq('baz bar')
end
end
context 'when ZSH_AUTOSUGGEST_COMPLETION_IGNORE is set to a pattern' do
let(:options) { ['ZSH_AUTOSUGGEST_STRATEGY=completion', 'ZSH_AUTOSUGGEST_COMPLETION_IGNORE="one *"'] }
it 'makes suggestions when the buffer does not match the pattern' do
session.send_string('baz ')
wait_for { session.content }.to eq('baz bar')
end
it 'does not make suggestions when the buffer matches the pattern' do
session.send_string('one t')
sleep 1
expect(session.content).to eq('one t')
end
end
context 'when async mode is enabled' do
let(:options) { ['ZSH_AUTOSUGGEST_USE_ASYNC=true', 'ZSH_AUTOSUGGEST_STRATEGY=completion'] }
it 'suggests the first completion result' do
session.send_string('baz ')
wait_for { session.content }.to eq('baz bar')
end
it 'does not add extra carriage returns when prefix has a line feed' do
skip '`stty` does not work inside zpty below zsh version 5.0.3' if session.zsh_version < Gem::Version.new('5.0.3')
session.send_string('baz \\').send_keys('C-v', 'C-j')
wait_for { session.content }.to eq("baz \\\nbar")
end
end
end

View file

@ -1,23 +0,0 @@
require 'strategies/special_characters_helper'
describe 'the `history` suggestion strategy' do
it 'suggests the last matching history entry' do
with_history('ls foo', 'ls bar', 'echo baz') do
session.send_string('ls')
wait_for { session.content }.to eq('ls bar')
end
end
context 'when ZSH_AUTOSUGGEST_HISTORY_IGNORE is set to a pattern' do
let(:options) { ['ZSH_AUTOSUGGEST_HISTORY_IGNORE="* bar"'] }
it 'does not make suggestions that match the pattern' do
with_history('ls foo', 'ls bar', 'echo baz') do
session.send_string('ls')
wait_for { session.content }.to eq('ls foo')
end
end
end
include_examples 'special characters'
end

View file

@ -1,34 +0,0 @@
require 'strategies/special_characters_helper'
describe 'the `match_prev_cmd` strategy' do
let(:options) { ['ZSH_AUTOSUGGEST_STRATEGY=match_prev_cmd'] }
let(:history) { [
'echo what',
'ls foo',
'echo what',
'ls bar',
'ls baz',
'echo what'
] }
it 'suggests the last matching history entry after the previous command' do
with_history(*history) do
session.send_string('ls')
wait_for { session.content }.to eq('ls bar')
end
end
context 'when ZSH_AUTOSUGGEST_HISTORY_IGNORE is set to a pattern' do
let(:options) { ['ZSH_AUTOSUGGEST_STRATEGY=match_prev_cmd', 'ZSH_AUTOSUGGEST_HISTORY_IGNORE="* bar"'] }
it 'does not make suggestions that match the pattern' do
with_history(*history) do
session.send_string('ls')
wait_for { session.content }.to eq('ls foo')
end
end
end
include_examples 'special characters'
end

View file

@ -1,75 +0,0 @@
shared_examples 'special characters' do
describe 'a special character in the buffer should be treated like any other character' do
it 'asterisk' do
with_history('echo "hello*"', 'echo "hello."') do
session.send_string('echo "hello*')
wait_for { session.content }.to eq('echo "hello*"')
end
end
it 'question mark' do
with_history('echo "hello?"', 'echo "hello."') do
session.send_string('echo "hello?')
wait_for { session.content }.to eq('echo "hello?"')
end
end
it 'backslash' do
with_history('echo "hello\nworld"') do
session.send_string('echo "hello\\')
wait_for { session.content }.to eq('echo "hello\nworld"')
end
end
it 'double backslash' do
with_history('echo "\\\\"') do
session.send_string('echo "\\\\')
wait_for { session.content }.to eq('echo "\\\\"')
end
end
it 'tilde' do
with_history('echo ~/foo') do
session.send_string('echo ~')
wait_for { session.content }.to eq('echo ~/foo')
end
end
it 'parentheses' do
with_history('echo "$(ls foo)"') do
session.send_string('echo "$(')
wait_for { session.content }.to eq('echo "$(ls foo)"')
end
end
it 'square bracket' do
with_history('echo "$history[123]"') do
session.send_string('echo "$history[')
wait_for { session.content }.to eq('echo "$history[123]"')
session.send_string('123]')
wait_for { session.content }.to eq('echo "$history[123]"')
end
end
it 'octothorpe' do
with_history('echo "#yolo"') do
session.send_string('echo "#')
wait_for { session.content }.to eq('echo "#yolo"')
end
end
it 'caret' do
with_history('echo "^A"', 'echo "^B"') do
session.send_string('echo "^A')
wait_for { session.content }.to eq('echo "^A"')
end
end
it 'dash' do
with_history('-foo() {}') do
session.send_string('-')
wait_for { session.content }.to eq('-foo() {}')
end
end
end
end

View file

@ -1,99 +0,0 @@
require 'securerandom'
class TerminalSession
ZSH_BIN = ENV['TEST_ZSH_BIN'] || 'zsh'
def initialize(opts = {})
opts = {
width: 80,
height: 24,
prompt: '',
term: 'xterm-256color',
zsh_bin: ZSH_BIN
}.merge(opts)
@opts = opts
cmd="PS1=\"#{opts[:prompt]}\" TERM=#{opts[:term]} #{ZSH_BIN} -f"
tmux_command("new-session -d -x #{opts[:width]} -y #{opts[:height]} '#{cmd}'")
end
def zsh_version
@zsh_version ||= Gem::Version.new(`#{ZSH_BIN} -c 'echo -n $ZSH_VERSION'`)
end
def tmux_socket_name
@tmux_socket_name ||= SecureRandom.hex(6)
end
def run_command(command)
send_string(command)
send_keys('enter')
self
end
def send_string(str)
tmux_command("send-keys -t 0 -l -- '#{str.gsub("'", "\\'")}'")
self
end
def send_keys(*keys)
tmux_command("send-keys -t 0 #{keys.join(' ')}")
self
end
def paste_string(str)
tmux_command("set-buffer -- '#{str}'")
tmux_command("paste-buffer -dpr -t 0")
self
end
def content(esc_seqs: false)
cmd = 'capture-pane -p -t 0'
cmd += ' -e' if esc_seqs
tmux_command(cmd).strip
end
def clear_screen
send_keys('C-l')
i = 0
until content == opts[:prompt] || i > 20 do
sleep(0.1)
i = i + 1
end
self
end
def destroy
tmux_command('kill-session')
end
def cursor
tmux_command("display-message -t 0 -p '\#{cursor_x},\#{cursor_y}'").
strip.
split(',').
map(&:to_i)
end
def attach!
tmux_command('attach-session')
end
private
attr_reader :opts
def tmux_command(cmd)
out = `tmux -u -L #{tmux_socket_name} #{cmd}`
raise("tmux error running: '#{cmd}'") unless $?.success?
out
end
end

View file

@ -1,19 +0,0 @@
describe 'the `autosuggest-disable` widget' do
before do
session.run_command('bindkey ^B autosuggest-disable')
end
it 'disables suggestions and clears the suggestion' do
with_history('echo hello') do
session.send_string('echo')
wait_for { session.content }.to eq('echo hello')
session.send_keys('C-b')
wait_for { session.content }.to eq('echo')
session.send_string(' h')
sleep 1
expect(session.content).to eq('echo h')
end
end
end

View file

@ -1,42 +0,0 @@
describe 'the `autosuggest-enable` widget' do
before do
session.
run_command('typeset -g _ZSH_AUTOSUGGEST_DISABLED').
run_command('bindkey ^B autosuggest-enable')
end
it 'enables suggestions and fetches a suggestion' do
with_history('echo hello') do
session.send_string('e')
sleep 1
expect(session.content).to eq('e')
session.send_keys('C-b')
session.send_string('c')
wait_for { session.content }.to eq('echo hello')
end
end
context 'invoked on an empty buffer' do
it 'does not fetch a suggestion' do
with_history('echo hello') do
session.send_keys('C-b')
sleep 1
expect(session.content).to eq('')
end
end
end
context 'invoked on a non-empty buffer' do
it 'fetches a suggestion' do
with_history('echo hello') do
session.send_string('e')
sleep 1
expect(session.content).to eq('e')
session.send_keys('C-b')
wait_for { session.content }.to eq('echo hello')
end
end
end
end

View file

@ -1,24 +0,0 @@
describe 'the `autosuggest-fetch` widget' do
context 'when suggestions are disabled' do
before do
session.
run_command('bindkey ^B autosuggest-disable').
run_command('bindkey ^F autosuggest-fetch').
send_keys('C-b')
end
it 'will fetch and display a suggestion' do
with_history('echo hello') do
session.send_string('echo h')
sleep 1
expect(session.content).to eq('echo h')
session.send_keys('C-f')
wait_for { session.content }.to eq('echo hello')
session.send_string('e')
wait_for { session.content }.to eq('echo hello')
end
end
end
end

View file

@ -1,26 +0,0 @@
describe 'the `autosuggest-toggle` widget' do
before do
session.run_command('bindkey ^B autosuggest-toggle')
end
it 'toggles suggestions' do
with_history('echo world', 'echo hello') do
session.send_string('echo')
wait_for { session.content }.to eq('echo hello')
session.send_keys('C-b')
wait_for { session.content }.to eq('echo')
session.send_string(' h')
sleep 1
expect(session.content).to eq('echo h')
session.send_keys('C-b')
wait_for { session.content }.to eq('echo hello')
session.send_keys('C-h')
session.send_string('w')
wait_for { session.content }.to eq('echo world')
end
end
end

View file

@ -1,76 +0,0 @@
#--------------------------------------------------------------------#
# Async #
#--------------------------------------------------------------------#
_zsh_autosuggest_async_request() {
zmodload zsh/system 2>/dev/null # For `$sysparams`
typeset -g _ZSH_AUTOSUGGEST_ASYNC_FD _ZSH_AUTOSUGGEST_CHILD_PID
# If we've got a pending request, cancel it
if [[ -n "$_ZSH_AUTOSUGGEST_ASYNC_FD" ]] && { true <&$_ZSH_AUTOSUGGEST_ASYNC_FD } 2>/dev/null; then
# Close the file descriptor and remove the handler
exec {_ZSH_AUTOSUGGEST_ASYNC_FD}<&-
zle -F $_ZSH_AUTOSUGGEST_ASYNC_FD
# We won't know the pid unless the user has zsh/system module installed
if [[ -n "$_ZSH_AUTOSUGGEST_CHILD_PID" ]]; then
# Zsh will make a new process group for the child process only if job
# control is enabled (MONITOR option)
if [[ -o MONITOR ]]; then
# Send the signal to the process group to kill any processes that may
# have been forked by the suggestion strategy
kill -TERM -$_ZSH_AUTOSUGGEST_CHILD_PID 2>/dev/null
else
# Kill just the child process since it wasn't placed in a new process
# group. If the suggestion strategy forked any child processes they may
# be orphaned and left behind.
kill -TERM $_ZSH_AUTOSUGGEST_CHILD_PID 2>/dev/null
fi
fi
fi
# Fork a process to fetch a suggestion and open a pipe to read from it
exec {_ZSH_AUTOSUGGEST_ASYNC_FD}< <(
# Tell parent process our pid
echo $sysparams[pid]
# Fetch and print the suggestion
local suggestion
_zsh_autosuggest_fetch_suggestion "$1"
echo -nE "$suggestion"
)
# There's a weird bug here where ^C stops working unless we force a fork
# See https://github.com/zsh-users/zsh-autosuggestions/issues/364
autoload -Uz is-at-least
is-at-least 5.8 || command true
# Read the pid from the child process
read _ZSH_AUTOSUGGEST_CHILD_PID <&$_ZSH_AUTOSUGGEST_ASYNC_FD
# When the fd is readable, call the response handler
zle -F "$_ZSH_AUTOSUGGEST_ASYNC_FD" _zsh_autosuggest_async_response
}
# Called when new data is ready to be read from the pipe
# First arg will be fd ready for reading
# Second arg will be passed in case of error
_zsh_autosuggest_async_response() {
emulate -L zsh
local suggestion
if [[ -z "$2" || "$2" == "hup" ]]; then
# Read everything from the fd and give it as a suggestion
IFS='' read -rd '' -u $1 suggestion
zle autosuggest-suggest -- "$suggestion"
# Close the fd
exec {1}<&-
fi
# Always remove the handler
zle -F "$1"
}

View file

@ -1,106 +0,0 @@
#--------------------------------------------------------------------#
# Widget Helpers #
#--------------------------------------------------------------------#
_zsh_autosuggest_incr_bind_count() {
typeset -gi bind_count=$((_ZSH_AUTOSUGGEST_BIND_COUNTS[$1]+1))
_ZSH_AUTOSUGGEST_BIND_COUNTS[$1]=$bind_count
}
# Bind a single widget to an autosuggest widget, saving a reference to the original widget
_zsh_autosuggest_bind_widget() {
typeset -gA _ZSH_AUTOSUGGEST_BIND_COUNTS
local widget=$1
local autosuggest_action=$2
local prefix=$ZSH_AUTOSUGGEST_ORIGINAL_WIDGET_PREFIX
local -i bind_count
# Save a reference to the original widget
case $widgets[$widget] in
# Already bound
user:_zsh_autosuggest_(bound|orig)_*)
bind_count=$((_ZSH_AUTOSUGGEST_BIND_COUNTS[$widget]))
;;
# User-defined widget
user:*)
_zsh_autosuggest_incr_bind_count $widget
zle -N $prefix$bind_count-$widget ${widgets[$widget]#*:}
;;
# Built-in widget
builtin)
_zsh_autosuggest_incr_bind_count $widget
eval "_zsh_autosuggest_orig_${(q)widget}() { zle .${(q)widget} }"
zle -N $prefix$bind_count-$widget _zsh_autosuggest_orig_$widget
;;
# Completion widget
completion:*)
_zsh_autosuggest_incr_bind_count $widget
eval "zle -C $prefix$bind_count-${(q)widget} ${${(s.:.)widgets[$widget]}[2,3]}"
;;
esac
# Pass the original widget's name explicitly into the autosuggest
# function. Use this passed in widget name to call the original
# widget instead of relying on the $WIDGET variable being set
# correctly. $WIDGET cannot be trusted because other plugins call
# zle without the `-w` flag (e.g. `zle self-insert` instead of
# `zle self-insert -w`).
eval "_zsh_autosuggest_bound_${bind_count}_${(q)widget}() {
_zsh_autosuggest_widget_$autosuggest_action $prefix$bind_count-${(q)widget} \$@
}"
# Create the bound widget
zle -N -- $widget _zsh_autosuggest_bound_${bind_count}_$widget
}
# Map all configured widgets to the right autosuggest widgets
_zsh_autosuggest_bind_widgets() {
emulate -L zsh
local widget
local ignore_widgets
ignore_widgets=(
.\*
_\*
${_ZSH_AUTOSUGGEST_BUILTIN_ACTIONS/#/autosuggest-}
$ZSH_AUTOSUGGEST_ORIGINAL_WIDGET_PREFIX\*
$ZSH_AUTOSUGGEST_IGNORE_WIDGETS
)
# Find every widget we might want to bind and bind it appropriately
for widget in ${${(f)"$(builtin zle -la)"}:#${(j:|:)~ignore_widgets}}; do
if [[ -n ${ZSH_AUTOSUGGEST_CLEAR_WIDGETS[(r)$widget]} ]]; then
_zsh_autosuggest_bind_widget $widget clear
elif [[ -n ${ZSH_AUTOSUGGEST_ACCEPT_WIDGETS[(r)$widget]} ]]; then
_zsh_autosuggest_bind_widget $widget accept
elif [[ -n ${ZSH_AUTOSUGGEST_EXECUTE_WIDGETS[(r)$widget]} ]]; then
_zsh_autosuggest_bind_widget $widget execute
elif [[ -n ${ZSH_AUTOSUGGEST_PARTIAL_ACCEPT_WIDGETS[(r)$widget]} ]]; then
_zsh_autosuggest_bind_widget $widget partial_accept
else
# Assume any unspecified widget might modify the buffer
_zsh_autosuggest_bind_widget $widget modify
fi
done
}
# Given the name of an original widget and args, invoke it, if it exists
_zsh_autosuggest_invoke_original_widget() {
# Do nothing unless called with at least one arg
(( $# )) || return 0
local original_widget_name="$1"
shift
if (( ${+widgets[$original_widget_name]} )); then
zle $original_widget_name -- $@
fi
}

View file

@ -1,93 +0,0 @@
#--------------------------------------------------------------------#
# Global Configuration Variables #
#--------------------------------------------------------------------#
# Color to use when highlighting suggestion
# Uses format of `region_highlight`
# More info: http://zsh.sourceforge.net/Doc/Release/Zsh-Line-Editor.html#Zle-Widgets
(( ! ${+ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE} )) &&
typeset -g ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE='fg=8'
# Prefix to use when saving original versions of bound widgets
(( ! ${+ZSH_AUTOSUGGEST_ORIGINAL_WIDGET_PREFIX} )) &&
typeset -g ZSH_AUTOSUGGEST_ORIGINAL_WIDGET_PREFIX=autosuggest-orig-
# Strategies to use to fetch a suggestion
# Will try each strategy in order until a suggestion is returned
(( ! ${+ZSH_AUTOSUGGEST_STRATEGY} )) && {
typeset -ga ZSH_AUTOSUGGEST_STRATEGY
ZSH_AUTOSUGGEST_STRATEGY=(history)
}
# Widgets that clear the suggestion
(( ! ${+ZSH_AUTOSUGGEST_CLEAR_WIDGETS} )) && {
typeset -ga ZSH_AUTOSUGGEST_CLEAR_WIDGETS
ZSH_AUTOSUGGEST_CLEAR_WIDGETS=(
history-search-forward
history-search-backward
history-beginning-search-forward
history-beginning-search-backward
history-substring-search-up
history-substring-search-down
up-line-or-beginning-search
down-line-or-beginning-search
up-line-or-history
down-line-or-history
accept-line
copy-earlier-word
)
}
# Widgets that accept the entire suggestion
(( ! ${+ZSH_AUTOSUGGEST_ACCEPT_WIDGETS} )) && {
typeset -ga ZSH_AUTOSUGGEST_ACCEPT_WIDGETS
ZSH_AUTOSUGGEST_ACCEPT_WIDGETS=(
forward-char
end-of-line
vi-forward-char
vi-end-of-line
vi-add-eol
)
}
# Widgets that accept the entire suggestion and execute it
(( ! ${+ZSH_AUTOSUGGEST_EXECUTE_WIDGETS} )) && {
typeset -ga ZSH_AUTOSUGGEST_EXECUTE_WIDGETS
ZSH_AUTOSUGGEST_EXECUTE_WIDGETS=(
)
}
# Widgets that accept the suggestion as far as the cursor moves
(( ! ${+ZSH_AUTOSUGGEST_PARTIAL_ACCEPT_WIDGETS} )) && {
typeset -ga ZSH_AUTOSUGGEST_PARTIAL_ACCEPT_WIDGETS
ZSH_AUTOSUGGEST_PARTIAL_ACCEPT_WIDGETS=(
forward-word
emacs-forward-word
vi-forward-word
vi-forward-word-end
vi-forward-blank-word
vi-forward-blank-word-end
vi-find-next-char
vi-find-next-char-skip
)
}
# Widgets that should be ignored (globbing supported but must be escaped)
(( ! ${+ZSH_AUTOSUGGEST_IGNORE_WIDGETS} )) && {
typeset -ga ZSH_AUTOSUGGEST_IGNORE_WIDGETS
ZSH_AUTOSUGGEST_IGNORE_WIDGETS=(
orig-\*
beep
run-help
set-local-history
which-command
yank
yank-pop
zle-\*
)
}
# Pty name for capturing completions for completion suggestion strategy
(( ! ${+ZSH_AUTOSUGGEST_COMPLETIONS_PTY_NAME} )) &&
typeset -g ZSH_AUTOSUGGEST_COMPLETIONS_PTY_NAME=zsh_autosuggest_completion_pty

View file

@ -1,27 +0,0 @@
#--------------------------------------------------------------------#
# Fetch Suggestion #
#--------------------------------------------------------------------#
# Loops through all specified strategies and returns a suggestion
# from the first strategy to provide one.
#
_zsh_autosuggest_fetch_suggestion() {
typeset -g suggestion
local -a strategies
local strategy
# Ensure we are working with an array
strategies=(${=ZSH_AUTOSUGGEST_STRATEGY})
for strategy in $strategies; do
# Try to get a suggestion from this strategy
_zsh_autosuggest_strategy_$strategy "$1"
# Ensure the suggestion matches the prefix
[[ "$suggestion" != "$1"* ]] && unset suggestion
# Break once we've found a valid suggestion
[[ -n "$suggestion" ]] && break
done
}

View file

@ -1,26 +0,0 @@
#--------------------------------------------------------------------#
# Highlighting #
#--------------------------------------------------------------------#
# If there was a highlight, remove it
_zsh_autosuggest_highlight_reset() {
typeset -g _ZSH_AUTOSUGGEST_LAST_HIGHLIGHT
if [[ -n "$_ZSH_AUTOSUGGEST_LAST_HIGHLIGHT" ]]; then
region_highlight=("${(@)region_highlight:#$_ZSH_AUTOSUGGEST_LAST_HIGHLIGHT}")
unset _ZSH_AUTOSUGGEST_LAST_HIGHLIGHT
fi
}
# If there's a suggestion, highlight it
_zsh_autosuggest_highlight_apply() {
typeset -g _ZSH_AUTOSUGGEST_LAST_HIGHLIGHT
if (( $#POSTDISPLAY )); then
typeset -g _ZSH_AUTOSUGGEST_LAST_HIGHLIGHT="$#BUFFER $(($#BUFFER + $#POSTDISPLAY)) $ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE"
region_highlight+=("$_ZSH_AUTOSUGGEST_LAST_HIGHLIGHT")
else
unset _ZSH_AUTOSUGGEST_LAST_HIGHLIGHT
fi
}

View file

@ -1,33 +0,0 @@
#--------------------------------------------------------------------#
# Start #
#--------------------------------------------------------------------#
# Start the autosuggestion widgets
_zsh_autosuggest_start() {
# By default we re-bind widgets on every precmd to ensure we wrap other
# wrappers. Specifically, highlighting breaks if our widgets are wrapped by
# zsh-syntax-highlighting widgets. This also allows modifications to the
# widget list variables to take effect on the next precmd. However this has
# a decent performance hit, so users can set ZSH_AUTOSUGGEST_MANUAL_REBIND
# to disable the automatic re-binding.
if (( ${+ZSH_AUTOSUGGEST_MANUAL_REBIND} )); then
add-zsh-hook -d precmd _zsh_autosuggest_start
fi
_zsh_autosuggest_bind_widgets
}
# Mark for auto-loading the functions that we use
autoload -Uz add-zsh-hook is-at-least
# Automatically enable asynchronous mode in newer versions of zsh. Disable for
# older versions because there is a bug when using async mode where ^C does not
# work immediately after fetching a suggestion.
# See https://github.com/zsh-users/zsh-autosuggestions/issues/364
if is-at-least 5.0.8; then
typeset -g ZSH_AUTOSUGGEST_USE_ASYNC=
fi
# Start the autosuggestion widgets on the next precmd
add-zsh-hook precmd _zsh_autosuggest_start

View file

@ -1,137 +0,0 @@
#--------------------------------------------------------------------#
# Completion Suggestion Strategy #
#--------------------------------------------------------------------#
# Fetches a suggestion from the completion engine
#
_zsh_autosuggest_capture_postcompletion() {
# Always insert the first completion into the buffer
compstate[insert]=1
# Don't list completions
unset 'compstate[list]'
}
_zsh_autosuggest_capture_completion_widget() {
# Add a post-completion hook to be called after all completions have been
# gathered. The hook can modify compstate to affect what is done with the
# gathered completions.
local -a +h comppostfuncs
comppostfuncs=(_zsh_autosuggest_capture_postcompletion)
# Only capture completions at the end of the buffer
CURSOR=$#BUFFER
# Run the original widget wrapping `.complete-word` so we don't
# recursively try to fetch suggestions, since our pty is forked
# after autosuggestions is initialized.
zle -- ${(k)widgets[(r)completion:.complete-word:_main_complete]}
if is-at-least 5.0.3; then
# Don't do any cr/lf transformations. We need to do this immediately before
# output because if we do it in setup, onlcr will be re-enabled when we enter
# vared in the async code path. There is a bug in zpty module in older versions
# where the tty is not properly attached to the pty slave, resulting in stty
# getting stopped with a SIGTTOU. See zsh-workers thread 31660 and upstream
# commit f75904a38
stty -onlcr -ocrnl -F /dev/tty
fi
# The completion has been added, print the buffer as the suggestion
echo -nE - $'\0'$BUFFER$'\0'
}
zle -N autosuggest-capture-completion _zsh_autosuggest_capture_completion_widget
_zsh_autosuggest_capture_setup() {
# There is a bug in zpty module in older zsh versions by which a
# zpty that exits will kill all zpty processes that were forked
# before it. Here we set up a zsh exit hook to SIGKILL the zpty
# process immediately, before it has a chance to kill any other
# zpty processes.
if ! is-at-least 5.4; then
zshexit() {
# The zsh builtin `kill` fails sometimes in older versions
# https://unix.stackexchange.com/a/477647/156673
kill -KILL $$ 2>&- || command kill -KILL $$
# Block for long enough for the signal to come through
sleep 1
}
fi
# Try to avoid any suggestions that wouldn't match the prefix
zstyle ':completion:*' matcher-list ''
zstyle ':completion:*' path-completion false
zstyle ':completion:*' max-errors 0 not-numeric
bindkey '^I' autosuggest-capture-completion
}
_zsh_autosuggest_capture_completion_sync() {
_zsh_autosuggest_capture_setup
zle autosuggest-capture-completion
}
_zsh_autosuggest_capture_completion_async() {
_zsh_autosuggest_capture_setup
zmodload zsh/parameter 2>/dev/null || return # For `$functions`
# Make vared completion work as if for a normal command line
# https://stackoverflow.com/a/7057118/154703
autoload +X _complete
functions[_original_complete]=$functions[_complete]
function _complete() {
unset 'compstate[vared]'
_original_complete "$@"
}
# Open zle with buffer set so we can capture completions for it
vared 1
}
_zsh_autosuggest_strategy_completion() {
# Reset options to defaults and enable LOCAL_OPTIONS
emulate -L zsh
# Enable extended glob for completion ignore pattern
setopt EXTENDED_GLOB
typeset -g suggestion
local line REPLY
# Exit if we don't have completions
whence compdef >/dev/null || return
# Exit if we don't have zpty
zmodload zsh/zpty 2>/dev/null || return
# Exit if our search string matches the ignore pattern
[[ -n "$ZSH_AUTOSUGGEST_COMPLETION_IGNORE" ]] && [[ "$1" == $~ZSH_AUTOSUGGEST_COMPLETION_IGNORE ]] && return
# Zle will be inactive if we are in async mode
if zle; then
zpty $ZSH_AUTOSUGGEST_COMPLETIONS_PTY_NAME _zsh_autosuggest_capture_completion_sync
else
zpty $ZSH_AUTOSUGGEST_COMPLETIONS_PTY_NAME _zsh_autosuggest_capture_completion_async "\$1"
zpty -w $ZSH_AUTOSUGGEST_COMPLETIONS_PTY_NAME $'\t'
fi
{
# The completion result is surrounded by null bytes, so read the
# content between the first two null bytes.
zpty -r $ZSH_AUTOSUGGEST_COMPLETIONS_PTY_NAME line '*'$'\0''*'$'\0'
# Extract the suggestion from between the null bytes. On older
# versions of zsh (older than 5.3), we sometimes get extra bytes after
# the second null byte, so trim those off the end.
# See http://www.zsh.org/mla/workers/2015/msg03290.html
suggestion="${${(@0)line}[2]}"
} always {
# Destroy the pty
zpty -d $ZSH_AUTOSUGGEST_COMPLETIONS_PTY_NAME
}
}

View file

@ -1,32 +0,0 @@
#--------------------------------------------------------------------#
# History Suggestion Strategy #
#--------------------------------------------------------------------#
# Suggests the most recent history item that matches the given
# prefix.
#
_zsh_autosuggest_strategy_history() {
# Reset options to defaults and enable LOCAL_OPTIONS
emulate -L zsh
# Enable globbing flags so that we can use (#m) and (x~y) glob operator
setopt EXTENDED_GLOB
# Escape backslashes and all of the glob operators so we can use
# this string as a pattern to search the $history associative array.
# - (#m) globbing flag enables setting references for match data
# TODO: Use (b) flag when we can drop support for zsh older than v5.0.8
local prefix="${1//(#m)[\\*?[\]<>()|^~#]/\\$MATCH}"
# Get the history items that match the prefix, excluding those that match
# the ignore pattern
local pattern="$prefix*"
if [[ -n $ZSH_AUTOSUGGEST_HISTORY_IGNORE ]]; then
pattern="($pattern)~($ZSH_AUTOSUGGEST_HISTORY_IGNORE)"
fi
# Give the first history item matching the pattern as the suggestion
# - (r) subscript flag makes the pattern match on values
typeset -g suggestion="${history[(r)$pattern]}"
}

View file

@ -1,66 +0,0 @@
#--------------------------------------------------------------------#
# Match Previous Command Suggestion Strategy #
#--------------------------------------------------------------------#
# Suggests the most recent history item that matches the given
# prefix and whose preceding history item also matches the most
# recently executed command.
#
# For example, suppose your history has the following entries:
# - pwd
# - ls foo
# - ls bar
# - pwd
#
# Given the history list above, when you type 'ls', the suggestion
# will be 'ls foo' rather than 'ls bar' because your most recently
# executed command (pwd) was previously followed by 'ls foo'.
#
# Note that this strategy won't work as expected with ZSH options that don't
# preserve the history order such as `HIST_IGNORE_ALL_DUPS` or
# `HIST_EXPIRE_DUPS_FIRST`.
_zsh_autosuggest_strategy_match_prev_cmd() {
# Reset options to defaults and enable LOCAL_OPTIONS
emulate -L zsh
# Enable globbing flags so that we can use (#m) and (x~y) glob operator
setopt EXTENDED_GLOB
# TODO: Use (b) flag when we can drop support for zsh older than v5.0.8
local prefix="${1//(#m)[\\*?[\]<>()|^~#]/\\$MATCH}"
# Get the history items that match the prefix, excluding those that match
# the ignore pattern
local pattern="$prefix*"
if [[ -n $ZSH_AUTOSUGGEST_HISTORY_IGNORE ]]; then
pattern="($pattern)~($ZSH_AUTOSUGGEST_HISTORY_IGNORE)"
fi
# Get all history event numbers that correspond to history
# entries that match the pattern
local history_match_keys
history_match_keys=(${(k)history[(R)$~pattern]})
# By default we use the first history number (most recent history entry)
local histkey="${history_match_keys[1]}"
# Get the previously executed command
local prev_cmd="$(_zsh_autosuggest_escape_command "${history[$((HISTCMD-1))]}")"
# Iterate up to the first 200 history event numbers that match $prefix
for key in "${(@)history_match_keys[1,200]}"; do
# Stop if we ran out of history
[[ $key -gt 1 ]] || break
# See if the history entry preceding the suggestion matches the
# previous command, and use it if it does
if [[ "${history[$((key - 1))]}" == "$prev_cmd" ]]; then
histkey="$key"
break
fi
done
# Give back the matched history entry
typeset -g suggestion="$history[$histkey]"
}

View file

@ -1,11 +0,0 @@
#--------------------------------------------------------------------#
# Utility Functions #
#--------------------------------------------------------------------#
_zsh_autosuggest_escape_command() {
setopt localoptions EXTENDED_GLOB
# Escape special chars in the string (requires EXTENDED_GLOB)
echo -E "${1//(#m)[\"\'\\()\[\]|*?~]/\\$MATCH}"
}

View file

@ -1,231 +0,0 @@
#--------------------------------------------------------------------#
# Autosuggest Widget Implementations #
#--------------------------------------------------------------------#
# Disable suggestions
_zsh_autosuggest_disable() {
typeset -g _ZSH_AUTOSUGGEST_DISABLED
_zsh_autosuggest_clear
}
# Enable suggestions
_zsh_autosuggest_enable() {
unset _ZSH_AUTOSUGGEST_DISABLED
if (( $#BUFFER )); then
_zsh_autosuggest_fetch
fi
}
# Toggle suggestions (enable/disable)
_zsh_autosuggest_toggle() {
if (( ${+_ZSH_AUTOSUGGEST_DISABLED} )); then
_zsh_autosuggest_enable
else
_zsh_autosuggest_disable
fi
}
# Clear the suggestion
_zsh_autosuggest_clear() {
# Remove the suggestion
unset POSTDISPLAY
_zsh_autosuggest_invoke_original_widget $@
}
# Modify the buffer and get a new suggestion
_zsh_autosuggest_modify() {
local -i retval
# Only available in zsh >= 5.4
local -i KEYS_QUEUED_COUNT
# Save the contents of the buffer/postdisplay
local orig_buffer="$BUFFER"
local orig_postdisplay="$POSTDISPLAY"
# Clear suggestion while waiting for next one
unset POSTDISPLAY
# Original widget may modify the buffer
_zsh_autosuggest_invoke_original_widget $@
retval=$?
emulate -L zsh
# Don't fetch a new suggestion if there's more input to be read immediately
if (( $PENDING > 0 || $KEYS_QUEUED_COUNT > 0 )); then
POSTDISPLAY="$orig_postdisplay"
return $retval
fi
# Optimize if manually typing in the suggestion or if buffer hasn't changed
if [[ "$BUFFER" = "$orig_buffer"* && "$orig_postdisplay" = "${BUFFER:$#orig_buffer}"* ]]; then
POSTDISPLAY="${orig_postdisplay:$(($#BUFFER - $#orig_buffer))}"
return $retval
fi
# Bail out if suggestions are disabled
if (( ${+_ZSH_AUTOSUGGEST_DISABLED} )); then
return $?
fi
# Get a new suggestion if the buffer is not empty after modification
if (( $#BUFFER > 0 )); then
if [[ -z "$ZSH_AUTOSUGGEST_BUFFER_MAX_SIZE" ]] || (( $#BUFFER <= $ZSH_AUTOSUGGEST_BUFFER_MAX_SIZE )); then
_zsh_autosuggest_fetch
fi
fi
return $retval
}
# Fetch a new suggestion based on what's currently in the buffer
_zsh_autosuggest_fetch() {
if (( ${+ZSH_AUTOSUGGEST_USE_ASYNC} )); then
_zsh_autosuggest_async_request "$BUFFER"
else
local suggestion
_zsh_autosuggest_fetch_suggestion "$BUFFER"
_zsh_autosuggest_suggest "$suggestion"
fi
}
# Offer a suggestion
_zsh_autosuggest_suggest() {
emulate -L zsh
local suggestion="$1"
if [[ -n "$suggestion" ]] && (( $#BUFFER )); then
POSTDISPLAY="${suggestion#$BUFFER}"
else
unset POSTDISPLAY
fi
}
# Accept the entire suggestion
_zsh_autosuggest_accept() {
local -i retval max_cursor_pos=$#BUFFER
# When vicmd keymap is active, the cursor can't move all the way
# to the end of the buffer
if [[ "$KEYMAP" = "vicmd" ]]; then
max_cursor_pos=$((max_cursor_pos - 1))
fi
# If we're not in a valid state to accept a suggestion, just run the
# original widget and bail out
if (( $CURSOR != $max_cursor_pos || !$#POSTDISPLAY )); then
_zsh_autosuggest_invoke_original_widget $@
return
fi
# Only accept if the cursor is at the end of the buffer
# Add the suggestion to the buffer
BUFFER="$BUFFER$POSTDISPLAY"
# Remove the suggestion
unset POSTDISPLAY
# Run the original widget before manually moving the cursor so that the
# cursor movement doesn't make the widget do something unexpected
_zsh_autosuggest_invoke_original_widget $@
retval=$?
# Move the cursor to the end of the buffer
if [[ "$KEYMAP" = "vicmd" ]]; then
CURSOR=$(($#BUFFER - 1))
else
CURSOR=$#BUFFER
fi
return $retval
}
# Accept the entire suggestion and execute it
_zsh_autosuggest_execute() {
# Add the suggestion to the buffer
BUFFER="$BUFFER$POSTDISPLAY"
# Remove the suggestion
unset POSTDISPLAY
# Call the original `accept-line` to handle syntax highlighting or
# other potential custom behavior
_zsh_autosuggest_invoke_original_widget "accept-line"
}
# Partially accept the suggestion
_zsh_autosuggest_partial_accept() {
local -i retval cursor_loc
# Save the contents of the buffer so we can restore later if needed
local original_buffer="$BUFFER"
# Temporarily accept the suggestion.
BUFFER="$BUFFER$POSTDISPLAY"
# Original widget moves the cursor
_zsh_autosuggest_invoke_original_widget $@
retval=$?
# Normalize cursor location across vi/emacs modes
cursor_loc=$CURSOR
if [[ "$KEYMAP" = "vicmd" ]]; then
cursor_loc=$((cursor_loc + 1))
fi
# If we've moved past the end of the original buffer
if (( $cursor_loc > $#original_buffer )); then
# Set POSTDISPLAY to text right of the cursor
POSTDISPLAY="${BUFFER[$(($cursor_loc + 1)),$#BUFFER]}"
# Clip the buffer at the cursor
BUFFER="${BUFFER[1,$cursor_loc]}"
else
# Restore the original buffer
BUFFER="$original_buffer"
fi
return $retval
}
() {
typeset -ga _ZSH_AUTOSUGGEST_BUILTIN_ACTIONS
_ZSH_AUTOSUGGEST_BUILTIN_ACTIONS=(
clear
fetch
suggest
accept
execute
enable
disable
toggle
)
local action
for action in $_ZSH_AUTOSUGGEST_BUILTIN_ACTIONS modify partial_accept; do
eval "_zsh_autosuggest_widget_$action() {
local -i retval
_zsh_autosuggest_highlight_reset
_zsh_autosuggest_$action \$@
retval=\$?
_zsh_autosuggest_highlight_apply
zle -R
return \$retval
}"
done
for action in $_ZSH_AUTOSUGGEST_BUILTIN_ACTIONS; do
zle -N autosuggest-$action _zsh_autosuggest_widget_$action
done
}

View file

@ -1 +0,0 @@
source ${0:A:h}/zsh-autosuggestions.zsh

View file

@ -1,864 +0,0 @@
# Fish-like fast/unobtrusive autosuggestions for zsh.
# https://github.com/zsh-users/zsh-autosuggestions
# v0.7.0
# Copyright (c) 2013 Thiago de Arruda
# Copyright (c) 2016-2021 Eric Freese
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation
# files (the "Software"), to deal in the Software without
# restriction, including without limitation the rights to use,
# copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following
# conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
# OTHER DEALINGS IN THE SOFTWARE.
#--------------------------------------------------------------------#
# Global Configuration Variables #
#--------------------------------------------------------------------#
# Color to use when highlighting suggestion
# Uses format of `region_highlight`
# More info: http://zsh.sourceforge.net/Doc/Release/Zsh-Line-Editor.html#Zle-Widgets
(( ! ${+ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE} )) &&
typeset -g ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE='fg=8'
# Prefix to use when saving original versions of bound widgets
(( ! ${+ZSH_AUTOSUGGEST_ORIGINAL_WIDGET_PREFIX} )) &&
typeset -g ZSH_AUTOSUGGEST_ORIGINAL_WIDGET_PREFIX=autosuggest-orig-
# Strategies to use to fetch a suggestion
# Will try each strategy in order until a suggestion is returned
(( ! ${+ZSH_AUTOSUGGEST_STRATEGY} )) && {
typeset -ga ZSH_AUTOSUGGEST_STRATEGY
ZSH_AUTOSUGGEST_STRATEGY=(history)
}
# Widgets that clear the suggestion
(( ! ${+ZSH_AUTOSUGGEST_CLEAR_WIDGETS} )) && {
typeset -ga ZSH_AUTOSUGGEST_CLEAR_WIDGETS
ZSH_AUTOSUGGEST_CLEAR_WIDGETS=(
history-search-forward
history-search-backward
history-beginning-search-forward
history-beginning-search-backward
history-substring-search-up
history-substring-search-down
up-line-or-beginning-search
down-line-or-beginning-search
up-line-or-history
down-line-or-history
accept-line
copy-earlier-word
)
}
# Widgets that accept the entire suggestion
(( ! ${+ZSH_AUTOSUGGEST_ACCEPT_WIDGETS} )) && {
typeset -ga ZSH_AUTOSUGGEST_ACCEPT_WIDGETS
ZSH_AUTOSUGGEST_ACCEPT_WIDGETS=(
forward-char
end-of-line
vi-forward-char
vi-end-of-line
vi-add-eol
)
}
# Widgets that accept the entire suggestion and execute it
(( ! ${+ZSH_AUTOSUGGEST_EXECUTE_WIDGETS} )) && {
typeset -ga ZSH_AUTOSUGGEST_EXECUTE_WIDGETS
ZSH_AUTOSUGGEST_EXECUTE_WIDGETS=(
)
}
# Widgets that accept the suggestion as far as the cursor moves
(( ! ${+ZSH_AUTOSUGGEST_PARTIAL_ACCEPT_WIDGETS} )) && {
typeset -ga ZSH_AUTOSUGGEST_PARTIAL_ACCEPT_WIDGETS
ZSH_AUTOSUGGEST_PARTIAL_ACCEPT_WIDGETS=(
forward-word
emacs-forward-word
vi-forward-word
vi-forward-word-end
vi-forward-blank-word
vi-forward-blank-word-end
vi-find-next-char
vi-find-next-char-skip
)
}
# Widgets that should be ignored (globbing supported but must be escaped)
(( ! ${+ZSH_AUTOSUGGEST_IGNORE_WIDGETS} )) && {
typeset -ga ZSH_AUTOSUGGEST_IGNORE_WIDGETS
ZSH_AUTOSUGGEST_IGNORE_WIDGETS=(
orig-\*
beep
run-help
set-local-history
which-command
yank
yank-pop
zle-\*
)
}
# Pty name for capturing completions for completion suggestion strategy
(( ! ${+ZSH_AUTOSUGGEST_COMPLETIONS_PTY_NAME} )) &&
typeset -g ZSH_AUTOSUGGEST_COMPLETIONS_PTY_NAME=zsh_autosuggest_completion_pty
#--------------------------------------------------------------------#
# Utility Functions #
#--------------------------------------------------------------------#
_zsh_autosuggest_escape_command() {
setopt localoptions EXTENDED_GLOB
# Escape special chars in the string (requires EXTENDED_GLOB)
echo -E "${1//(#m)[\"\'\\()\[\]|*?~]/\\$MATCH}"
}
#--------------------------------------------------------------------#
# Widget Helpers #
#--------------------------------------------------------------------#
_zsh_autosuggest_incr_bind_count() {
typeset -gi bind_count=$((_ZSH_AUTOSUGGEST_BIND_COUNTS[$1]+1))
_ZSH_AUTOSUGGEST_BIND_COUNTS[$1]=$bind_count
}
# Bind a single widget to an autosuggest widget, saving a reference to the original widget
_zsh_autosuggest_bind_widget() {
typeset -gA _ZSH_AUTOSUGGEST_BIND_COUNTS
local widget=$1
local autosuggest_action=$2
local prefix=$ZSH_AUTOSUGGEST_ORIGINAL_WIDGET_PREFIX
local -i bind_count
# Save a reference to the original widget
case $widgets[$widget] in
# Already bound
user:_zsh_autosuggest_(bound|orig)_*)
bind_count=$((_ZSH_AUTOSUGGEST_BIND_COUNTS[$widget]))
;;
# User-defined widget
user:*)
_zsh_autosuggest_incr_bind_count $widget
zle -N $prefix$bind_count-$widget ${widgets[$widget]#*:}
;;
# Built-in widget
builtin)
_zsh_autosuggest_incr_bind_count $widget
eval "_zsh_autosuggest_orig_${(q)widget}() { zle .${(q)widget} }"
zle -N $prefix$bind_count-$widget _zsh_autosuggest_orig_$widget
;;
# Completion widget
completion:*)
_zsh_autosuggest_incr_bind_count $widget
eval "zle -C $prefix$bind_count-${(q)widget} ${${(s.:.)widgets[$widget]}[2,3]}"
;;
esac
# Pass the original widget's name explicitly into the autosuggest
# function. Use this passed in widget name to call the original
# widget instead of relying on the $WIDGET variable being set
# correctly. $WIDGET cannot be trusted because other plugins call
# zle without the `-w` flag (e.g. `zle self-insert` instead of
# `zle self-insert -w`).
eval "_zsh_autosuggest_bound_${bind_count}_${(q)widget}() {
_zsh_autosuggest_widget_$autosuggest_action $prefix$bind_count-${(q)widget} \$@
}"
# Create the bound widget
zle -N -- $widget _zsh_autosuggest_bound_${bind_count}_$widget
}
# Map all configured widgets to the right autosuggest widgets
_zsh_autosuggest_bind_widgets() {
emulate -L zsh
local widget
local ignore_widgets
ignore_widgets=(
.\*
_\*
${_ZSH_AUTOSUGGEST_BUILTIN_ACTIONS/#/autosuggest-}
$ZSH_AUTOSUGGEST_ORIGINAL_WIDGET_PREFIX\*
$ZSH_AUTOSUGGEST_IGNORE_WIDGETS
)
# Find every widget we might want to bind and bind it appropriately
for widget in ${${(f)"$(builtin zle -la)"}:#${(j:|:)~ignore_widgets}}; do
if [[ -n ${ZSH_AUTOSUGGEST_CLEAR_WIDGETS[(r)$widget]} ]]; then
_zsh_autosuggest_bind_widget $widget clear
elif [[ -n ${ZSH_AUTOSUGGEST_ACCEPT_WIDGETS[(r)$widget]} ]]; then
_zsh_autosuggest_bind_widget $widget accept
elif [[ -n ${ZSH_AUTOSUGGEST_EXECUTE_WIDGETS[(r)$widget]} ]]; then
_zsh_autosuggest_bind_widget $widget execute
elif [[ -n ${ZSH_AUTOSUGGEST_PARTIAL_ACCEPT_WIDGETS[(r)$widget]} ]]; then
_zsh_autosuggest_bind_widget $widget partial_accept
else
# Assume any unspecified widget might modify the buffer
_zsh_autosuggest_bind_widget $widget modify
fi
done
}
# Given the name of an original widget and args, invoke it, if it exists
_zsh_autosuggest_invoke_original_widget() {
# Do nothing unless called with at least one arg
(( $# )) || return 0
local original_widget_name="$1"
shift
if (( ${+widgets[$original_widget_name]} )); then
zle $original_widget_name -- $@
fi
}
#--------------------------------------------------------------------#
# Highlighting #
#--------------------------------------------------------------------#
# If there was a highlight, remove it
_zsh_autosuggest_highlight_reset() {
typeset -g _ZSH_AUTOSUGGEST_LAST_HIGHLIGHT
if [[ -n "$_ZSH_AUTOSUGGEST_LAST_HIGHLIGHT" ]]; then
region_highlight=("${(@)region_highlight:#$_ZSH_AUTOSUGGEST_LAST_HIGHLIGHT}")
unset _ZSH_AUTOSUGGEST_LAST_HIGHLIGHT
fi
}
# If there's a suggestion, highlight it
_zsh_autosuggest_highlight_apply() {
typeset -g _ZSH_AUTOSUGGEST_LAST_HIGHLIGHT
if (( $#POSTDISPLAY )); then
typeset -g _ZSH_AUTOSUGGEST_LAST_HIGHLIGHT="$#BUFFER $(($#BUFFER + $#POSTDISPLAY)) $ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE"
region_highlight+=("$_ZSH_AUTOSUGGEST_LAST_HIGHLIGHT")
else
unset _ZSH_AUTOSUGGEST_LAST_HIGHLIGHT
fi
}
#--------------------------------------------------------------------#
# Autosuggest Widget Implementations #
#--------------------------------------------------------------------#
# Disable suggestions
_zsh_autosuggest_disable() {
typeset -g _ZSH_AUTOSUGGEST_DISABLED
_zsh_autosuggest_clear
}
# Enable suggestions
_zsh_autosuggest_enable() {
unset _ZSH_AUTOSUGGEST_DISABLED
if (( $#BUFFER )); then
_zsh_autosuggest_fetch
fi
}
# Toggle suggestions (enable/disable)
_zsh_autosuggest_toggle() {
if (( ${+_ZSH_AUTOSUGGEST_DISABLED} )); then
_zsh_autosuggest_enable
else
_zsh_autosuggest_disable
fi
}
# Clear the suggestion
_zsh_autosuggest_clear() {
# Remove the suggestion
unset POSTDISPLAY
_zsh_autosuggest_invoke_original_widget $@
}
# Modify the buffer and get a new suggestion
_zsh_autosuggest_modify() {
local -i retval
# Only available in zsh >= 5.4
local -i KEYS_QUEUED_COUNT
# Save the contents of the buffer/postdisplay
local orig_buffer="$BUFFER"
local orig_postdisplay="$POSTDISPLAY"
# Clear suggestion while waiting for next one
unset POSTDISPLAY
# Original widget may modify the buffer
_zsh_autosuggest_invoke_original_widget $@
retval=$?
emulate -L zsh
# Don't fetch a new suggestion if there's more input to be read immediately
if (( $PENDING > 0 || $KEYS_QUEUED_COUNT > 0 )); then
POSTDISPLAY="$orig_postdisplay"
return $retval
fi
# Optimize if manually typing in the suggestion or if buffer hasn't changed
if [[ "$BUFFER" = "$orig_buffer"* && "$orig_postdisplay" = "${BUFFER:$#orig_buffer}"* ]]; then
POSTDISPLAY="${orig_postdisplay:$(($#BUFFER - $#orig_buffer))}"
return $retval
fi
# Bail out if suggestions are disabled
if (( ${+_ZSH_AUTOSUGGEST_DISABLED} )); then
return $?
fi
# Get a new suggestion if the buffer is not empty after modification
if (( $#BUFFER > 0 )); then
if [[ -z "$ZSH_AUTOSUGGEST_BUFFER_MAX_SIZE" ]] || (( $#BUFFER <= $ZSH_AUTOSUGGEST_BUFFER_MAX_SIZE )); then
_zsh_autosuggest_fetch
fi
fi
return $retval
}
# Fetch a new suggestion based on what's currently in the buffer
_zsh_autosuggest_fetch() {
if (( ${+ZSH_AUTOSUGGEST_USE_ASYNC} )); then
_zsh_autosuggest_async_request "$BUFFER"
else
local suggestion
_zsh_autosuggest_fetch_suggestion "$BUFFER"
_zsh_autosuggest_suggest "$suggestion"
fi
}
# Offer a suggestion
_zsh_autosuggest_suggest() {
emulate -L zsh
local suggestion="$1"
if [[ -n "$suggestion" ]] && (( $#BUFFER )); then
POSTDISPLAY="${suggestion#$BUFFER}"
else
unset POSTDISPLAY
fi
}
# Accept the entire suggestion
_zsh_autosuggest_accept() {
local -i retval max_cursor_pos=$#BUFFER
# When vicmd keymap is active, the cursor can't move all the way
# to the end of the buffer
if [[ "$KEYMAP" = "vicmd" ]]; then
max_cursor_pos=$((max_cursor_pos - 1))
fi
# If we're not in a valid state to accept a suggestion, just run the
# original widget and bail out
if (( $CURSOR != $max_cursor_pos || !$#POSTDISPLAY )); then
_zsh_autosuggest_invoke_original_widget $@
return
fi
# Only accept if the cursor is at the end of the buffer
# Add the suggestion to the buffer
BUFFER="$BUFFER$POSTDISPLAY"
# Remove the suggestion
unset POSTDISPLAY
# Run the original widget before manually moving the cursor so that the
# cursor movement doesn't make the widget do something unexpected
_zsh_autosuggest_invoke_original_widget $@
retval=$?
# Move the cursor to the end of the buffer
if [[ "$KEYMAP" = "vicmd" ]]; then
CURSOR=$(($#BUFFER - 1))
else
CURSOR=$#BUFFER
fi
return $retval
}
# Accept the entire suggestion and execute it
_zsh_autosuggest_execute() {
# Add the suggestion to the buffer
BUFFER="$BUFFER$POSTDISPLAY"
# Remove the suggestion
unset POSTDISPLAY
# Call the original `accept-line` to handle syntax highlighting or
# other potential custom behavior
_zsh_autosuggest_invoke_original_widget "accept-line"
}
# Partially accept the suggestion
_zsh_autosuggest_partial_accept() {
local -i retval cursor_loc
# Save the contents of the buffer so we can restore later if needed
local original_buffer="$BUFFER"
# Temporarily accept the suggestion.
BUFFER="$BUFFER$POSTDISPLAY"
# Original widget moves the cursor
_zsh_autosuggest_invoke_original_widget $@
retval=$?
# Normalize cursor location across vi/emacs modes
cursor_loc=$CURSOR
if [[ "$KEYMAP" = "vicmd" ]]; then
cursor_loc=$((cursor_loc + 1))
fi
# If we've moved past the end of the original buffer
if (( $cursor_loc > $#original_buffer )); then
# Set POSTDISPLAY to text right of the cursor
POSTDISPLAY="${BUFFER[$(($cursor_loc + 1)),$#BUFFER]}"
# Clip the buffer at the cursor
BUFFER="${BUFFER[1,$cursor_loc]}"
else
# Restore the original buffer
BUFFER="$original_buffer"
fi
return $retval
}
() {
typeset -ga _ZSH_AUTOSUGGEST_BUILTIN_ACTIONS
_ZSH_AUTOSUGGEST_BUILTIN_ACTIONS=(
clear
fetch
suggest
accept
execute
enable
disable
toggle
)
local action
for action in $_ZSH_AUTOSUGGEST_BUILTIN_ACTIONS modify partial_accept; do
eval "_zsh_autosuggest_widget_$action() {
local -i retval
_zsh_autosuggest_highlight_reset
_zsh_autosuggest_$action \$@
retval=\$?
_zsh_autosuggest_highlight_apply
zle -R
return \$retval
}"
done
for action in $_ZSH_AUTOSUGGEST_BUILTIN_ACTIONS; do
zle -N autosuggest-$action _zsh_autosuggest_widget_$action
done
}
#--------------------------------------------------------------------#
# Completion Suggestion Strategy #
#--------------------------------------------------------------------#
# Fetches a suggestion from the completion engine
#
_zsh_autosuggest_capture_postcompletion() {
# Always insert the first completion into the buffer
compstate[insert]=1
# Don't list completions
unset 'compstate[list]'
}
_zsh_autosuggest_capture_completion_widget() {
# Add a post-completion hook to be called after all completions have been
# gathered. The hook can modify compstate to affect what is done with the
# gathered completions.
local -a +h comppostfuncs
comppostfuncs=(_zsh_autosuggest_capture_postcompletion)
# Only capture completions at the end of the buffer
CURSOR=$#BUFFER
# Run the original widget wrapping `.complete-word` so we don't
# recursively try to fetch suggestions, since our pty is forked
# after autosuggestions is initialized.
zle -- ${(k)widgets[(r)completion:.complete-word:_main_complete]}
if is-at-least 5.0.3; then
# Don't do any cr/lf transformations. We need to do this immediately before
# output because if we do it in setup, onlcr will be re-enabled when we enter
# vared in the async code path. There is a bug in zpty module in older versions
# where the tty is not properly attached to the pty slave, resulting in stty
# getting stopped with a SIGTTOU. See zsh-workers thread 31660 and upstream
# commit f75904a38
stty -onlcr -ocrnl -F /dev/tty
fi
# The completion has been added, print the buffer as the suggestion
echo -nE - $'\0'$BUFFER$'\0'
}
zle -N autosuggest-capture-completion _zsh_autosuggest_capture_completion_widget
_zsh_autosuggest_capture_setup() {
# There is a bug in zpty module in older zsh versions by which a
# zpty that exits will kill all zpty processes that were forked
# before it. Here we set up a zsh exit hook to SIGKILL the zpty
# process immediately, before it has a chance to kill any other
# zpty processes.
if ! is-at-least 5.4; then
zshexit() {
# The zsh builtin `kill` fails sometimes in older versions
# https://unix.stackexchange.com/a/477647/156673
kill -KILL $$ 2>&- || command kill -KILL $$
# Block for long enough for the signal to come through
sleep 1
}
fi
# Try to avoid any suggestions that wouldn't match the prefix
zstyle ':completion:*' matcher-list ''
zstyle ':completion:*' path-completion false
zstyle ':completion:*' max-errors 0 not-numeric
bindkey '^I' autosuggest-capture-completion
}
_zsh_autosuggest_capture_completion_sync() {
_zsh_autosuggest_capture_setup
zle autosuggest-capture-completion
}
_zsh_autosuggest_capture_completion_async() {
_zsh_autosuggest_capture_setup
zmodload zsh/parameter 2>/dev/null || return # For `$functions`
# Make vared completion work as if for a normal command line
# https://stackoverflow.com/a/7057118/154703
autoload +X _complete
functions[_original_complete]=$functions[_complete]
function _complete() {
unset 'compstate[vared]'
_original_complete "$@"
}
# Open zle with buffer set so we can capture completions for it
vared 1
}
_zsh_autosuggest_strategy_completion() {
# Reset options to defaults and enable LOCAL_OPTIONS
emulate -L zsh
# Enable extended glob for completion ignore pattern
setopt EXTENDED_GLOB
typeset -g suggestion
local line REPLY
# Exit if we don't have completions
whence compdef >/dev/null || return
# Exit if we don't have zpty
zmodload zsh/zpty 2>/dev/null || return
# Exit if our search string matches the ignore pattern
[[ -n "$ZSH_AUTOSUGGEST_COMPLETION_IGNORE" ]] && [[ "$1" == $~ZSH_AUTOSUGGEST_COMPLETION_IGNORE ]] && return
# Zle will be inactive if we are in async mode
if zle; then
zpty $ZSH_AUTOSUGGEST_COMPLETIONS_PTY_NAME _zsh_autosuggest_capture_completion_sync
else
zpty $ZSH_AUTOSUGGEST_COMPLETIONS_PTY_NAME _zsh_autosuggest_capture_completion_async "\$1"
zpty -w $ZSH_AUTOSUGGEST_COMPLETIONS_PTY_NAME $'\t'
fi
{
# The completion result is surrounded by null bytes, so read the
# content between the first two null bytes.
zpty -r $ZSH_AUTOSUGGEST_COMPLETIONS_PTY_NAME line '*'$'\0''*'$'\0'
# Extract the suggestion from between the null bytes. On older
# versions of zsh (older than 5.3), we sometimes get extra bytes after
# the second null byte, so trim those off the end.
# See http://www.zsh.org/mla/workers/2015/msg03290.html
suggestion="${${(@0)line}[2]}"
} always {
# Destroy the pty
zpty -d $ZSH_AUTOSUGGEST_COMPLETIONS_PTY_NAME
}
}
#--------------------------------------------------------------------#
# History Suggestion Strategy #
#--------------------------------------------------------------------#
# Suggests the most recent history item that matches the given
# prefix.
#
_zsh_autosuggest_strategy_history() {
# Reset options to defaults and enable LOCAL_OPTIONS
emulate -L zsh
# Enable globbing flags so that we can use (#m) and (x~y) glob operator
setopt EXTENDED_GLOB
# Escape backslashes and all of the glob operators so we can use
# this string as a pattern to search the $history associative array.
# - (#m) globbing flag enables setting references for match data
# TODO: Use (b) flag when we can drop support for zsh older than v5.0.8
local prefix="${1//(#m)[\\*?[\]<>()|^~#]/\\$MATCH}"
# Get the history items that match the prefix, excluding those that match
# the ignore pattern
local pattern="$prefix*"
if [[ -n $ZSH_AUTOSUGGEST_HISTORY_IGNORE ]]; then
pattern="($pattern)~($ZSH_AUTOSUGGEST_HISTORY_IGNORE)"
fi
# Give the first history item matching the pattern as the suggestion
# - (r) subscript flag makes the pattern match on values
typeset -g suggestion="${history[(r)$pattern]}"
}
#--------------------------------------------------------------------#
# Match Previous Command Suggestion Strategy #
#--------------------------------------------------------------------#
# Suggests the most recent history item that matches the given
# prefix and whose preceding history item also matches the most
# recently executed command.
#
# For example, suppose your history has the following entries:
# - pwd
# - ls foo
# - ls bar
# - pwd
#
# Given the history list above, when you type 'ls', the suggestion
# will be 'ls foo' rather than 'ls bar' because your most recently
# executed command (pwd) was previously followed by 'ls foo'.
#
# Note that this strategy won't work as expected with ZSH options that don't
# preserve the history order such as `HIST_IGNORE_ALL_DUPS` or
# `HIST_EXPIRE_DUPS_FIRST`.
_zsh_autosuggest_strategy_match_prev_cmd() {
# Reset options to defaults and enable LOCAL_OPTIONS
emulate -L zsh
# Enable globbing flags so that we can use (#m) and (x~y) glob operator
setopt EXTENDED_GLOB
# TODO: Use (b) flag when we can drop support for zsh older than v5.0.8
local prefix="${1//(#m)[\\*?[\]<>()|^~#]/\\$MATCH}"
# Get the history items that match the prefix, excluding those that match
# the ignore pattern
local pattern="$prefix*"
if [[ -n $ZSH_AUTOSUGGEST_HISTORY_IGNORE ]]; then
pattern="($pattern)~($ZSH_AUTOSUGGEST_HISTORY_IGNORE)"
fi
# Get all history event numbers that correspond to history
# entries that match the pattern
local history_match_keys
history_match_keys=(${(k)history[(R)$~pattern]})
# By default we use the first history number (most recent history entry)
local histkey="${history_match_keys[1]}"
# Get the previously executed command
local prev_cmd="$(_zsh_autosuggest_escape_command "${history[$((HISTCMD-1))]}")"
# Iterate up to the first 200 history event numbers that match $prefix
for key in "${(@)history_match_keys[1,200]}"; do
# Stop if we ran out of history
[[ $key -gt 1 ]] || break
# See if the history entry preceding the suggestion matches the
# previous command, and use it if it does
if [[ "${history[$((key - 1))]}" == "$prev_cmd" ]]; then
histkey="$key"
break
fi
done
# Give back the matched history entry
typeset -g suggestion="$history[$histkey]"
}
#--------------------------------------------------------------------#
# Fetch Suggestion #
#--------------------------------------------------------------------#
# Loops through all specified strategies and returns a suggestion
# from the first strategy to provide one.
#
_zsh_autosuggest_fetch_suggestion() {
typeset -g suggestion
local -a strategies
local strategy
# Ensure we are working with an array
strategies=(${=ZSH_AUTOSUGGEST_STRATEGY})
for strategy in $strategies; do
# Try to get a suggestion from this strategy
_zsh_autosuggest_strategy_$strategy "$1"
# Ensure the suggestion matches the prefix
[[ "$suggestion" != "$1"* ]] && unset suggestion
# Break once we've found a valid suggestion
[[ -n "$suggestion" ]] && break
done
}
#--------------------------------------------------------------------#
# Async #
#--------------------------------------------------------------------#
_zsh_autosuggest_async_request() {
zmodload zsh/system 2>/dev/null # For `$sysparams`
typeset -g _ZSH_AUTOSUGGEST_ASYNC_FD _ZSH_AUTOSUGGEST_CHILD_PID
# If we've got a pending request, cancel it
if [[ -n "$_ZSH_AUTOSUGGEST_ASYNC_FD" ]] && { true <&$_ZSH_AUTOSUGGEST_ASYNC_FD } 2>/dev/null; then
# Close the file descriptor and remove the handler
exec {_ZSH_AUTOSUGGEST_ASYNC_FD}<&-
zle -F $_ZSH_AUTOSUGGEST_ASYNC_FD
# We won't know the pid unless the user has zsh/system module installed
if [[ -n "$_ZSH_AUTOSUGGEST_CHILD_PID" ]]; then
# Zsh will make a new process group for the child process only if job
# control is enabled (MONITOR option)
if [[ -o MONITOR ]]; then
# Send the signal to the process group to kill any processes that may
# have been forked by the suggestion strategy
kill -TERM -$_ZSH_AUTOSUGGEST_CHILD_PID 2>/dev/null
else
# Kill just the child process since it wasn't placed in a new process
# group. If the suggestion strategy forked any child processes they may
# be orphaned and left behind.
kill -TERM $_ZSH_AUTOSUGGEST_CHILD_PID 2>/dev/null
fi
fi
fi
# Fork a process to fetch a suggestion and open a pipe to read from it
exec {_ZSH_AUTOSUGGEST_ASYNC_FD}< <(
# Tell parent process our pid
echo $sysparams[pid]
# Fetch and print the suggestion
local suggestion
_zsh_autosuggest_fetch_suggestion "$1"
echo -nE "$suggestion"
)
# There's a weird bug here where ^C stops working unless we force a fork
# See https://github.com/zsh-users/zsh-autosuggestions/issues/364
autoload -Uz is-at-least
is-at-least 5.8 || command true
# Read the pid from the child process
read _ZSH_AUTOSUGGEST_CHILD_PID <&$_ZSH_AUTOSUGGEST_ASYNC_FD
# When the fd is readable, call the response handler
zle -F "$_ZSH_AUTOSUGGEST_ASYNC_FD" _zsh_autosuggest_async_response
}
# Called when new data is ready to be read from the pipe
# First arg will be fd ready for reading
# Second arg will be passed in case of error
_zsh_autosuggest_async_response() {
emulate -L zsh
local suggestion
if [[ -z "$2" || "$2" == "hup" ]]; then
# Read everything from the fd and give it as a suggestion
IFS='' read -rd '' -u $1 suggestion
zle autosuggest-suggest -- "$suggestion"
# Close the fd
exec {1}<&-
fi
# Always remove the handler
zle -F "$1"
}
#--------------------------------------------------------------------#
# Start #
#--------------------------------------------------------------------#
# Start the autosuggestion widgets
_zsh_autosuggest_start() {
# By default we re-bind widgets on every precmd to ensure we wrap other
# wrappers. Specifically, highlighting breaks if our widgets are wrapped by
# zsh-syntax-highlighting widgets. This also allows modifications to the
# widget list variables to take effect on the next precmd. However this has
# a decent performance hit, so users can set ZSH_AUTOSUGGEST_MANUAL_REBIND
# to disable the automatic re-binding.
if (( ${+ZSH_AUTOSUGGEST_MANUAL_REBIND} )); then
add-zsh-hook -d precmd _zsh_autosuggest_start
fi
_zsh_autosuggest_bind_widgets
}
# Mark for auto-loading the functions that we use
autoload -Uz add-zsh-hook is-at-least
# Automatically enable asynchronous mode in newer versions of zsh. Disable for
# older versions because there is a bug when using async mode where ^C does not
# work immediately after fetching a suggestion.
# See https://github.com/zsh-users/zsh-autosuggestions/issues/364
if is-at-least 5.0.8; then
typeset -g ZSH_AUTOSUGGEST_USE_ASYNC=
fi
# Start the autosuggestion widgets on the next precmd
add-zsh-hook precmd _zsh_autosuggest_start

View file

@ -1,15 +0,0 @@
# Top-most editorconfig file
root = true
[*]
end_of_line = lf
tab_width = 2
indent_size = 2
indent_style = space
[Makefile]
tab_width = 8
indent_size = 8
indent_style = tab

Some files were not shown because too many files have changed in this diff Show more