summary refs log tree commit diff
diff options
context:
space:
mode:
authorPeter Stephenson <pws@users.sourceforge.net>2002-07-05 10:49:46 +0000
committerPeter Stephenson <pws@users.sourceforge.net>2002-07-05 10:49:46 +0000
commit363079af7600095d2accf6d2d6eebe68a97b0d81 (patch)
tree496962f30da40f5dfcfb33e1801f45d21d8c3ad3
parent135db923be1336fc8d83b94678097c8c963cce0a (diff)
downloadzsh-363079af7600095d2accf6d2d6eebe68a97b0d81.tar.gz
zsh-363079af7600095d2accf6d2d6eebe68a97b0d81.tar.xz
zsh-363079af7600095d2accf6d2d6eebe68a97b0d81.zip
17414: narrow-to-region save and restore.
-rw-r--r--ChangeLog6
-rw-r--r--Doc/Zsh/contrib.yo31
-rw-r--r--Functions/Zle/narrow-to-region135
3 files changed, 122 insertions, 50 deletions
diff --git a/ChangeLog b/ChangeLog
index b9b7f9a94..85364d06d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2002-07-05  Peter Stephenson  <pws@csr.com>
+
+	* 17414: Doc/Zsh/contrib.yo, Functions/Zle/narrow-to-region:
+	allow narrow-to-region to save and restore state, a bit
+	like save-restriction in emacs only completely different.
+
 2002-07-05  Sven Wischnowsky  <wischnow@zsh.org>
 
 	* 17429: Src/Zle/complist.c: improve interactive mode when
diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo
index 58a943e1a..a6e2c8811 100644
--- a/Doc/Zsh/contrib.yo
+++ b/Doc/Zsh/contrib.yo
@@ -477,15 +477,17 @@ example(bindkey '^Xf' insert-files)
 )
 tindex(narrow-to-region)
 tindex(narrow-to-region-invisible)
-xitem(tt(narrow-to-region [ -p) var(pre) tt(] [ -P) var(post) tt(] [ -n ] [) var(start) var(end) tt(]))
+xitem(tt(narrow-to-region [ -p) var(pre) tt(] [ -P) var(post) tt(]))
+xitem(    tt([ -S) var(statepm) tt(| -R) var(statepm) tt(] [ -n ] [) var(start) var(end) tt(])))
 item(tt(narrow-to-region-invisible))(
 Narrow the editable portion of the buffer to the region between the cursor
 and the mark, which may be in either order.  The region may not be empty.
 
 tt(narrow-to-region) may be used as a widget or called as a function from a
 user-defined widget; by default, the text outside the editable area remains
-visible.  Various options and arguments are available when it is called as
-a function.
+visible.  A tt(recursive-edit) is performed and the original widening
+status is then restored.  Various options and arguments are available when
+it is called as a function.
 
 The options tt(-p) var(pretext) and tt(-P) var(posttext) may be
 used to replace the text before and after the display for the duration of
@@ -498,16 +500,37 @@ will be made invisible.
 Two numeric arguments may be given which will be used instead of the cursor
 and mark positions.
 
+The option tt(-S) var(statepm) is used to narrow according to the other
+options while saving the original state in the parameter with name
+var(statepm), while the option tt(-R) var(statepm) is used to restore the
+state from the parameter; note in both cases the em(name) of the parameter
+is required.  In the second case, other options and arguments are
+irrelevant.  When this method is used, no tt(recursive-edit) is performed;
+the calling widget should call this function with the option tt(-S),
+perform its own editing on the command line or pass control to the user
+via `tt(zle recursive-edit)', then call this function with the option
+tt(-R).  The argument var(statepm) must be a suitable name for an ordinary
+parameter, except that parameters beginning with the prefix tt(_ntr_) are
+reserved for use within tt(narrow-to-region).  Typically the parameter will
+be local to the calling function.
+
 tt(narrow-to-region-invisible) is a simple widget which calls
 tt(narrow-to-region) with arguments which replace any text outside the
 region with `tt(...)'.
 
-On return from both widgets, the display is restored by any zle command
+The display is restored (and the widget returns) upon any zle command
 which would usually cause the line to be accepted or aborted.  Hence an
 additional such command is required to accept or abort the current line.
 
 The return status of both widgets is zero if the line was accepted, else
 non-zero.
+
+Here is a trivial example of a widget using this feature.
+example(local state
+narrow-to-region -p $'Editing restricted region\n' \ 
+  -P '' -S state
+zle recursive-edit
+narrow-to-region -R state)
 )
 tindex(predict-on)
 tindex(predict-off)
diff --git a/Functions/Zle/narrow-to-region b/Functions/Zle/narrow-to-region
index baa8b48c2..1f8438789 100644
--- a/Functions/Zle/narrow-to-region
+++ b/Functions/Zle/narrow-to-region
@@ -8,75 +8,118 @@
 # Other options:
 #   -p pretext   show `pretext' instead of the buffer text before the region.
 #   -P posttext  show  `posttext' instead of the buffer text after the region.
+# Either or both may be empty.
 #   -n           Only replace the text before or after the region with
 #                the -p or -P options if the text was not empty.
-# Either or both may be empty.
+#   -S statevar
+#   -R statevar
+# Save or restore the state in/from the parameter named statevar.  In
+# either case no recursive editing takes place; this will typically be
+# done within the calling function between calls with -S and -R.  The
+# statevar may not begin with the prefix _ntr_ which is reserved for
+# parameters within narrow-to-region.
 
 emulate -L zsh
 setopt extendedglob
 
-local lbuffer rbuffer predisplay=$PREDISPLAY postdisplay=$POSTDISPLAY
-integer start end swap cursor=$CURSOR mark=$MARK stat
+local _ntr_lbuffer _ntr_rbuffer 
+local _ntr_predisplay=$PREDISPLAY _ntr_postdisplay=$POSTDISPLAY
+integer _ntr_start _ntr_end _ntr_swap _ntr_cursor=$CURSOR _ntr_mark=$MARK
+integer _ntr_stat
 
-local opt pretext posttext usepretext useposttext nonempty
+local _ntr_opt _ntr_pretext _ntr_posttext _ntr_usepretext _ntr_useposttext
+local _ntr_nonempty _ntr_save _ntr_restore
 
-while getopts "np:P:" opt; do
-  case $opt in
-    (n) nonempty=1
+while getopts "np:P:R:S:" _ntr_opt; do
+  case $_ntr_opt in
+    (n) _ntr_nonempty=1
+	;;
+    (p) _ntr_pretext=$OPTARG _ntr_usepretext=1
 	;;
-    (p) pretext=$OPTARG usepretext=1
+    (P) _ntr_posttext=$OPTARG _ntr_useposttext=1
 	;;
-    (P) posttext=$OPTARG useposttext=1
+    (R) _ntr_restore=$OPTARG
+        ;;
+    (S)	_ntr_save=$OPTARG
 	;;
-    (*) [[ $opt != '?' ]] && print "$0: unhandled option: $opt" >&2
+    (*) [[ $_ntr_opt != '?' ]] && print "$0: unhandled option: $_ntr_opt" >&2
 	return 1
 	;;
   esac
 done
 (( OPTIND > 1 )) && shift $(( OPTIND - 1 ))
 
-if (( $# )); then
-  if (( $# != 2 )); then
-    zle -M "$0: supply zero or two arguments"
-    return 1
-  fi
-  start=$1
-  end=$2
-else
-  start=$MARK
-  end=$CURSOR
-fi
-
-if (( start == end )); then
+if [[ $_ntr_restore = _ntr_* || $_ntr_save = _ntr_* ]]; then
+  zle -M "$0: _ntr_ prefix is reserved" >&2
   return 1
-elif (( start > end )); then
-  swap=start
-  start=end
-  end=swap
 fi
 
-(( end++, cursor -= start, mark -= start ))
+if [[ -n $_ntr_save || -z $_ntr_restore ]]; then
 
-lbuffer=${BUFFER[1,start]}
-if [[ -z $usepretext || ( -n $nonempty && -z $lbuffer ) ]]; then
-  pretext=$lbuffer
+  if (( $# )); then
+    if (( $# != 2 )); then
+      zle -M "$0: supply zero or two arguments"
+      return 1
+    fi
+    _ntr_start=$1
+    _ntr_end=$2
+  else
+    _ntr_start=$MARK
+    _ntr_end=$CURSOR
+  fi
+
+  if (( _ntr_start == _ntr_end )); then
+    return 1
+  elif (( _ntr_start > _ntr_end )); then
+    _ntr_swap=_ntr_start
+    _ntr_start=_ntr_end
+    _ntr_end=_ntr_swap
+  fi
+
+  (( _ntr_end++, _ntr_cursor -= _ntr_start, _ntr_mark -= _ntr_start ))
+  
+  _ntr_lbuffer=${BUFFER[1,_ntr_start]}
+  if [[ -z $_ntr_usepretext || ( -n $_ntr_nonempty && -z $_ntr_lbuffer ) ]]
+  then
+    _ntr_pretext=$_ntr_lbuffer
+  fi
+  _ntr_rbuffer=${BUFFER[_ntr_end,-1]}
+  if [[ -z $_ntr_useposttext || ( -n $_ntr_nonempty && -z $_ntr_rbuffer ) ]]
+  then
+    _ntr_posttext=$_ntr_rbuffer
+  fi
+  PREDISPLAY="$_ntr_predisplay$_ntr_pretext"
+  POSTDISPLAY="$_ntr_posttext$_ntr_postdisplay"
+  BUFFER=${BUFFER[_ntr_start+1,_ntr_end-1]}
+  CURSOR=$_ntr_cursor
+  MARK=$_ntr_mark
+
+  if [[ -n $_ntr_save ]]; then
+    eval "$_ntr_save=(${(qq)_ntr_predisplay} ${(qq)_ntr_postdisplay}
+${(qq)_ntr_lbuffer} ${(qq)_ntr_rbuffer})" || return 1
+  fi
 fi
-rbuffer=${BUFFER[end,-1]}
-if [[ -z $useposttext || ( -n $nonempty && -z $rbuffer ) ]]; then
-  posttext=$rbuffer
+
+if [[ -z $_ntr_save && -z $_ntr_restore ]]; then
+  zle recursive-edit
+  _ntr_stat=$?
 fi
-PREDISPLAY="$predisplay$pretext"
-POSTDISPLAY="$posttext$postdisplay"
-BUFFER=${BUFFER[start+1,end-1]}
-CURSOR=$cursor
-MARK=$mark
 
-zle recursive-edit
-stat=$?
+if [[ -n $_ntr_restore || -z $_ntr_save ]]; then
+  if [[ -n $_ntr_restore ]]; then
+    if ! eval "_ntr_predisplay=\${${_ntr_restore}[1]}
+_ntr_postdisplay=\${${_ntr_restore}[2]}
+_ntr_lbuffer=\${${_ntr_restore}[3]}
+_ntr_rbuffer=\${${_ntr_restore}[4]}"; then
+      zle -M Failed.
+      return 1
+    fi
+  fi
 
-PREDISPLAY=$predisplay
-POSTDISPLAY=$postdisplay
-LBUFFER="$lbuffer$LBUFFER"
-RBUFFER="$RBUFFER$rbuffer"
+  PREDISPLAY=$_ntr_predisplay
+  POSTDISPLAY=$_ntr_postdisplay
+  LBUFFER="$_ntr_lbuffer$LBUFFER"
+  RBUFFER="$RBUFFER$_ntr_rbuffer"
+fi
 
-return $stat
+return $_ntr_stat