1#!/bin/zsh -fi 2# A zsh sticky-note ("post-it") application. Load this file as a function: 3# autoload -Uz sticky-note 4# 5# It may then be bound as a widget: 6# zle -N sticky-note 7# And/or run as a command: 8# sticky-note 9# sticky-note -b 10# sticky-note -l ... 11# The -b option is like "zed -b": it installs keymaps/bindings only. 12# Use the -l option to list previous sticky notes. Most options of the 13# "fc -l" command are supported, for selecting which notes to display. 14# If "sticky-note -l" is run from inside a widget, the cursor is moved 15# to the top left of the terminal before display and returned to its 16# original position after display. The -l option is implicitly added 17# when sticky-note is called from zle-line-init, to avoid inadvertently 18# trapping the user inside the note editor. 19# 20# Otherwise, invoke the line editor with the previous notes available 21# as an editor history. Two quick taps on the return/enter key finish 22# the note, or you can use ^X^W as usual (ZZ in vicmd mode). 23 24# The application is configured by three zstyles, all using the context 25# ":sticky-note". The first two styles are "notefile" and "maxnotes" 26# to name the file in which notes are stored and the maximum number of 27# notes to retain: 28# zstyle :sticky-note notefile ~/.zsticky 29# zstyle :sticky-note maxnotes 1000 30 31# The "theme" style may be set to control the appearance of the notes. 32# The style is an associative array; the current set of values (defaults 33# in parens) are: 34# bg => name or ANSI escape for background color (yellow) 35# fg => name or ANSI escape for foreground color (black) 36# color => ANSI escape for color scheme ($theme[bg]$theme[fg]) 37# reset => ANSI escape to restore "normal" colors 38# Values given as names are looked up in the $bg and $fg arrays from the 39# "colors" function. If a "color" field is set, the "bg" and "fg" fields 40# are not used. Example: 41# zstyle :sticky-note theme \ 42# bg red \ 43# fg $fg_bold[yellow] 44 45# For backwards compatibility with an earlier version, the notefile may 46# also be named by the STICKYFILE variable (defaults to $HOME/.zsticky). 47# The number of notes stored may be given by STICKYSIZE (1000). 48 49# I encourage all you creative people to contribute enhancements ... 50 51emulate -LR zsh 52setopt nobanghist extendedhistory histignoredups 53 54local STICKYFILE=${STICKYFILE:-$HOME/.zsticky} 55local STICKYSIZE=${STICKYSIZE:-1000} 56local sticky stickyfile stickysize 57 58zstyle -s :sticky-note notefile stickyfile || stickyfile=$STICKYFILE 59zstyle -s :sticky-note maxnotes stickysize || stickysize=$STICKYSIZE 60 61# Set up keybindings (adapted from "zed") 62if ! bindkey -M sticky >& /dev/null 63then 64 bindkey -N sticky main 65 bindkey -M sticky ^X^W accept-line 66 bindkey -M sticky ^M^M accept-line # Two quick RETs ends note 67 bindkey -M sticky ^M self-insert-unmeta 68fi 69if ! bindkey -M sticky-vicmd >& /dev/null 70then 71 bindkey -N sticky-vicmd vicmd 72 bindkey -M sticky-vicmd ZZ accept-line 73fi 74 75[[ "$1" == -b ]] && return 0 76 77# Look up color theme 78local -A theme 79(($+bg && $+fg)) || { autoload -Uz colors; colors } 80zstyle -m :sticky-note theme '*' || { 81 zstyle :sticky-note theme bg yellow fg black 82} 83zstyle -a :sticky-note theme theme 84(( ${+bg[$theme[bg]]} )) && theme[bg]=$bg[$theme[bg]] 85(( ${+fg[$theme[fg]]} )) && theme[fg]=$fg[$theme[fg]] 86(( ${+theme[color]} )) || theme[color]=$theme[bg]$theme[fg] 87(( ${+theme[reset]} )) || theme[reset]=$reset_color 88 89# If invoked as a widget, behave a bit like run-help 90if zle 91then 92 zmodload -i zsh/parameter 93 if [[ $* == -*l* || $functrace == *zle-line-init:* ]] 94 then 95 fc -ap $stickyfile $stickysize $stickysize 96 echoti sc 97 echoti home 98 print -nr "$theme[color]" 99 fc -l "${@:--1}" | while read -r sticky; do print -- "$sticky"; done 100 print -nr "$theme[reset]" 101 echoti rc 102 elif [[ $CONTEXT = (cont|select|vared) ]] 103 then 104 zle -M "No stickies during ${${(z)PREBUFFER}[1]:-$CONTEXT}, sorry" 105 zle .beep 106 zle -R 107 else 108 zle .push-line 109 BUFFER=sticky-note 110 zle .accept-line 111 fi 112 return 0 113fi 114 115# Invoked as a command, behave like zed, but write a history file 116fc -ap $stickyfile $stickysize $stickysize 117 118# With a -l option, list the existing sticky notes 119if [[ "$*" == -*l* ]] 120then 121 print -nr "$theme[color]" 122 # Use read/print loop to interpolate "\n" in history lines 123 fc -f "$@" | while read -r sticky; do print -- "$sticky"; done 124 print -nr "$theme[reset]" 125 return 0 126fi 127 128# Edit a new sticky note and add it to the stickyfile 129while vared -h -p "%{$theme[color]%}" -M sticky -m sticky-vicmd sticky 130do 131 { 132 [[ -n "$sticky" ]] && print -s -- "$sticky" 133 } always { 134 (( TRY_BLOCK_ERROR = 0 )) 135 } && break 136 echo -n -e '\a' 137done 138return 0 139