2019-09-08 12:47:38 +00:00
|
|
|
#!/usr/bin/env zsh
|
|
|
|
|
2019-09-24 19:34:15 +00:00
|
|
|
# http://zsh.sourceforge.net/Doc/Release/Zsh-Line-Editor.html
|
|
|
|
# http://zsh.sourceforge.net/Doc/Release/Zsh-Line-Editor.html#Zle-Builtins
|
|
|
|
# http://zsh.sourceforge.net/Doc/Release/Zsh-Line-Editor.html#Standard-Widgets
|
|
|
|
|
2019-09-08 13:01:19 +00:00
|
|
|
# _fzf_history_widget {{{
|
2019-09-08 12:47:38 +00:00
|
|
|
# taken from https://github.com/junegunn/fzf/blob/master/shell/key-bindings.zsh
|
2019-09-08 13:01:19 +00:00
|
|
|
_fzf_history_widget() {
|
2019-09-24 19:34:15 +00:00
|
|
|
setopt local_options pipe_fail
|
2019-09-08 12:47:38 +00:00
|
|
|
local selected
|
|
|
|
selected=(
|
|
|
|
$(fc -rl 1 |
|
|
|
|
fzf --height=40% --reverse --nth=2.. --tiebreak=index --query="$LBUFFER")
|
|
|
|
)
|
|
|
|
local fzf_ret="$?"
|
|
|
|
if (( ${#selected} )); then
|
|
|
|
zle vi-fetch-history -n "${selected[1]}"
|
|
|
|
fi
|
|
|
|
zle reset-prompt
|
|
|
|
return "$fzf_ret"
|
|
|
|
}
|
|
|
|
|
2019-09-08 13:01:19 +00:00
|
|
|
zle -N _fzf_history_widget
|
2020-05-13 21:49:39 +00:00
|
|
|
bindkey '\er' _fzf_history_widget
|
2019-09-08 13:01:19 +00:00
|
|
|
# }}}
|
|
|
|
|
|
|
|
# palette {{{
|
|
|
|
# This widget lets you select a command snippet and fill in its placeholders.
|
|
|
|
# It uses "TLDR pages" as the snippet database, so the widget will download
|
|
|
|
# them on the first invocation. Or, you can also create a symlink to a local
|
|
|
|
# cache of a "TLDR pages" client, e.g. for tealdeer (which is what I use):
|
|
|
|
#
|
|
|
|
# ln -sv ~/.cache/tealdeer/tldr-master/pages $ZSH_CACHE_DIR/tldr-pages
|
|
|
|
#
|
|
|
|
# Usage:
|
|
|
|
# 1. press Alt+Shift+P (or Esc+Shift+P)
|
|
|
|
# 2. select snippet in the fuzzy finder (fzf)
|
|
|
|
# 3. Press Alt+Shift+P again, this time it'll take you to the first placeholder
|
|
|
|
# 4. Enter some text
|
|
|
|
# 5. Repeat steps 3 and 4 until there're no placeholders left
|
|
|
|
#
|
|
|
|
# Requirements/Dependencies:
|
|
|
|
# 1. AWK (any implementation will probably work) for parsing "TLDR pages"
|
|
|
|
# 2. the FZF fuzzy finder
|
|
|
|
# 3. Tar (any implementation will probably work) and Curl for downloading
|
|
|
|
# "TLDR pages"
|
|
|
|
|
|
|
|
PALETTE_TLDR_PAGES_DIR="$ZSH_CACHE_DIR/tldr-pages"
|
|
|
|
|
|
|
|
# strings which are used to mark placeholders (please don't modify)
|
|
|
|
PALETTE_PLACEHOLDER_START="{{"
|
|
|
|
PALETTE_PLACEHOLDER_END="}}"
|
|
|
|
|
|
|
|
# a string which is used to separate snippet from its description in the
|
|
|
|
# fuzzy-finder
|
|
|
|
PALETTE_SNIPPET_COMMENT=" ## "
|
|
|
|
|
|
|
|
# Main function of the widget
|
|
|
|
_palette_widget() {
|
|
|
|
# download "TLDR pages" if we don't have them
|
|
|
|
if [[ ! -d "$PALETTE_TLDR_PAGES_DIR" ]]; then
|
2021-03-30 12:15:33 +00:00
|
|
|
print -r
|
2019-09-08 13:01:19 +00:00
|
|
|
_palette_download_tldr_pages
|
2021-03-30 12:15:33 +00:00
|
|
|
print -r
|
2019-09-08 13:01:19 +00:00
|
|
|
fi
|
|
|
|
|
|
|
|
# try to fill in a placeholder if there're any, otherwise pick a snippet
|
|
|
|
if ! _palette_fill_in_placeholder; then
|
|
|
|
local selected
|
|
|
|
if selected="$(_palette_parse_tldr_pages | fzf --height 40% --reverse --ansi)"
|
|
|
|
then
|
|
|
|
# paste selected snippet without its description
|
|
|
|
zle -U "${selected%%$PALETTE_SNIPPET_COMMENT*}"
|
|
|
|
fi
|
|
|
|
fi
|
|
|
|
|
|
|
|
# immediately redraw
|
|
|
|
zle redisplay
|
|
|
|
}
|
|
|
|
|
|
|
|
# This function deletes the first placeholder from the buffer and places the
|
|
|
|
# cursor at the beginning of that placeholder. If there're no placeholders in
|
|
|
|
# the buffer, it exits with exit code 1.
|
|
|
|
_palette_fill_in_placeholder() {
|
|
|
|
# NOTE!!! indexes in ZSH arrays start at one!
|
|
|
|
local start_index="${BUFFER[(i)$PALETTE_PLACEHOLDER_START]}"
|
|
|
|
(( start_index == 0 || start_index > ${#BUFFER} )) && return 1
|
|
|
|
local end_index="${BUFFER[(i)$PALETTE_PLACEHOLDER_END]}"
|
|
|
|
# the CURSOR variable is zero-based while ZSH arrays are one-based
|
|
|
|
(( CURSOR = start_index - 1 ))
|
|
|
|
BUFFER="${BUFFER[1,start_index-1]}${BUFFER[end_index+2,${#BUFFER}]}"
|
|
|
|
}
|
|
|
|
|
|
|
|
# This function parses "TLDR pages" for snippets using AWK. Fortunately, all
|
|
|
|
# "TLDR pages" files are use the same Markdown-like syntax so they're very easy
|
|
|
|
# to parse.
|
|
|
|
_palette_parse_tldr_pages() {
|
|
|
|
# I chose to use AWK here because it was designed specifically for text
|
|
|
|
# processing and includes all basic utilities that I need here.
|
|
|
|
awk '
|
|
|
|
# when we find a "description" line...
|
|
|
|
match($0, /^- (.+):$/, match_groups) {
|
|
|
|
# ...get actual description from it...
|
|
|
|
description = match_groups[1]
|
|
|
|
# ...then skip any lines that are not actual commands, while saving RegEx
|
|
|
|
# match groups...
|
|
|
|
while (!match($0, /^`(.+)`$/, match_groups)) getline
|
|
|
|
# ...after that we can get the command...
|
|
|
|
command = match_groups[1]
|
|
|
|
# ...and finally, we print command and description, separated by
|
|
|
|
# PALETTE_SNIPPET_COMMENT, and with some colors!
|
|
|
|
printf "%s\x1b[90m'"$PALETTE_SNIPPET_COMMENT"'%s\x1b[0m\n", command, description
|
|
|
|
}
|
|
|
|
' "$PALETTE_TLDR_PAGES_DIR"/**/*.md
|
|
|
|
}
|
|
|
|
|
|
|
|
# This function downloads the "TLDR pages"
|
|
|
|
_palette_download_tldr_pages() {
|
|
|
|
mkdir -pv "$PALETTE_TLDR_PAGES_DIR"
|
2021-03-30 12:15:33 +00:00
|
|
|
print -r -- "Downloading tldr pages..."
|
2019-09-08 13:01:19 +00:00
|
|
|
|
|
|
|
if curl -Lf https://github.com/tldr-pages/tldr/archive/master.tar.gz |
|
|
|
|
tar -C "$PALETTE_TLDR_PAGES_DIR" --gzip --strip-components 2 --extract tldr-master/pages
|
|
|
|
then
|
2021-03-30 12:15:33 +00:00
|
|
|
print -r -- "Done!"
|
2019-09-08 13:01:19 +00:00
|
|
|
fi
|
|
|
|
}
|
|
|
|
|
|
|
|
# finally, bind the widget to Alt+Shift+P (or Esc+Shift+P)
|
|
|
|
zle -N _palette_widget
|
2020-05-13 21:49:39 +00:00
|
|
|
bindkey '\eP' _palette_widget
|
2019-09-08 13:01:19 +00:00
|
|
|
# }}}
|
2019-09-24 19:34:15 +00:00
|
|
|
|
2020-05-13 21:49:39 +00:00
|
|
|
# expand-or-complete-with-dots {{{
|
|
|
|
# expand-or-complete-with-dots() {
|
|
|
|
# local wrap_ctrl_supported
|
|
|
|
# if (( ${+terminfo[rmam]} && ${+terminfo[smam]} )); then
|
|
|
|
# wrap_ctrl_supported=1
|
|
|
|
# fi
|
|
|
|
# # toggle line-wrapping off and back on again
|
|
|
|
# if [[ -n "$wrap_ctrl_supported" ]]; then echoti rmam; fi
|
|
|
|
# print -Pn "%F{red}...%f"
|
|
|
|
# if [[ -n "$wrap_ctrl_supported" ]]; then echoti smam; fi
|
|
|
|
# zle expand-or-complete
|
|
|
|
# zle redisplay
|
|
|
|
# }
|
|
|
|
# zle -N expand-or-complete-with-dots
|
|
|
|
# bindkey "^I" expand-or-complete-with-dots
|
|
|
|
# }}}
|
|
|
|
|
|
|
|
# find man page widget {{{
|
|
|
|
_widget_find_man_page() {
|
|
|
|
local words=("${(@z)BUFFER}")
|
|
|
|
local cmd_name="${words[1]}"
|
|
|
|
zle push-line
|
2020-09-14 14:45:20 +00:00
|
|
|
local manpage=""
|
|
|
|
manpage="$(fzf-search-manpage "$cmd_name")"
|
|
|
|
BUFFER="man $manpage"
|
2020-05-13 21:49:39 +00:00
|
|
|
zle accept-line
|
|
|
|
}
|
|
|
|
zle -N find-man-page _widget_find_man_page
|
|
|
|
# bind to F1
|
|
|
|
bindkey '\eOP' find-man-page
|
|
|
|
# }}}
|
2020-08-28 12:12:29 +00:00
|
|
|
|
|
|
|
# other keybindings {{{
|
|
|
|
|
|
|
|
bindkey '\ee' edit-command-line
|
|
|
|
|
|
|
|
# }}}
|