zsh-workers
 help / color / mirror / code / Atom feed
From: Bart Schaefer <schaefer@brasslantern.com>
To: vapnik spaknik <vapniks@yahoo.com>
Cc: Zsh Hackers List <zsh-workers@zsh.org>
Subject: Re: Suggested improvement for sticky-note
Date: Sun, 12 Nov 2023 13:10:14 -0800	[thread overview]
Message-ID: <CAH+w=7ZRvCU1Uog_38D=CH7xTGYy1Lnuq4ORR0Oz77psZZAmag@mail.gmail.com> (raw)
In-Reply-To: <CAH+w=7Z0wO_1AgHxhsRLDcActY=YCyp1+1r-w4mJxmKDGhZM9A@mail.gmail.com>

[-- Attachment #1: Type: text/plain, Size: 2478 bytes --]

Returning 2.5 years later ...

> On Mon, May 3, 2021 at 7:06 PM vapnik spaknik <vapniks@yahoo.com> wrote:
> >
> > adds options for selecting a background colour &/or blinking when creating a new sticky note, and automatically adds the appropriate escape codes.

The attached revision of sticky-note (which requires the current
development version of zsh for ${| code } and namespaces) implements
these in a more satisfactory way, by keeping a second file of assigned
display attributes alongside the history-formatted file that stores
the notes themselves.  The assignment of colors, blinking, etc. is now
activated by a key binding rather than a command line option, and is
customizable by a style.  I have not implemented "stacking" of styles
at this point, so if you want to change black-on-yellow to
blinking-white-on-red, you'll need a single display name for the
latter.

I'm sure there are undiscovered bugs with this, so mess around if interested.

On Sun, May 9, 2021 at 1:50 PM Bart Schaefer <schaefer@brasslantern.com> wrote:
>
> There are a few reasonable suggestions here mixed with quite a number
> of things that could be improved.  Adding noflowcontrol to the setopts
> is probably a good idea, and passing "-e" to vared should at least be
> configurable.

These are implemented in the attached version.  Several vared options
can now be controlled with
  zstyle :sticky-note vared-options ...

Read the large comment at the top of the file for a description of
what you can do, with some examples.  This should eventually go into
the contributions doc.

> That also caused me to notice that interrupting
> sticky-note with a keyboard interrupt (^C) can cause old notes to
> disappear, so that should be fixed.

I haven't tracked that down yet.  Also yet to be fixed is expiring
lines from the display file when the corresponding lines expire from
the history.

> Having the note blink while it is being edited is rather
> weird/distracting even if you want it to blink when displayed later.

The name of the current selected display style is displayed in the
PREDISPLAY string during editing.

As a final note, I found an error in the doc for "vared":

     ...  If the
     -e flag is given, typing ^D (Control-D) on an empty line causes
     vared to exit immediately with a non-zero return value.

This should say "in an empty note" not "empty line".  It only works if
the whole note would be blank.

[-- Attachment #2: sticky-note --]
[-- Type: application/octet-stream, Size: 10266 bytes --]

#!/bin/zsh -fi
# A zsh sticky-note ("post-it") application.  Load this file as a function:
#    autoload -Uz sticky-note
#
# It may then be bound as a widget:
#    zle -N sticky-note
# And/or run as a command:
#    sticky-note
#    sticky-note -b
#    sticky-note -l ...
# The -b option is like "zed -b": it installs keymaps/bindings only.
# Use the -l option to list previous sticky notes.  Most options of the
# "fc -l" command are supported, for selecting which notes to display.
# If "sticky-note -l" is run from inside a widget, the cursor is moved
# to the top left of the terminal before display and returned to its
# original position after display.  The -l option is implicitly added
# when sticky-note is called from zle-line-init, to avoid inadvertently
# trapping the user inside the note editor.
#
# Otherwise, invoke the line editor with the previous notes available
# as an editor history.  Two quick taps on the return/enter key finish
# the note, or you can use ^X^W as usual (ZZ in vicmd mode).

# The application is configured by several zstyles, all using the context
# ":sticky-note".  The complete list of styles is and their types is:
#   notefile       string (filename)
#   maxnotes       number
#   vared-options  array
#   theme          associative array
#   display        associative array
#   list-display   boolean (string true|yes|on|1 or not set for false)

# The first two styles are "notefile" and "maxnotes" to name the file in
# which notes are stored and the maximum number of notes to retain:
#   zstyle :sticky-note notefile ~/.zsticky
#   zstyle :sticky-note maxnotes 1000

# For backwards compatibility with an earlier version, the notefile may
# also be named by the STICKYFILE variable (defaults to $HOME/.zsticky).
# The number of notes stored may be given by STICKYSIZE (1000).

# The "vared-options" style lists options passed to vared when a note
# is edited. The vared options -A, -a, -c, -M, and -m are ignored.  The
# useful options are -i, -f, -e, -p, -r, and in unusual cases -t.  The
# options -p and -r should use the same syntax as the "prompt" value of
# the "theme" style, described below, and the -r option should.  As a
# special case, to make the note history unavailable when editing,
# include +h in the vared-options style.  Example:
#   zstyle :sticky-note vared-options +h -e -r %T

# The "theme" style may be set to control the appearance of the notes.
# The style is an associative array; the current set of values (defaults
# in parens) are:
#   bg     => name or ANSI escape for background color (yellow)
#   fg     => name or ANSI escape for foreground color (black)
#   color  => ANSI escape for color scheme ($theme[bg]$theme[fg])
#   reset  => ANSI escape to restore "normal" colors
#   prompt => Passed to vared.  May refer to %{${theme[bg]}%} et al.
# Values given as names are looked up in the $bg and $fg arrays from the
# "colors" function.  If a "color" field is set, the "bg" and "fg" fields
# are not used unless referenced in "prompt".  The prompt value should
# be single-quoted and must use appropriate %{...%} wrappers around
# zero-width outputs such as color changes.  Example:
#   zstyle :sticky-note theme \
#     bg red \
#     fg $fg_bold[yellow] \
#     prompt '%{$theme[bg]$fg_bold[white]%}POST-IT:%{$theme[reset]%}'
# NOTE:  You must define either color or both fg and bg, but the values
# $theme[color] and $theme[reset] are always generated if omitted.

# The "display" style is an associative array mapping custom display
# attribute names to the ANSI codes to enable them.  The style must use
# "%s" at the position where the note should appear, and must end with
# ANSI codes to discontinue the style.  An empty value turns off the
# display formatting.  For example:
#   zstyle :sticky-note display \
#     none "" \
#     blink "$(echoti blink)%s$(echoti sgr0)" \
#     reverse $'\e[07m%s\e[00m'
# If you use this style, a file named $STICKYFILE.display is created
# to preserve the display attributes of the notes in $STICKYFILE.
# NOTE: Changing the display zstyle does not change the display of
# previously created notes.  There is no default display style.

# To set the display for a note, type ctrl-x question-mark (^X?) to
# run the widget "_sticky-display".  When a "display" style is set, this
# replaces the _complete_help binding from the default keymap.  The
# keymap named "sticky" may be modified to customize this, after running
# "sticky-note -b" to initialize.

# By default the display style is only applied when "posting" notes to
# the top of the screen via the ZLE widget, but can be applied to the
# output of "sticky-note -l" by setting the "list-display" style:
#   zstyle :sticky-note list-display true

# I encourage all you creative people to contribute enhancements ...

emulate -LR zsh

# TODO: Clean this up as notes expire from the STICKYFILE.
typeset -gA .zsticky.display

# Set up keybindings (adapted from "zed")
if ! bindkey -M sticky >& /dev/null
then
  bindkey -N sticky main
  bindkey -M sticky ^X^W accept-line
  bindkey -M sticky ^M^M accept-line	# Two quick RETs ends note
  bindkey -M sticky ^M self-insert-unmeta
fi
if ! bindkey -M sticky-vicmd >& /dev/null 
then
  bindkey -N sticky-vicmd vicmd
  bindkey -M sticky-vicmd ZZ accept-line
fi
if ! functions _sticky-display >& /dev/null &&
     zstyle -m :sticky-note display '*'
then
  function _sticky-display {
    if [[ -z $compstate[vared] ]]
    then
      local save_buffer=$BUFFER save_cursor=$CURSOR
      BUFFER=
      zle -U $'\t'
      zle recursive-edit -K sticky-display
      .zsticky.display[last]=$BUFFER
      PREDISPLAY="[ $BUFFER ] "
      BUFFER=$save_buffer CURSOR=$save_cursor
      zle reset-prompt
    else
      zstyle -a :sticky-note display sticky_displays
      compadd -x "Press TAB to choose display mode, ENTER to set:" \
	      -V nosort ${.zsticky.display[last]} \
	      ${${(ok)sticky_displays}:#${.zsticky.display[last]}}
      compstate[insert]=menu
    fi
  }
  zle -N _sticky-display
  bindkey -M sticky '^X?' _sticky-display
  zle -C sticky-display-choices menu-complete _sticky-display
  bindkey -N sticky-display
  bindkey -M sticky-display $'\t' sticky-display-choices
  bindkey -M sticky-display ^M accept-line
fi

[[ "$1" == -b ]] && return 0

setopt noflowcontrol nobanghist extendedhistory histignoredups
zmodload -i zsh/datetime

local STICKYFILE=${STICKYFILE:-$HOME/.zsticky}
local STICKYSIZE=${STICKYSIZE:-1000}
local PREDISPLAY sticky stickyfile stickysize
local -A sticky_displays vared_options

zstyle -s :sticky-note notefile stickyfile || stickyfile=$STICKYFILE
zstyle -s :sticky-note maxnotes stickysize || stickysize=$STICKYSIZE

# Populate options to vared
local -a v0
if zstyle -a :sticky-note vared-options v0
then
  v0[${v0[(i)-a]}]=()
  v0[${v0[(i)-A]}]=()
  v0[${v0[(i)-c]}]=()
  if (( ${v0[(I)+h]} ))
  then
    v0[${v0[(i)-h]}]=()
    v0[${v0[(i)+h]}]=()
  else
    v0+=(-h '')
  fi
  if (( ${v0[(I)-g]} ))
  then
    v0[${v0[(i)-g]}]=(-g '')
  fi
  if (( ${v0[(I)-e]} ))
  then
    v0[${v0[(i)-e]}]=(-e '')
  fi
  vared_options=( "$v0[@]" )
else
  vared_options=(-h '')
fi
: ${vared_options[-i]:=undefined-key}
: ${vared_options[-f]:=undefined-key}
: ${vared_options[-M]::=sticky}
: ${vared_options[-m]::=sticky-vicmd}

# Look up color theme
local -A theme
(($+bg && $+fg)) || { autoload -Uz colors; colors }
zstyle -m :sticky-note theme '*' || {
    zstyle :sticky-note theme bg yellow fg black
}
zstyle -a :sticky-note theme theme
(( ${+bg[$theme[bg]]} )) && theme[bg]=$bg[$theme[bg]]
(( ${+fg[$theme[fg]]} )) && theme[fg]=$fg[$theme[fg]]
(( ${+theme[color]} )) || theme[color]=$theme[bg]$theme[fg]
(( ${+theme[reset]} )) || theme[reset]=$reset_color
(( ${+theme[prompt]} )) || theme[prompt]=$vared_options[-p]

theme[prompt]="${(e)theme[prompt]}%{${theme[color]}%}"
vared_options[-p]=$theme[prompt]

# Load per-note display settings
if [[ -z ${.zsticky.display} && -r $stickyfile.display ]]
then
  source $stickyfile.display
fi

# If invoked as a widget, behave a bit like run-help
if zle
then
  zmodload -i zsh/parameter
  if [[ $* == -*l* || $functrace == *zle-line-init:* ]]
  then
    local num stamp ceol=${ echoti el }
    fc -ap $stickyfile $stickysize $stickysize
    echoti cup $LINES 1
    zle reset-prompt
    echoti sc
    echoti home
    print -nr "$theme[color]"
    fc -t %s -l "${@:--1}" |
      while read -r num stamp sticky
      do
	if [[ -n ${.zsticky.display[$stamp]} ]]
	then
	  printf -v sticky "${.zsticky.display[$stamp]}$theme[color]" $sticky
	fi
	printf %s\\n "$num  "${sticky//$'\\n'/$ceol$'\n'}$ceol
      done
    print -nr "$theme[reset]"
    echoti rc
  elif [[ $CONTEXT = (cont|select|vared) ]]
  then
    zle -M "No stickies during ${${(z)PREBUFFER}[1]:-$CONTEXT}, sorry"
    zle .beep
    zle -R
  else
    zle .push-line
    BUFFER=sticky-note
    zle .accept-line
  fi
  return 0
fi

# Invoked as a command, behave like zed, but write a history file
fc -ap $stickyfile $stickysize $stickysize

# With a -l option, list the existing sticky notes
if [[ "$*" == -*l* ]]
then
  local num stamp display
  print -nr "$theme[color]"
  # Use read/print loop to interpolate "\n" in history lines
  fc -t %s "$@" |
    while read -r num stamp sticky
    do
      if zstyle -t :sticky-note list-display &&
	  [[ -n ${.zsticky.display[$stamp]} ]]
      then
	printf -v sticky "${.zsticky.display[$stamp]}$theme[color]" $sticky
      fi
      print -- "${| strftime -s REPLY -n '%x %H:%M' $stamp }  $sticky"
    done
  print -nr "$theme[reset]"
  return 0
fi

# Edit a new sticky note and add it to the stickyfile
while vared ${(kv)vared_options} sticky
do
  {
    if [[ -n "$sticky" ]]
    then
      print -s -- "$sticky"
      fc -W && SAVEHIST=0
      # File is updated but internal "fc -l" is not yet.  Get the timestamp.
      stamp=${${${| local line;
		  while read line; do REPLY=$line; done <$stickyfile }#: }%%:*}
      if [[ -n $stamp && -n ${.zsticky.display[last]} && -n $sticky_displays ]]
      then
	.zsticky.display[$stamp]=${sticky_displays[${.zsticky.display[last]}]}
        typeset -p .zsticky.display >| $stickyfile.display
      fi
    fi
  } always {
    unset sticky_displays
    (( TRY_BLOCK_ERROR = 0 ))
  } && break
  echo -n -e '\a'
done
return 0

  parent reply	other threads:[~2023-11-12 21:11 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <1185563186.165566.1619896723304.ref@mail.yahoo.com>
2021-05-01 19:18 ` vapnik spaknik
2021-05-02 23:57   ` Bart Schaefer
2021-05-04  2:06     ` vapnik spaknik
2021-05-09 20:50       ` Bart Schaefer
2021-05-11 10:18         ` Mikael Magnusson
2021-05-14 23:40           ` Termcap and boldface (was sticky-note) Bart Schaefer
2021-05-11 12:37         ` Suggested improvement for sticky-note vapnik spaknik
2023-11-12 21:10         ` Bart Schaefer [this message]
2023-11-19  5:25           ` Bart Schaefer

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CAH+w=7ZRvCU1Uog_38D=CH7xTGYy1Lnuq4ORR0Oz77psZZAmag@mail.gmail.com' \
    --to=schaefer@brasslantern.com \
    --cc=vapniks@yahoo.com \
    --cc=zsh-workers@zsh.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).