unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
* bug#19829: 25.0.50; query-replace in rectangle regions do not honor boundaries
@ 2015-02-10 14:58 Bastien
  2015-02-10 23:40 ` Juri Linkov
  2015-11-13 23:32 ` Juri Linkov
  0 siblings, 2 replies; 25+ messages in thread
From: Bastien @ 2015-02-10 14:58 UTC (permalink / raw)
  To: 19829


When selecting a region with C-x SPC, then M-% will suggest
replacement in the non-rectangular region.  I expected the
replacements to be suggested within the rectangular region.



In GNU Emacs 25.0.50.5 (i686-pc-linux-gnu, GTK+ Version 3.12.2)
 of 2015-02-10 on bzg
Repository revision: d5111d525f134d0a1f15c61d16d59b20d824f552
Windowing system distributor `The X.Org Foundation', version 11.0.11600000
System Description:	Ubuntu 14.10

Configured features:
XPM JPEG TIFF GIF PNG RSVG IMAGEMAGICK SOUND GPM DBUS GCONF GSETTINGS
NOTIFY LIBSELINUX GNUTLS LIBXML2 FREETYPE M17N_FLT LIBOTF XFT ZLIB

Important settings:
  value of $LANG: fr_FR.UTF-8
  value of $XMODIFIERS: @im=ibus
  locale-coding-system: utf-8-unix

Major mode: Org

Minor modes in effect:
  text-scale-mode: t
  magit-auto-revert-mode: t
  hidden-mode-line-mode: t
  bzg-big-fringe-mode: t
  erc-list-mode: t
  erc-menu-mode: t
  erc-autojoin-mode: t
  erc-ring-mode: t
  erc-networks-mode: t
  erc-pcomplete-mode: t
  erc-track-mode: t
  erc-match-mode: t
  erc-button-mode: t
  erc-fill-mode: t
  erc-stamp-mode: t
  erc-netsplit-mode: t
  erc-irccontrols-mode: t
  erc-noncommands-mode: t
  erc-move-to-prompt-mode: t
  erc-readonly-mode: t
  diff-auto-refine-mode: t
  shell-dirtrack-mode: t
  display-time-mode: t
  show-paren-mode: t
  global-eldoc-mode: t
  electric-indent-mode: t
  mouse-wheel-mode: t
  tool-bar-mode: t
  menu-bar-mode: t
  file-name-shadow-mode: t
  global-font-lock-mode: t
  font-lock-mode: t
  auto-composition-mode: t
  auto-encryption-mode: t
  auto-compression-mode: t
  line-number-mode: t
  auto-fill-function: org-auto-fill-function

Recent messages:
C-z C-g is undefined
Quit
Making completion list... [3 times]
Type C-x 1 to delete the help window.
(No changes need to be saved)
Making completion list...
completing-read-default: Command attempted to use minibuffer while in minibuffer
Quit
Type C-x 1 to delete the help window.
(No changes need to be saved) [2 times]

Load-path shadows:
~/install/git/org-mode/lisp/ob-core hides /usr/local/share/emacs/25.0.50/lisp/org/ob-core
~/install/git/org-mode/lisp/org-mobile hides /usr/local/share/emacs/25.0.50/lisp/org/org-mobile
~/install/git/org-mode/lisp/ob-makefile hides /usr/local/share/emacs/25.0.50/lisp/org/ob-makefile
~/install/git/org-mode/lisp/org-src hides /usr/local/share/emacs/25.0.50/lisp/org/org-src
~/install/git/org-mode/lisp/ob-asymptote hides /usr/local/share/emacs/25.0.50/lisp/org/ob-asymptote
~/install/git/org-mode/lisp/ox-texinfo hides /usr/local/share/emacs/25.0.50/lisp/org/ox-texinfo
~/install/git/org-mode/lisp/org-compat hides /usr/local/share/emacs/25.0.50/lisp/org/org-compat
~/install/git/org-mode/lisp/ox-icalendar hides /usr/local/share/emacs/25.0.50/lisp/org/ox-icalendar
~/install/git/org-mode/lisp/ob-matlab hides /usr/local/share/emacs/25.0.50/lisp/org/ob-matlab
~/install/git/org-mode/lisp/org-datetree hides /usr/local/share/emacs/25.0.50/lisp/org/org-datetree
~/install/git/org-mode/lisp/ob-emacs-lisp hides /usr/local/share/emacs/25.0.50/lisp/org/ob-emacs-lisp
~/install/git/org-mode/lisp/ob-fortran hides /usr/local/share/emacs/25.0.50/lisp/org/ob-fortran
~/install/git/org-mode/lisp/org-mouse hides /usr/local/share/emacs/25.0.50/lisp/org/org-mouse
~/install/git/org-mode/lisp/ob-java hides /usr/local/share/emacs/25.0.50/lisp/org/ob-java
~/install/git/org-mode/lisp/ox-org hides /usr/local/share/emacs/25.0.50/lisp/org/ox-org
~/install/git/org-mode/lisp/ob-shen hides /usr/local/share/emacs/25.0.50/lisp/org/ob-shen
~/install/git/org-mode/lisp/ob-lob hides /usr/local/share/emacs/25.0.50/lisp/org/ob-lob
~/install/git/org-mode/lisp/ob-mscgen hides /usr/local/share/emacs/25.0.50/lisp/org/ob-mscgen
~/install/git/org-mode/lisp/org-ctags hides /usr/local/share/emacs/25.0.50/lisp/org/org-ctags
~/install/git/org-mode/lisp/ob-ruby hides /usr/local/share/emacs/25.0.50/lisp/org/ob-ruby
~/install/git/org-mode/lisp/org-gnus hides /usr/local/share/emacs/25.0.50/lisp/org/org-gnus
~/install/git/org-mode/lisp/org-bibtex hides /usr/local/share/emacs/25.0.50/lisp/org/org-bibtex
~/install/git/org-mode/lisp/ob-ditaa hides /usr/local/share/emacs/25.0.50/lisp/org/ob-ditaa
~/install/git/org-mode/lisp/ob-comint hides /usr/local/share/emacs/25.0.50/lisp/org/ob-comint
~/install/git/org-mode/lisp/ob-lilypond hides /usr/local/share/emacs/25.0.50/lisp/org/ob-lilypond
~/install/git/org-mode/lisp/ob-sass hides /usr/local/share/emacs/25.0.50/lisp/org/ob-sass
~/install/git/org-mode/lisp/ob-io hides /usr/local/share/emacs/25.0.50/lisp/org/ob-io
~/install/git/org-mode/lisp/ox-man hides /usr/local/share/emacs/25.0.50/lisp/org/ox-man
~/install/git/org-mode/lisp/org-archive hides /usr/local/share/emacs/25.0.50/lisp/org/org-archive
~/install/git/org-mode/lisp/org-version hides /usr/local/share/emacs/25.0.50/lisp/org/org-version
~/install/git/org-mode/lisp/org-agenda hides /usr/local/share/emacs/25.0.50/lisp/org/org-agenda
~/install/git/org-mode/lisp/ob-ocaml hides /usr/local/share/emacs/25.0.50/lisp/org/ob-ocaml
~/install/git/org-mode/lisp/ob-eval hides /usr/local/share/emacs/25.0.50/lisp/org/ob-eval
~/install/git/org-mode/lisp/ob-keys hides /usr/local/share/emacs/25.0.50/lisp/org/ob-keys
~/install/git/org-mode/lisp/org-colview hides /usr/local/share/emacs/25.0.50/lisp/org/org-colview
~/install/git/org-mode/lisp/ob-screen hides /usr/local/share/emacs/25.0.50/lisp/org/ob-screen
~/install/git/org-mode/lisp/ob-sqlite hides /usr/local/share/emacs/25.0.50/lisp/org/ob-sqlite
~/install/git/org-mode/lisp/ob-table hides /usr/local/share/emacs/25.0.50/lisp/org/ob-table
~/install/git/org-mode/lisp/org-macro hides /usr/local/share/emacs/25.0.50/lisp/org/org-macro
~/install/git/org-mode/lisp/org-docview hides /usr/local/share/emacs/25.0.50/lisp/org/org-docview
~/install/git/org-mode/lisp/org-protocol hides /usr/local/share/emacs/25.0.50/lisp/org/org-protocol
~/install/git/org-mode/lisp/ox-publish hides /usr/local/share/emacs/25.0.50/lisp/org/ox-publish
~/install/git/org-mode/lisp/ob-js hides /usr/local/share/emacs/25.0.50/lisp/org/ob-js
~/install/git/org-mode/lisp/org-element hides /usr/local/share/emacs/25.0.50/lisp/org/org-element
~/install/git/org-mode/lisp/ob-perl hides /usr/local/share/emacs/25.0.50/lisp/org/ob-perl
~/install/git/org-mode/lisp/ox hides /usr/local/share/emacs/25.0.50/lisp/org/ox
~/install/git/org-mode/lisp/org-install hides /usr/local/share/emacs/25.0.50/lisp/org/org-install
~/install/git/org-mode/lisp/org-id hides /usr/local/share/emacs/25.0.50/lisp/org/org-id
~/install/git/org-mode/lisp/org hides /usr/local/share/emacs/25.0.50/lisp/org/org
~/install/git/org-mode/lisp/ob-tangle hides /usr/local/share/emacs/25.0.50/lisp/org/ob-tangle
~/install/git/org-mode/lisp/ob-octave hides /usr/local/share/emacs/25.0.50/lisp/org/ob-octave
~/install/git/org-mode/lisp/ob-plantuml hides /usr/local/share/emacs/25.0.50/lisp/org/ob-plantuml
~/install/git/org-mode/lisp/ob-haskell hides /usr/local/share/emacs/25.0.50/lisp/org/ob-haskell
~/install/git/org-mode/lisp/org-w3m hides /usr/local/share/emacs/25.0.50/lisp/org/org-w3m
~/install/git/org-mode/lisp/ob-picolisp hides /usr/local/share/emacs/25.0.50/lisp/org/ob-picolisp
~/install/git/org-mode/lisp/ob-org hides /usr/local/share/emacs/25.0.50/lisp/org/ob-org
~/install/git/org-mode/lisp/org-clock hides /usr/local/share/emacs/25.0.50/lisp/org/org-clock
~/install/git/org-mode/lisp/org-indent hides /usr/local/share/emacs/25.0.50/lisp/org/org-indent
~/install/git/org-mode/lisp/ob-css hides /usr/local/share/emacs/25.0.50/lisp/org/ob-css
~/install/git/org-mode/lisp/ob-latex hides /usr/local/share/emacs/25.0.50/lisp/org/ob-latex
~/install/git/org-mode/lisp/org-capture hides /usr/local/share/emacs/25.0.50/lisp/org/org-capture
~/install/git/org-mode/lisp/ob-scheme hides /usr/local/share/emacs/25.0.50/lisp/org/ob-scheme
~/install/git/org-mode/lisp/org-info hides /usr/local/share/emacs/25.0.50/lisp/org/org-info
~/install/git/org-mode/lisp/ox-odt hides /usr/local/share/emacs/25.0.50/lisp/org/ox-odt
~/install/git/org-mode/lisp/org-footnote hides /usr/local/share/emacs/25.0.50/lisp/org/org-footnote
~/install/git/org-mode/lisp/org-plot hides /usr/local/share/emacs/25.0.50/lisp/org/org-plot
~/install/git/org-mode/lisp/ob-maxima hides /usr/local/share/emacs/25.0.50/lisp/org/ob-maxima
~/install/git/org-mode/lisp/ob-awk hides /usr/local/share/emacs/25.0.50/lisp/org/ob-awk
~/install/git/org-mode/lisp/ob-dot hides /usr/local/share/emacs/25.0.50/lisp/org/ob-dot
~/install/git/org-mode/lisp/org-eshell hides /usr/local/share/emacs/25.0.50/lisp/org/org-eshell
~/install/git/org-mode/lisp/ob-ledger hides /usr/local/share/emacs/25.0.50/lisp/org/ob-ledger
~/install/git/org-mode/lisp/org-list hides /usr/local/share/emacs/25.0.50/lisp/org/org-list
~/install/git/org-mode/lisp/ob-scala hides /usr/local/share/emacs/25.0.50/lisp/org/ob-scala
~/install/git/org-mode/lisp/ox-beamer hides /usr/local/share/emacs/25.0.50/lisp/org/ox-beamer
~/install/git/org-mode/lisp/ox-html hides /usr/local/share/emacs/25.0.50/lisp/org/ox-html
~/install/git/org-mode/lisp/ob-python hides /usr/local/share/emacs/25.0.50/lisp/org/ob-python
~/install/git/org-mode/lisp/ob-gnuplot hides /usr/local/share/emacs/25.0.50/lisp/org/ob-gnuplot
~/install/git/org-mode/lisp/ob hides /usr/local/share/emacs/25.0.50/lisp/org/ob
~/install/git/org-mode/lisp/ox-md hides /usr/local/share/emacs/25.0.50/lisp/org/ox-md
~/install/git/org-mode/lisp/org-entities hides /usr/local/share/emacs/25.0.50/lisp/org/org-entities
~/install/git/org-mode/lisp/ob-sql hides /usr/local/share/emacs/25.0.50/lisp/org/ob-sql
~/install/git/org-mode/lisp/org-inlinetask hides /usr/local/share/emacs/25.0.50/lisp/org/org-inlinetask
~/install/git/org-mode/lisp/ob-C hides /usr/local/share/emacs/25.0.50/lisp/org/ob-C
~/install/git/org-mode/lisp/ob-R hides /usr/local/share/emacs/25.0.50/lisp/org/ob-R
~/install/git/org-mode/lisp/org-timer hides /usr/local/share/emacs/25.0.50/lisp/org/org-timer
~/install/git/org-mode/lisp/org-pcomplete hides /usr/local/share/emacs/25.0.50/lisp/org/org-pcomplete
~/install/git/org-mode/lisp/ox-latex hides /usr/local/share/emacs/25.0.50/lisp/org/ox-latex
~/install/git/org-mode/lisp/org-loaddefs hides /usr/local/share/emacs/25.0.50/lisp/org/org-loaddefs
~/install/git/org-mode/lisp/org-bbdb hides /usr/local/share/emacs/25.0.50/lisp/org/org-bbdb
~/install/git/org-mode/lisp/ob-ref hides /usr/local/share/emacs/25.0.50/lisp/org/ob-ref
~/install/git/org-mode/lisp/ob-calc hides /usr/local/share/emacs/25.0.50/lisp/org/ob-calc
~/install/git/org-mode/lisp/org-faces hides /usr/local/share/emacs/25.0.50/lisp/org/org-faces
~/install/git/org-mode/lisp/ob-lisp hides /usr/local/share/emacs/25.0.50/lisp/org/ob-lisp
~/install/git/org-mode/lisp/org-irc hides /usr/local/share/emacs/25.0.50/lisp/org/org-irc
~/install/git/org-mode/lisp/ob-clojure hides /usr/local/share/emacs/25.0.50/lisp/org/ob-clojure
~/install/git/org-mode/lisp/org-feed hides /usr/local/share/emacs/25.0.50/lisp/org/org-feed
~/install/git/org-mode/lisp/org-attach hides /usr/local/share/emacs/25.0.50/lisp/org/org-attach
~/install/git/org-mode/lisp/ox-ascii hides /usr/local/share/emacs/25.0.50/lisp/org/ox-ascii
~/install/git/org-mode/lisp/org-macs hides /usr/local/share/emacs/25.0.50/lisp/org/org-macs
~/install/git/org-mode/lisp/org-habit hides /usr/local/share/emacs/25.0.50/lisp/org/org-habit
~/install/git/org-mode/lisp/org-crypt hides /usr/local/share/emacs/25.0.50/lisp/org/org-crypt
~/install/git/org-mode/lisp/ob-exp hides /usr/local/share/emacs/25.0.50/lisp/org/ob-exp
~/install/git/org-mode/lisp/org-rmail hides /usr/local/share/emacs/25.0.50/lisp/org/org-rmail
~/install/git/org-mode/lisp/org-mhe hides /usr/local/share/emacs/25.0.50/lisp/org/org-mhe
~/install/git/org-mode/lisp/org-table hides /usr/local/share/emacs/25.0.50/lisp/org/org-table
/usr/local/share/emacs/25.0.50/lisp/gnus/gnus hides /home/guerry/elisp/config/gnus
/usr/local/share/emacs/25.0.50/lisp/textmodes/ispell hides /usr/share/emacs/site-lisp/dictionaries-common/ispell
/usr/local/share/emacs/25.0.50/lisp/textmodes/flyspell hides /usr/share/emacs/site-lisp/dictionaries-common/flyspell
/usr/local/share/emacs/site-lisp/notmuch-tree hides /usr/share/emacs/site-lisp/notmuch/notmuch-tree
/usr/local/share/emacs/site-lisp/notmuch hides /usr/share/emacs/site-lisp/notmuch/notmuch
/usr/local/share/emacs/site-lisp/notmuch-print hides /usr/share/emacs/site-lisp/notmuch/notmuch-print
/usr/local/share/emacs/site-lisp/notmuch-hello hides /usr/share/emacs/site-lisp/notmuch/notmuch-hello
/usr/local/share/emacs/site-lisp/notmuch-crypto hides /usr/share/emacs/site-lisp/notmuch/notmuch-crypto
/usr/local/share/emacs/site-lisp/notmuch-maildir-fcc hides /usr/share/emacs/site-lisp/notmuch/notmuch-maildir-fcc
/usr/local/share/emacs/site-lisp/notmuch-tag hides /usr/share/emacs/site-lisp/notmuch/notmuch-tag
/usr/local/share/emacs/site-lisp/coolj hides /usr/share/emacs/site-lisp/notmuch/coolj
/usr/local/share/emacs/site-lisp/notmuch-query hides /usr/share/emacs/site-lisp/notmuch/notmuch-query
/usr/local/share/emacs/site-lisp/notmuch-parser hides /usr/share/emacs/site-lisp/notmuch/notmuch-parser
/usr/local/share/emacs/site-lisp/notmuch-message hides /usr/share/emacs/site-lisp/notmuch/notmuch-message
/usr/local/share/emacs/site-lisp/notmuch-wash hides /usr/share/emacs/site-lisp/notmuch/notmuch-wash
/usr/local/share/emacs/site-lisp/notmuch-lib hides /usr/share/emacs/site-lisp/notmuch/notmuch-lib
/usr/local/share/emacs/site-lisp/notmuch-address hides /usr/share/emacs/site-lisp/notmuch/notmuch-address
/usr/local/share/emacs/site-lisp/notmuch-show hides /usr/share/emacs/site-lisp/notmuch/notmuch-show
/usr/local/share/emacs/site-lisp/notmuch-mua hides /usr/share/emacs/site-lisp/notmuch/notmuch-mua
~/install/git/org-mode/lisp/org-src hides /usr/share/emacs/site-lisp/org/org-src
~/install/git/org-mode/lisp/ob-J hides /usr/share/emacs/site-lisp/org/ob-J
~/install/git/org-mode/lisp/ob-asymptote hides /usr/share/emacs/site-lisp/org/ob-asymptote
~/install/git/org-mode/lisp/ox-icalendar hides /usr/share/emacs/site-lisp/org/ox-icalendar
~/install/git/org-mode/lisp/ox-org hides /usr/share/emacs/site-lisp/org/ox-org
~/install/git/org-mode/lisp/org-bibtex hides /usr/share/emacs/site-lisp/org/org-bibtex
~/install/git/org-mode/lisp/ob-groovy hides /usr/share/emacs/site-lisp/org/ob-groovy
~/install/git/org-mode/lisp/org-list hides /usr/share/emacs/site-lisp/org/org-list
~/install/git/org-mode/lisp/org-datetree hides /usr/share/emacs/site-lisp/org/org-datetree
~/install/git/org-mode/lisp/ob-emacs-lisp hides /usr/share/emacs/site-lisp/org/ob-emacs-lisp
~/install/git/org-mode/lisp/org-mouse hides /usr/share/emacs/site-lisp/org/org-mouse
~/install/git/org-mode/lisp/ob-java hides /usr/share/emacs/site-lisp/org/ob-java
~/install/git/org-mode/lisp/org-plot hides /usr/share/emacs/site-lisp/org/org-plot
~/install/git/org-mode/lisp/ob-C hides /usr/share/emacs/site-lisp/org/ob-C
~/install/git/org-mode/lisp/ox-html hides /usr/share/emacs/site-lisp/org/ox-html
~/install/git/org-mode/lisp/ox-odt hides /usr/share/emacs/site-lisp/org/ox-odt
~/install/git/org-mode/lisp/ob-shen hides /usr/share/emacs/site-lisp/org/ob-shen
~/install/git/org-mode/lisp/org-inlinetask hides /usr/share/emacs/site-lisp/org/org-inlinetask
~/install/git/org-mode/lisp/ob-plantuml hides /usr/share/emacs/site-lisp/org/ob-plantuml
~/install/git/org-mode/lisp/ob-js hides /usr/share/emacs/site-lisp/org/ob-js
~/install/git/org-mode/lisp/ob-mscgen hides /usr/share/emacs/site-lisp/org/ob-mscgen
~/install/git/org-mode/lisp/ob-sqlite hides /usr/share/emacs/site-lisp/org/ob-sqlite
~/install/git/org-mode/lisp/org-w3m hides /usr/share/emacs/site-lisp/org/org-w3m
~/install/git/org-mode/lisp/org-ctags hides /usr/share/emacs/site-lisp/org/org-ctags
~/install/git/org-mode/lisp/org-habit hides /usr/share/emacs/site-lisp/org/org-habit
~/install/git/org-mode/lisp/ob-org hides /usr/share/emacs/site-lisp/org/ob-org
~/install/git/org-mode/lisp/ox-beamer hides /usr/share/emacs/site-lisp/org/ox-beamer
~/install/git/org-mode/lisp/org-gnus hides /usr/share/emacs/site-lisp/org/org-gnus
~/install/git/org-mode/lisp/ob-lob hides /usr/share/emacs/site-lisp/org/ob-lob
~/install/git/org-mode/lisp/ob-ditaa hides /usr/share/emacs/site-lisp/org/ob-ditaa
~/install/git/org-mode/lisp/ob-comint hides /usr/share/emacs/site-lisp/org/ob-comint
~/install/git/org-mode/lisp/ob-haskell hides /usr/share/emacs/site-lisp/org/ob-haskell
~/install/git/org-mode/lisp/ob-sass hides /usr/share/emacs/site-lisp/org/ob-sass
~/install/git/org-mode/lisp/org-id hides /usr/share/emacs/site-lisp/org/org-id
~/install/git/org-mode/lisp/org-archive hides /usr/share/emacs/site-lisp/org/org-archive
~/install/git/org-mode/lisp/org-mobile hides /usr/share/emacs/site-lisp/org/org-mobile
~/install/git/org-mode/lisp/ob-clojure hides /usr/share/emacs/site-lisp/org/ob-clojure
~/install/git/org-mode/lisp/ob-io hides /usr/share/emacs/site-lisp/org/ob-io
~/install/git/org-mode/lisp/ox-man hides /usr/share/emacs/site-lisp/org/ox-man
~/install/git/org-mode/lisp/ob-latex hides /usr/share/emacs/site-lisp/org/ob-latex
~/install/git/org-mode/lisp/org-indent hides /usr/share/emacs/site-lisp/org/org-indent
~/install/git/org-mode/lisp/ox-ascii hides /usr/share/emacs/site-lisp/org/ox-ascii
~/install/git/org-mode/lisp/ob-ruby hides /usr/share/emacs/site-lisp/org/ob-ruby
~/install/git/org-mode/lisp/org-colview hides /usr/share/emacs/site-lisp/org/org-colview
~/install/git/org-mode/lisp/org-pcomplete hides /usr/share/emacs/site-lisp/org/org-pcomplete
~/install/git/org-mode/lisp/org-version hides /usr/share/emacs/site-lisp/org/org-version
~/install/git/org-mode/lisp/ob-ocaml hides /usr/share/emacs/site-lisp/org/ob-ocaml
~/install/git/org-mode/lisp/ob-ebnf hides /usr/share/emacs/site-lisp/org/ob-ebnf
~/install/git/org-mode/lisp/ob-keys hides /usr/share/emacs/site-lisp/org/ob-keys
~/install/git/org-mode/lisp/ob-screen hides /usr/share/emacs/site-lisp/org/ob-screen
~/install/git/org-mode/lisp/ob-table hides /usr/share/emacs/site-lisp/org/ob-table
~/install/git/org-mode/lisp/ob-abc hides /usr/share/emacs/site-lisp/org/ob-abc
~/install/git/org-mode/lisp/ob-shell hides /usr/share/emacs/site-lisp/org/ob-shell
~/install/git/org-mode/lisp/ob-picolisp hides /usr/share/emacs/site-lisp/org/ob-picolisp
~/install/git/org-mode/lisp/org-macro hides /usr/share/emacs/site-lisp/org/org-macro
~/install/git/org-mode/lisp/org-protocol hides /usr/share/emacs/site-lisp/org/org-protocol
~/install/git/org-mode/lisp/org-mhe hides /usr/share/emacs/site-lisp/org/org-mhe
~/install/git/org-mode/lisp/ox-publish hides /usr/share/emacs/site-lisp/org/ox-publish
~/install/git/org-mode/lisp/org-compat hides /usr/share/emacs/site-lisp/org/org-compat
~/install/git/org-mode/lisp/ob-perl hides /usr/share/emacs/site-lisp/org/ob-perl
~/install/git/org-mode/lisp/ox hides /usr/share/emacs/site-lisp/org/ox
~/install/git/org-mode/lisp/org-install hides /usr/share/emacs/site-lisp/org/org-install
~/install/git/org-mode/lisp/ob-ledger hides /usr/share/emacs/site-lisp/org/ob-ledger
~/install/git/org-mode/lisp/org-entities hides /usr/share/emacs/site-lisp/org/org-entities
~/install/git/org-mode/lisp/ob-core hides /usr/share/emacs/site-lisp/org/ob-core
~/install/git/org-mode/lisp/ob-lilypond hides /usr/share/emacs/site-lisp/org/ob-lilypond
~/install/git/org-mode/lisp/org hides /usr/share/emacs/site-lisp/org/org
~/install/git/org-mode/lisp/ob-fortran hides /usr/share/emacs/site-lisp/org/ob-fortran
~/install/git/org-mode/lisp/ob-tangle hides /usr/share/emacs/site-lisp/org/ob-tangle
~/install/git/org-mode/lisp/ob-octave hides /usr/share/emacs/site-lisp/org/ob-octave
~/install/git/org-mode/lisp/org-rmail hides /usr/share/emacs/site-lisp/org/org-rmail
~/install/git/org-mode/lisp/org-feed hides /usr/share/emacs/site-lisp/org/org-feed
~/install/git/org-mode/lisp/ob-lisp hides /usr/share/emacs/site-lisp/org/ob-lisp
~/install/git/org-mode/lisp/org-clock hides /usr/share/emacs/site-lisp/org/org-clock
~/install/git/org-mode/lisp/ob-awk hides /usr/share/emacs/site-lisp/org/ob-awk
~/install/git/org-mode/lisp/ob-scheme hides /usr/share/emacs/site-lisp/org/ob-scheme
~/install/git/org-mode/lisp/org-info hides /usr/share/emacs/site-lisp/org/org-info
~/install/git/org-mode/lisp/org-footnote hides /usr/share/emacs/site-lisp/org/org-footnote
~/install/git/org-mode/lisp/ob-maxima hides /usr/share/emacs/site-lisp/org/ob-maxima
~/install/git/org-mode/lisp/ob-dot hides /usr/share/emacs/site-lisp/org/ob-dot
~/install/git/org-mode/lisp/org-eshell hides /usr/share/emacs/site-lisp/org/org-eshell
~/install/git/org-mode/lisp/ob-css hides /usr/share/emacs/site-lisp/org/ob-css
~/install/git/org-mode/lisp/ob-exp hides /usr/share/emacs/site-lisp/org/ob-exp
~/install/git/org-mode/lisp/org-table hides /usr/share/emacs/site-lisp/org/org-table
~/install/git/org-mode/lisp/ob-makefile hides /usr/share/emacs/site-lisp/org/ob-makefile
~/install/git/org-mode/lisp/ob-coq hides /usr/share/emacs/site-lisp/org/ob-coq
~/install/git/org-mode/lisp/ob-python hides /usr/share/emacs/site-lisp/org/ob-python
~/install/git/org-mode/lisp/ob hides /usr/share/emacs/site-lisp/org/ob
~/install/git/org-mode/lisp/ob-matlab hides /usr/share/emacs/site-lisp/org/ob-matlab
~/install/git/org-mode/lisp/org-bbdb hides /usr/share/emacs/site-lisp/org/org-bbdb
~/install/git/org-mode/lisp/ob-R hides /usr/share/emacs/site-lisp/org/ob-R
~/install/git/org-mode/lisp/org-timer hides /usr/share/emacs/site-lisp/org/org-timer
~/install/git/org-mode/lisp/org-crypt hides /usr/share/emacs/site-lisp/org/org-crypt
~/install/git/org-mode/lisp/org-docview hides /usr/share/emacs/site-lisp/org/org-docview
~/install/git/org-mode/lisp/org-loaddefs hides /usr/share/emacs/site-lisp/org/org-loaddefs
~/install/git/org-mode/lisp/org-capture hides /usr/share/emacs/site-lisp/org/org-capture
~/install/git/org-mode/lisp/ob-sql hides /usr/share/emacs/site-lisp/org/ob-sql
~/install/git/org-mode/lisp/ox-texinfo hides /usr/share/emacs/site-lisp/org/ox-texinfo
~/install/git/org-mode/lisp/ob-scala hides /usr/share/emacs/site-lisp/org/ob-scala
~/install/git/org-mode/lisp/ob-calc hides /usr/share/emacs/site-lisp/org/ob-calc
~/install/git/org-mode/lisp/org-faces hides /usr/share/emacs/site-lisp/org/org-faces
~/install/git/org-mode/lisp/org-macs hides /usr/share/emacs/site-lisp/org/org-macs
~/install/git/org-mode/lisp/ox-latex hides /usr/share/emacs/site-lisp/org/ox-latex
~/install/git/org-mode/lisp/org-element hides /usr/share/emacs/site-lisp/org/org-element
~/install/git/org-mode/lisp/org-agenda hides /usr/share/emacs/site-lisp/org/org-agenda
~/install/git/org-mode/lisp/org-irc hides /usr/share/emacs/site-lisp/org/org-irc
~/install/git/org-mode/lisp/ox-md hides /usr/share/emacs/site-lisp/org/ox-md
~/install/git/org-mode/lisp/ob-forth hides /usr/share/emacs/site-lisp/org/ob-forth
~/install/git/org-mode/lisp/ob-ref hides /usr/share/emacs/site-lisp/org/ob-ref
~/install/git/org-mode/lisp/ob-eval hides /usr/share/emacs/site-lisp/org/ob-eval
~/install/git/org-mode/lisp/ob-gnuplot hides /usr/share/emacs/site-lisp/org/ob-gnuplot
~/install/git/org-mode/lisp/org-attach hides /usr/share/emacs/site-lisp/org/org-attach

Features:
(shadow emacsbug ox-org calc-map calc-stat calc-vec calc-ext calc-menu
calc-aent calc calc-loaddefs calc-macs dired-aux gnus-draft flow-fill
gnus-dup gnus-mlspl sort smiley gnus-html mm-url qp mm-archive
gnus-async gnus-bcklg gnus-ml disp-table misearch multi-isearch
holidays hol-loaddefs cal-move debug gnus-cite nnir gnus-topic utf-7
nndraft nnmh nnfolder gnutls network-stream nsm nnml nnmaildir
gnus-agent gnus-srvr gnus-score score-mode nnvirtual nntp gnus-cache
eieio-opt speedbar sb-image ezimage dframe face-remap cal-iso bookmark
tabify helm-config helm-autoloads helm-aliases magit-key-mode magit
view help-mode grep autorevert filenotify git-rebase-mode
git-commit-mode log-edit pcvs-util add-log company-statistics server
benchmark erc-services erc-list erc-menu erc-join erc-ring
erc-networks erc-pcomplete erc-track erc-match erc-button erc-fill
erc-stamp erc-netsplit erc-goodies erc erc-backend erc-compat pp
bbdb-message bbdb-gnus bbdb-mua bbdb-anniv bbdb-loaddefs gnus-gravatar
mail-extr gravatar url-cache ecomplete boxquote rect spam spam-stat
bbdb-com bbdb bbdb-site gnus-uu yenc gnus-msg gnus-art mm-uu mml2015
smtpmail sendmail epa epg starttls notmuch hl-line notmuch-version
notmuch-message notmuch-maildir-fcc notmuch-hello notmuch-tree
notmuch-parser notmuch-show notmuch-print notmuch-crypto notmuch-mua
notmuch-address notmuch-wash coolj notmuch-query goto-addr icalendar
notmuch-tag crm notmuch-lib mm-view mml-smime smime dig debbugs-org
debbugs-gnu debbugs soap-client url-http url-auth url-gw url url-proxy
url-privacy url-expand url-methods url-history url-cookie url-domsuf
url-util url-parse url-vars mailcap warnings xml vc-git diff-mode
org-rmail org-mhe org-irc org-info org-docview org-bibtex bibtex
org-bbdb org-w3m org-agenda appt diary-lib diary-loaddefs org-clock
ob-gnuplot ob-R ob-plantuml ob-scheme geiser ob-ledger ob-ditaa ob-org
ob-clojure ob-dot ob-sh ox-koma-letter org-gnus ox-odt rng-loc rng-uri
rng-parse rng-match rng-dt rng-util rng-pttrn nxml-parse nxml-ns
nxml-enc xmltok nxml-util ox-beamer ox-reveal ox-rss ox-latex
ox-icalendar ox-html table ox-ascii ox-publish ox org-element avl-tree
wdired dired-details dired-x w3m browse-url doc-view jka-compr
image-mode timezone w3m-hist w3m-fb bookmark-w3m w3m-ems w3m-ccl ccl
w3m-favicon w3m-image w3m-proc w3m-util cyberpunk-theme info company
cider tramp-sh cider-mode cider-repl cider-eldoc cider-interaction
apropos compile arc-mode archive-mode cider-doc org-table org
org-macro org-footnote org-pcomplete org-list org-faces org-entities
noutline outline org-version ob-emacs-lisp ob ob-tangle ob-ref ob-lob
ob-table ob-exp org-src easy-mmode ob-keys ob-comint ob-core ob-eval
org-compat org-macs org-loaddefs find-func cal-menu calendar
cal-loaddefs gnus-sum gnus-group gnus-undo gnus-start gnus-cloud
nnimap nnmail mail-source tls utf7 netrc nnoo parse-time gnus-spec
gnus-int gnus-range message rfc822 mml mml-sec mm-decode mm-bodies
mm-encode mail-parse rfc2231 rfc2047 rfc2045 ietf-drums mailabbrev
gmm-utils mailheader gnus-win gnus gnus-ems nnheader mail-utils
wid-edit cider-test cider-stacktrace cider-client nrepl-client tramp
tramp-compat auth-source gnus-util mm-util mail-prsvr password-cache
tramp-loaddefs trampver shell pcomplete comint format-spec queue
cider-util clojure-mode rx cl-macs derived edmacro kmacro easymenu
imenu cl ewoc ansi-color etags xref eieio byte-opt bytecomp
byte-compile cl-extra seq cconv eieio-core cl-generic pcase
cl-loaddefs cl-lib ring thingatpt dash gv ibuffer mule-util elscreen
advice help-fns dired register-list time paren whitespace elec-pair
company-autoloads dash-autoloads debbugs-autoloads dired+-autoloads
dired-details-autoloads queue-autoloads register-list-autoloads
package epg-config time-date tooltip eldoc electric uniquify
ediff-hook vc-hooks lisp-float-type mwheel x-win x-dnd tool-bar dnd
fontset image regexp-opt fringe tabulated-list newcomment elisp-mode
lisp-mode prog-mode register page menu-bar rfn-eshadow timer select
scroll-bar mouse jit-lock font-lock syntax facemenu font-core frame
cham georgian utf-8-lang misc-lang vietnamese tibetan thai tai-viet
lao korean japanese hebrew greek romanian slovak czech european
ethiopic indian cyrillic chinese case-table epa-hook jka-cmpr-hook
help simple abbrev minibuffer cl-preloaded nadvice loaddefs button
faces cus-face macroexp files text-properties overlay sha1 md5 base64
format env code-pages mule custom widget hashtable-print-readable
backquote make-network-process dbusbind gfilenotify dynamic-setting
system-font-setting font-render-setting move-toolbar gtk x-toolkit x
multi-tty emacs)

Memory information:
((conses 8 1534388 185285)
 (symbols 24 137946 0)
 (miscs 20 43830 7717)
 (strings 16 504955 31175)
 (string-bytes 1 15293294)
 (vectors 8 105801)
 (vector-slots 4 2266305 80282)
 (floats 8 944 409)
 (intervals 28 32636 4161)
 (buffers 520 99)
 (heap 1024 145190 5395))

-- 
 Bastien





^ permalink raw reply	[flat|nested] 25+ messages in thread

* bug#19829: 25.0.50; query-replace in rectangle regions do not honor boundaries
  2015-02-10 14:58 bug#19829: 25.0.50; query-replace in rectangle regions do not honor boundaries Bastien
@ 2015-02-10 23:40 ` Juri Linkov
  2015-02-12  0:57   ` Juri Linkov
  2015-11-13 23:32 ` Juri Linkov
  1 sibling, 1 reply; 25+ messages in thread
From: Juri Linkov @ 2015-02-10 23:40 UTC (permalink / raw)
  To: Bastien; +Cc: 19829

> When selecting a region with C-x SPC, then M-% will suggest
> replacement in the non-rectangular region.  I expected the
> replacements to be suggested within the rectangular region.

It would be very easy to support the rectangular region replacements
the same way as such replacements are already supported in WDired
where replacements are restricted to the vertical column of filenames.

But the problem is that I don't see how the information about
column positions of the selected rectangular region would be
supplied to query-replace by region-beginning and region-end.





^ permalink raw reply	[flat|nested] 25+ messages in thread

* bug#19829: 25.0.50; query-replace in rectangle regions do not honor boundaries
  2015-02-10 23:40 ` Juri Linkov
@ 2015-02-12  0:57   ` Juri Linkov
  2015-02-12 14:33     ` Stefan Monnier
  0 siblings, 1 reply; 25+ messages in thread
From: Juri Linkov @ 2015-02-12  0:57 UTC (permalink / raw)
  To: Bastien; +Cc: 19829

>> When selecting a region with C-x SPC, then M-% will suggest
>> replacement in the non-rectangular region.  I expected the
>> replacements to be suggested within the rectangular region.
>
> It would be very easy to support the rectangular region replacements
> the same way as such replacements are already supported in WDired
> where replacements are restricted to the vertical column of filenames.
>
> But the problem is that I don't see how the information about
> column positions of the selected rectangular region would be
> supplied to query-replace by region-beginning and region-end.

I wonder how do other commands that accept region-beginning/end
process the rectangular region?





^ permalink raw reply	[flat|nested] 25+ messages in thread

* bug#19829: 25.0.50; query-replace in rectangle regions do not honor boundaries
  2015-02-12  0:57   ` Juri Linkov
@ 2015-02-12 14:33     ` Stefan Monnier
  2015-02-13  0:54       ` Juri Linkov
  0 siblings, 1 reply; 25+ messages in thread
From: Stefan Monnier @ 2015-02-12 14:33 UTC (permalink / raw)
  To: Juri Linkov; +Cc: Bastien, 19829

> I wonder how do other commands that accept region-beginning/end
> process the rectangular region?

Well, there's the source code to help you find out, of course.
More seriously, the rectangle support (can be rect.el or cua-rect.el)
code sets up `region-extract-function' and commands that need to operate
on the region should then call `region-extract-function' instead of
relying on region-beginning/end.

Obviously, this infrastructure is not sufficient for query-replace, so
we'll need to add a `region-map-function` or something like that.


        Stefan


PS: when designing this interface I had in mind potential future
non-rectangular (and non-contiguous) regions, such as those that one can
define in some systems (e.g. file-managers) via "control-click".





^ permalink raw reply	[flat|nested] 25+ messages in thread

* bug#19829: 25.0.50; query-replace in rectangle regions do not honor boundaries
  2015-02-12 14:33     ` Stefan Monnier
@ 2015-02-13  0:54       ` Juri Linkov
  2015-02-14  3:59         ` Stefan Monnier
  0 siblings, 1 reply; 25+ messages in thread
From: Juri Linkov @ 2015-02-13  0:54 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: Bastien, 19829

>> I wonder how do other commands that accept region-beginning/end
>> process the rectangular region?
>
> Well, there's the source code to help you find out, of course.
> More seriously, the rectangle support (can be rect.el or cua-rect.el)
> code sets up `region-extract-function' and commands that need to operate
> on the region should then call `region-extract-function' instead of
> relying on region-beginning/end.
>
> Obviously, this infrastructure is not sufficient for query-replace, so
> we'll need to add a `region-map-function` or something like that.

Better would be to add a function that will return a list of positions
of the rectangular region, i.e. while currently for the contiguous region
region-beginning/end returns its bounds, for non-contiguous rectangular
regions we need a list of column bounds.

As a proof of concept, this small patch implements the feature of
query-replace in rectangular regions, but I'm not sure how its parts
should be refactored into a more general function such as e.g.
`region-positions-extract-function' that will return a list of
region positions.

diff --git a/lisp/replace.el b/lisp/replace.el
index e0636e0..8eeeb1a 100644
--- a/lisp/replace.el
+++ b/lisp/replace.el
@@ -2089,6 +2089,7 @@ (defun perform-replace (from-string replacements
 
          ;; If non-nil, it is marker saying where in the buffer to stop.
          (limit nil)
+	 (rectangular-region-positions nil)
 
          ;; Data for the next match.  If a cons, it has the same format as
          ;; (match-data); otherwise it is t if a match is possible at point.
@@ -2101,6 +2102,27 @@ (defun perform-replace (from-string replacements
                       "Query replacing %s with %s: (\\<query-replace-map>\\[help] for help) ")
                      minibuffer-prompt-properties))))
 
+    (when rectangle-mark-mode
+      (let ((positions (list nil)))
+	(apply-on-rectangle
+	 (lambda (startcol endcol positions)
+	   (setcdr positions (cons (cons
+				    (progn (move-to-column startcol) (point))
+				    (progn (move-to-column endcol)   (point)))
+				   (cdr positions))))
+	 (region-beginning) (region-end) positions)
+	(setq rectangular-region-positions (nreverse (cdr positions)))
+	(add-function :after-while (local 'isearch-filter-predicate)
+		      (lambda (start end)
+			(delq nil (mapcar
+				   (lambda (positions)
+				     (and
+				      (>= start (car positions))
+				      (<= start (cdr positions))
+				      (>= end   (car positions))
+				      (<= end   (cdr positions))))
+				   rectangular-region-positions))))))
+
     ;; If region is active, in Transient Mark mode, operate on region.
     (if backward
 	(when end





^ permalink raw reply related	[flat|nested] 25+ messages in thread

* bug#19829: 25.0.50; query-replace in rectangle regions do not honor boundaries
  2015-02-13  0:54       ` Juri Linkov
@ 2015-02-14  3:59         ` Stefan Monnier
  2015-02-18 18:30           ` Juri Linkov
  0 siblings, 1 reply; 25+ messages in thread
From: Stefan Monnier @ 2015-02-14  3:59 UTC (permalink / raw)
  To: Juri Linkov; +Cc: Bastien, 19829

>> Obviously, this infrastructure is not sufficient for query-replace, so
>> we'll need to add a `region-map-function` or something like that.
> Better would be to add a function that will return a list of positions
> of the rectangular region, i.e. while currently for the contiguous region
> region-beginning/end returns its bounds, for non-contiguous rectangular
> regions we need a list of column bounds.

That would also work, yes.  We could make region-extract-function accept
yet another value of its argument (say `positions') such that instead of
returning the textual content, it just returns a list of
(START . END) bounds.


        Stefan





^ permalink raw reply	[flat|nested] 25+ messages in thread

* bug#19829: 25.0.50; query-replace in rectangle regions do not honor boundaries
  2015-02-14  3:59         ` Stefan Monnier
@ 2015-02-18 18:30           ` Juri Linkov
  2015-02-18 22:56             ` Stefan Monnier
  2015-02-19 14:27             ` bug#19829: 25.0.50; query-replace in rectangle regions do not honor boundaries Bastien
  0 siblings, 2 replies; 25+ messages in thread
From: Juri Linkov @ 2015-02-18 18:30 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: Bastien, 19829

> That would also work, yes.  We could make region-extract-function accept
> yet another value of its argument (say `positions') such that instead of
> returning the textual content, it just returns a list of
> (START . END) bounds.

Now this is ready.  The first part of the patch adds a new argument
`positions' to `region-extract-function', and the second part for
replace.el uses it in `perform-replace':

diff --git a/lisp/simple.el b/lisp/simple.el
index 25293ed..34b8bb4 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -956,11 +956,15 @@ (defcustom delete-active-region t
   :version "24.1")
 
 (defvar region-extract-function
-  (lambda (delete)
+  (lambda (delete &optional positions)
     (when (region-beginning)
-      (if (eq delete 'delete-only)
-          (delete-region (region-beginning) (region-end))
-        (filter-buffer-substring (region-beginning) (region-end) delete))))
+      (cond
+       (positions
+        (list (cons (region-beginning) (region-end))))
+       ((eq delete 'delete-only)
+        (delete-region (region-beginning) (region-end)))
+       (t
+        (filter-buffer-substring (region-beginning) (region-end) delete)))))
   "Function to get the region's content.
 Called with one argument DELETE.
 If DELETE is `delete-only', then only delete the region and the return value
diff --git a/lisp/rect.el b/lisp/rect.el
index c5a5486..7bb017d 100644
--- a/lisp/rect.el
+++ b/lisp/rect.el
@@ -216,6 +216,14 @@ (defun extract-rectangle-line (startcol endcol lines)
 			   (spaces-string endextra))))
     (setcdr lines (cons line (cdr lines)))))
 
+(defun extract-rectangle-position (startcol endcol positions)
+  (let (start end)
+    (move-to-column startcol)
+    (setq start (point))
+    (move-to-column endcol)
+    (setq end (point))
+    (setcdr positions (cons (cons start end) (cdr positions)))))
+
 (defconst spaces-strings
   '["" " " "  " "   " "    " "     " "      " "       " "        "])
 
@@ -257,6 +265,15 @@ (defun extract-rectangle (start end)
     (apply-on-rectangle 'extract-rectangle-line start end lines)
     (nreverse (cdr lines))))
 
+(defun extract-rectangle-positions (start end)
+  "Return the positions of the rectangle with corners at START and END.
+Return it as a list of (START . END) bounds, one for each line of
+the rectangle."
+  (let ((positions (list nil)))
+    (apply-on-rectangle 'extract-rectangle-position
+                        start end positions)
+    (nreverse (cdr positions))))
+
 (defvar killed-rectangle nil
   "Rectangle for `yank-rectangle' to insert.")
 
@@ -680,9 +697,13 @@ (defun rectangle-previous-line (&optional n)
     (rectangle--col-pos col 'point)))
 
 
-(defun rectangle--extract-region (orig &optional delete)
-  (if (not rectangle-mark-mode)
-      (funcall orig delete)
+(defun rectangle--extract-region (orig &optional delete positions)
+  (cond
+   ((not rectangle-mark-mode)
+    (funcall orig delete))
+   (positions
+    (extract-rectangle-positions (region-beginning) (region-end)))
+   (t
     (let* ((strs (funcall (if delete
                               #'delete-extract-rectangle
                             #'extract-rectangle)
@@ -696,7 +717,7 @@ (defun rectangle--extract-region (orig &optional delete)
         (put-text-property 0 (length str) 'yank-handler
                            `(rectangle--insert-for-yank ,strs t)
                            str)
-        str))))
+        str)))))
 
 (defun rectangle--insert-for-yank (strs)
   (push (point) buffer-undo-list)
diff --git a/lisp/emulation/cua-rect.el b/lisp/emulation/cua-rect.el
index ea8b524..a631984 100644
--- a/lisp/emulation/cua-rect.el
+++ b/lisp/emulation/cua-rect.el
@@ -666,6 +666,22 @@ (defun cua--extract-rectangle ()
     	     (setq rect (cons row rect))))))
     (nreverse rect)))
 
+(defun cua--extract-rectangle-positions ()
+  (let (rect)
+    (if (not (cua--rectangle-virtual-edges))
+        (cua--rectangle-operation nil nil nil nil nil ; do not tabify
+          (lambda (s e _l _r)
+             (setq rect (cons (cons s e) rect))))
+      (cua--rectangle-operation nil 1 nil nil nil ; do not tabify
+        (lambda (s e l r _v)
+           (goto-char s)
+           (move-to-column l)
+           (setq s (point))
+           (move-to-column r)
+           (setq e (point))
+           (setq rect (cons (cons s e) rect)))))
+    (nreverse rect)))
+
 (defun cua--insert-rectangle (rect &optional below paste-column line-count)
   ;; Insert rectangle as insert-rectangle, but don't set mark and exit with
   ;; point at either next to top right or below bottom left corner
@@ -1403,10 +1419,14 @@ (defun cua--rectangle-highlight-for-redisplay (orig &rest args)
     ;; already do it elsewhere.
     (funcall redisplay-unhighlight-region-function (nth 3 args))))
 
-(defun cua--rectangle-region-extract (orig &optional delete)
+(defun cua--rectangle-region-extract (orig &optional delete positions)
   (cond
-   ((not cua--rectangle) (funcall orig delete))
-   ((eq delete 'delete-only) (cua--delete-rectangle))
+   ((not cua--rectangle)
+    (funcall orig delete))
+   (positions
+    (cua--extract-rectangle-positions))
+   ((eq delete 'delete-only)
+    (cua--delete-rectangle))
    (t
     (let* ((strs (cua--extract-rectangle))
            (str (mapconcat #'identity strs "\n")))



diff --git a/lisp/replace.el b/lisp/replace.el
index e0636e0..aec348f 100644
--- a/lisp/replace.el
+++ b/lisp/replace.el
@@ -2089,6 +2089,9 @@ (defun perform-replace (from-string replacements
 
          ;; If non-nil, it is marker saying where in the buffer to stop.
          (limit nil)
+         ;; Use local binding in add-function below.
+         (isearch-filter-predicate isearch-filter-predicate)
+         (rectangular-region-positions nil)
 
          ;; Data for the next match.  If a cons, it has the same format as
          ;; (match-data); otherwise it is t if a match is possible at point.
@@ -2101,6 +2104,24 @@ (defun perform-replace (from-string replacements
                       "Query replacing %s with %s: (\\<query-replace-map>\\[help] for help) ")
                      minibuffer-prompt-properties))))
 
+    ;; If rectangle is active, operate on rectangular region.
+    (when (and (boundp 'rectangle-mark-mode) rectangle-mark-mode)
+      (setq rectangular-region-positions
+            (mapcar (lambda (position)
+                      (cons (copy-marker (car position))
+                            (copy-marker (cdr position))))
+                    (funcall region-extract-function nil t)))
+      (add-function :after-while isearch-filter-predicate
+                    (lambda (start end)
+                      (delq nil (mapcar
+                                 (lambda (positions)
+                                   (and
+                                    (>= start (car positions))
+                                    (<= start (cdr positions))
+                                    (>= end   (car positions))
+                                    (<= end   (cdr positions))))
+                                 rectangular-region-positions)))))
+
     ;; If region is active, in Transient Mark mode, operate on region.
     (if backward
 	(when end





^ permalink raw reply related	[flat|nested] 25+ messages in thread

* bug#19829: 25.0.50; query-replace in rectangle regions do not honor boundaries
  2015-02-18 18:30           ` Juri Linkov
@ 2015-02-18 22:56             ` Stefan Monnier
  2015-02-19 19:12               ` Juri Linkov
  2015-02-19 14:27             ` bug#19829: 25.0.50; query-replace in rectangle regions do not honor boundaries Bastien
  1 sibling, 1 reply; 25+ messages in thread
From: Stefan Monnier @ 2015-02-18 22:56 UTC (permalink / raw)
  To: Juri Linkov; +Cc: Bastien, 19829

> +  (lambda (delete &optional positions)

No: additional *value*, not additional *argument*.

> +  (let (start end)
> +    (move-to-column startcol)
> +    (setq start (point))
> +    (move-to-column endcol)
> +    (setq end (point))
> +    (setcdr positions (cons (cons start end) (cdr positions)))))

Aka
     (move-to-column startcol)
     (let ((start (point)))
       (move-to-column endcol)
       (push (cons start (point)) (cdr positions)))

> +    (apply-on-rectangle 'extract-rectangle-position
                          ^^^
                          #'

You could also inline this function so as to avoid the dummy (list
nil) cell.

> +         ;; Use local binding in add-function below.
> +         (isearch-filter-predicate isearch-filter-predicate)
> +         (rectangular-region-positions nil)

replace.el should not know about rectangles and shouldn't check
rectangle-mark-mode.  It should simply always call
region-extract-function to get the various elements that make up the
"region".


        Stefan





^ permalink raw reply	[flat|nested] 25+ messages in thread

* bug#19829: 25.0.50; query-replace in rectangle regions do not honor boundaries
  2015-02-18 18:30           ` Juri Linkov
  2015-02-18 22:56             ` Stefan Monnier
@ 2015-02-19 14:27             ` Bastien
  1 sibling, 0 replies; 25+ messages in thread
From: Bastien @ 2015-02-19 14:27 UTC (permalink / raw)
  To: Juri Linkov; +Cc: 19829

Juri Linkov <juri@linkov.net> writes:

> Now this is ready.

Thanks for your work on this!

Quite an improvement, consistency-wise.

-- 
 Bastien





^ permalink raw reply	[flat|nested] 25+ messages in thread

* bug#19829: 25.0.50; query-replace in rectangle regions do not honor boundaries
  2015-02-18 22:56             ` Stefan Monnier
@ 2015-02-19 19:12               ` Juri Linkov
  2015-02-19 21:29                 ` Stefan Monnier
  0 siblings, 1 reply; 25+ messages in thread
From: Juri Linkov @ 2015-02-19 19:12 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: Bastien, 19829

>> +  (lambda (delete &optional positions)
>
> No: additional *value*, not additional *argument*.

Sorry, I misread your previous message.  Then maybe the argument `delete'
should be renamed to something else, but I have no idea for another name.

>> +  (let (start end)
>> +    (move-to-column startcol)
>> +    (setq start (point))
>> +    (move-to-column endcol)
>> +    (setq end (point))
>> +    (setcdr positions (cons (cons start end) (cdr positions)))))
>
> Aka
>      (move-to-column startcol)
>      (let ((start (point)))
>        (move-to-column endcol)
>        (push (cons start (point)) (cdr positions)))
>
>> +    (apply-on-rectangle 'extract-rectangle-position
>                           ^^^
>                           #'

Done in the new patch.

>> +         ;; Use local binding in add-function below.
>> +         (isearch-filter-predicate isearch-filter-predicate)
>> +         (rectangular-region-positions nil)
>
> replace.el should not know about rectangles and shouldn't check
> rectangle-mark-mode.  It should simply always call
> region-extract-function to get the various elements that make up the
> "region".

This is true generally, but query-replace is a very special command.
It already does many unorthodox things like putting markers on
region boundaries, and then deactivating the mark.  What is more,
it needs to use rectangle boundaries in isearch-filter-predicate,
so lazy-highlight will match only strings it's going to replace.

I propose to start with simpler commands that operate on region,
and add support for rectangular regions to them to see how this
feature develops, and then optimize query-replace based on
this experience.

diff --git a/lisp/simple.el b/lisp/simple.el
index 25293ed..76d84c9 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -958,13 +958,19 @@ (defcustom delete-active-region t
 (defvar region-extract-function
   (lambda (delete)
     (when (region-beginning)
-      (if (eq delete 'delete-only)
-          (delete-region (region-beginning) (region-end))
-        (filter-buffer-substring (region-beginning) (region-end) delete))))
+      (cond
+       ((eq delete 'positions)
+        (list (cons (region-beginning) (region-end))))
+       ((eq delete 'delete-only)
+        (delete-region (region-beginning) (region-end)))
+       (t
+        (filter-buffer-substring (region-beginning) (region-end) delete)))))
   "Function to get the region's content.
 Called with one argument DELETE.
 If DELETE is `delete-only', then only delete the region and the return value
 is undefined.  If DELETE is nil, just return the content as a string.
+If DELETE is `positions', then don't delete, but just return the
+positions of the region as a list of (START . END) boundaries.
 If anything else, delete the region and return its content as a string.")
 
 (defun delete-backward-char (n &optional killflag)
diff --git a/lisp/rect.el b/lisp/rect.el
index c5a5486..271f720 100644
--- a/lisp/rect.el
+++ b/lisp/rect.el
@@ -257,6 +257,19 @@ (defun extract-rectangle (start end)
     (apply-on-rectangle 'extract-rectangle-line start end lines)
     (nreverse (cdr lines))))
 
+(defun extract-rectangle-positions (start end)
+  "Return the positions of the rectangle with corners at START and END.
+Return it as a list of (START . END) boundaries, one for each line of
+the rectangle."
+  (let (positions)
+    (apply-on-rectangle
+     (lambda (startcol endcol)
+       (move-to-column startcol)
+       (push (cons (prog1 (point) (move-to-column endcol)) (point))
+	     positions))
+     start end)
+    (nreverse positions)))
+
 (defvar killed-rectangle nil
   "Rectangle for `yank-rectangle' to insert.")
 
@@ -681,8 +694,12 @@ (defun rectangle-previous-line (&optional n)
 
 
 (defun rectangle--extract-region (orig &optional delete)
-  (if (not rectangle-mark-mode)
-      (funcall orig delete)
+  (cond
+   ((not rectangle-mark-mode)
+    (funcall orig delete))
+   ((eq delete 'positions)
+    (extract-rectangle-positions (region-beginning) (region-end)))
+   (t
     (let* ((strs (funcall (if delete
                               #'delete-extract-rectangle
                             #'extract-rectangle)
@@ -696,7 +713,7 @@ (defun rectangle--extract-region (orig &optional delete)
         (put-text-property 0 (length str) 'yank-handler
                            `(rectangle--insert-for-yank ,strs t)
                            str)
-        str))))
+        str)))))
 
 (defun rectangle--insert-for-yank (strs)
   (push (point) buffer-undo-list)
diff --git a/lisp/emulation/cua-rect.el b/lisp/emulation/cua-rect.el
index ea8b524..044939f 100644
--- a/lisp/emulation/cua-rect.el
+++ b/lisp/emulation/cua-rect.el
@@ -666,6 +666,22 @@ (defun cua--extract-rectangle ()
     	     (setq rect (cons row rect))))))
     (nreverse rect)))
 
+(defun cua--extract-rectangle-positions ()
+  (let (rect)
+    (if (not (cua--rectangle-virtual-edges))
+        (cua--rectangle-operation nil nil nil nil nil ; do not tabify
+          (lambda (s e _l _r)
+             (setq rect (cons (cons s e) rect))))
+      (cua--rectangle-operation nil 1 nil nil nil ; do not tabify
+        (lambda (s e l r _v)
+           (goto-char s)
+           (move-to-column l)
+           (setq s (point))
+           (move-to-column r)
+           (setq e (point))
+           (setq rect (cons (cons s e) rect)))))
+    (nreverse rect)))
+
 (defun cua--insert-rectangle (rect &optional below paste-column line-count)
   ;; Insert rectangle as insert-rectangle, but don't set mark and exit with
   ;; point at either next to top right or below bottom left corner
@@ -1405,8 +1421,12 @@ (defun cua--rectangle-highlight-for-redisplay (orig &rest args)
 
 (defun cua--rectangle-region-extract (orig &optional delete)
   (cond
-   ((not cua--rectangle) (funcall orig delete))
-   ((eq delete 'delete-only) (cua--delete-rectangle))
+   ((not cua--rectangle)
+    (funcall orig delete))
+   ((eq delete 'positions)
+    (cua--extract-rectangle-positions))
+   ((eq delete 'delete-only)
+    (cua--delete-rectangle))
    (t
     (let* ((strs (cua--extract-rectangle))
            (str (mapconcat #'identity strs "\n")))



diff --git a/lisp/replace.el b/lisp/replace.el
index e0636e0..f2fee8c 100644
--- a/lisp/replace.el
+++ b/lisp/replace.el
@@ -2089,6 +2089,9 @@ (defun perform-replace (from-string replacements
 
          ;; If non-nil, it is marker saying where in the buffer to stop.
          (limit nil)
+         ;; Use local binding in add-function below.
+         (isearch-filter-predicate isearch-filter-predicate)
+         (rectangular-region-positions nil)
 
          ;; Data for the next match.  If a cons, it has the same format as
          ;; (match-data); otherwise it is t if a match is possible at point.
@@ -2101,6 +2104,24 @@ (defun perform-replace (from-string replacements
                       "Query replacing %s with %s: (\\<query-replace-map>\\[help] for help) ")
                      minibuffer-prompt-properties))))
 
+    ;; If rectangle is active, operate on rectangular region.
+    (when (and (boundp 'rectangle-mark-mode) rectangle-mark-mode)
+      (setq rectangular-region-positions
+            (mapcar (lambda (position)
+                      (cons (copy-marker (car position))
+                            (copy-marker (cdr position))))
+                    (funcall region-extract-function 'positions)))
+      (add-function :after-while isearch-filter-predicate
+                    (lambda (start end)
+                      (delq nil (mapcar
+                                 (lambda (positions)
+                                   (and
+                                    (>= start (car positions))
+                                    (<= start (cdr positions))
+                                    (>= end   (car positions))
+                                    (<= end   (cdr positions))))
+                                 rectangular-region-positions)))))
+
     ;; If region is active, in Transient Mark mode, operate on region.
     (if backward
 	(when end





^ permalink raw reply related	[flat|nested] 25+ messages in thread

* bug#19829: 25.0.50; query-replace in rectangle regions do not honor boundaries
  2015-02-19 19:12               ` Juri Linkov
@ 2015-02-19 21:29                 ` Stefan Monnier
  2015-02-23 19:19                   ` Juri Linkov
  0 siblings, 1 reply; 25+ messages in thread
From: Stefan Monnier @ 2015-02-19 21:29 UTC (permalink / raw)
  To: Juri Linkov; +Cc: Bastien, 19829

> This is true generally, but query-replace is a very special command.
> It already does many unorthodox things like putting markers on
> region boundaries, and then deactivating the mark.  What is more,
> it needs to use rectangle boundaries in isearch-filter-predicate,
> so lazy-highlight will match only strings it's going to replace.

I don't see how that's relevant: always calling
extract-rectangle-position should simply work (the normal region is just
a degenerate form of a special region, which has only one span), at
least as long as the rectangle case works correctly.


        Stefan





^ permalink raw reply	[flat|nested] 25+ messages in thread

* bug#19829: 25.0.50; query-replace in rectangle regions do not honor boundaries
  2015-02-19 21:29                 ` Stefan Monnier
@ 2015-02-23 19:19                   ` Juri Linkov
  2015-03-11 20:31                     ` Stefan Monnier
  0 siblings, 1 reply; 25+ messages in thread
From: Juri Linkov @ 2015-02-23 19:19 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: Bastien, 19829

>> This is true generally, but query-replace is a very special command.
>> It already does many unorthodox things like putting markers on
>> region boundaries, and then deactivating the mark.  What is more,
>> it needs to use rectangle boundaries in isearch-filter-predicate,
>> so lazy-highlight will match only strings it's going to replace.
>
> I don't see how that's relevant: always calling
> extract-rectangle-position should simply work (the normal region is just
> a degenerate form of a special region, which has only one span), at
> least as long as the rectangle case works correctly.

Rewriting the complex function `perform-replace' to work on several
region chunks is not needed because the most suitable way is to use
`isearch-filter-predicate' for this specific case of search/replace.

For all other region-processing commands it makes sense
to process separate chunks of rectangular regions implicitly.
This is why I suggested to do this for any other command, but
I wonder why no one asked yet about doing this for other commands.





^ permalink raw reply	[flat|nested] 25+ messages in thread

* bug#19829: 25.0.50; query-replace in rectangle regions do not honor boundaries
  2015-02-23 19:19                   ` Juri Linkov
@ 2015-03-11 20:31                     ` Stefan Monnier
  2015-03-12 19:19                       ` Juri Linkov
  2015-06-30 20:42                       ` bug#19829: 25.0.50; Design of commands operating on rectangular regions Juri Linkov
  0 siblings, 2 replies; 25+ messages in thread
From: Stefan Monnier @ 2015-03-11 20:31 UTC (permalink / raw)
  To: Juri Linkov; +Cc: Bastien, 19829

> Rewriting the complex function `perform-replace' to work on several
> region chunks is not needed because the most suitable way is to use
> `isearch-filter-predicate' for this specific case of search/replace.

I don't see how that's relevant: you still should not check
rectangle-mark-mode.

If you want to avoid the isearch-filter-predicate in the "normal" case,
that's OK, but you should do it by checking the value returned by
region-extract-function.


        Stefan





^ permalink raw reply	[flat|nested] 25+ messages in thread

* bug#19829: 25.0.50; query-replace in rectangle regions do not honor boundaries
  2015-03-11 20:31                     ` Stefan Monnier
@ 2015-03-12 19:19                       ` Juri Linkov
  2015-03-13  1:04                         ` Stefan Monnier
  2015-06-30 20:42                       ` bug#19829: 25.0.50; Design of commands operating on rectangular regions Juri Linkov
  1 sibling, 1 reply; 25+ messages in thread
From: Juri Linkov @ 2015-03-12 19:19 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: Bastien, 19829

> If you want to avoid the isearch-filter-predicate in the "normal" case,
> that's OK, but you should do it by checking the value returned by
> region-extract-function.

I agree, so the first step would be to design a "rectangular argument"
for a simpler case in bug#20070.





^ permalink raw reply	[flat|nested] 25+ messages in thread

* bug#19829: 25.0.50; query-replace in rectangle regions do not honor boundaries
  2015-03-12 19:19                       ` Juri Linkov
@ 2015-03-13  1:04                         ` Stefan Monnier
  0 siblings, 0 replies; 25+ messages in thread
From: Stefan Monnier @ 2015-03-13  1:04 UTC (permalink / raw)
  To: Juri Linkov; +Cc: Bastien, 19829

>> If you want to avoid the isearch-filter-predicate in the "normal" case,
>> that's OK, but you should do it by checking the value returned by
>> region-extract-function.

> I agree, so the first step would be to design a "rectangular argument"
> for a simpler case in bug#20070.

I don't understand.


        Stefan





^ permalink raw reply	[flat|nested] 25+ messages in thread

* bug#19829: 25.0.50; Design of commands operating on rectangular regions
  2015-03-11 20:31                     ` Stefan Monnier
  2015-03-12 19:19                       ` Juri Linkov
@ 2015-06-30 20:42                       ` Juri Linkov
  2015-07-01  2:29                         ` Stefan Monnier
  2015-07-07 21:27                         ` Richard Stallman
  1 sibling, 2 replies; 25+ messages in thread
From: Juri Linkov @ 2015-06-30 20:42 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: Bastien, 19829

> If you want to avoid the isearch-filter-predicate in the "normal" case,
> that's OK, but you should do it by checking the value returned by
> region-extract-function.

Now that we have enough evidence of diverse needs for commands operating
on rectangular regions, it's possible to create a general design.

Here is a composite patch with implementation of rectangular regions
based on three different use cases:

1. query-replace on rectangle regions
2. downcase-region on rectangle regions
3. shell-command-on-region on rectangle regions

First is the common part:

diff --git a/lisp/simple.el b/lisp/simple.el
index 4ef45c5..df6aa10 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -958,15 +958,34 @@
 (defvar region-extract-function
   (lambda (delete)
     (when (region-beginning)
-      (if (eq delete 'delete-only)
-          (delete-region (region-beginning) (region-end))
-        (filter-buffer-substring (region-beginning) (region-end) delete))))
+      (cond
+       ((eq delete 'positions)
+        (list (cons (region-beginning) (region-end))))
+       ((eq delete 'delete-only)
+        (delete-region (region-beginning) (region-end)))
+       (t
+        (filter-buffer-substring (region-beginning) (region-end) delete)))))
   "Function to get the region's content.
 Called with one argument DELETE.
 If DELETE is `delete-only', then only delete the region and the return value
 is undefined.  If DELETE is nil, just return the content as a string.
+If DELETE is `positions', then don't delete, but just return the
+positions of the region as a list of (START . END) boundaries.
 If anything else, delete the region and return its content as a string.")
 
+(defvar region-insert-function
+  (lambda (lines)
+    (let ((first t))
+      (while lines
+        (or first
+            (insert ?\n))
+        (insert-for-yank (car lines))
+        (setq lines (cdr lines)
+              first nil))))
+  "Function to insert the region's content.
+Called with one argument LINES.
+Insert the region as a list of lines.")
+
 (defun delete-backward-char (n &optional killflag)
   "Delete the previous N characters (following if N is negative).
 If Transient Mark mode is enabled, the mark is active, and N is 1,
@@ -4950,6 +4989,9 @@ (defun region-active-p ()
        ;; region is active when there's no mark.
        (progn (cl-assert (mark)) t)))
 
+(defun region ()
+  `(region
+    (positions ,@(funcall region-extract-function 'positions))))
 
 (defvar redisplay-unhighlight-region-function
   (lambda (rol) (when (overlayp rol) (delete-overlay rol))))
diff --git a/lisp/rect.el b/lisp/rect.el
index acd3a48..3d3370c 100644
--- a/lisp/rect.el
+++ b/lisp/rect.el
@@ -257,6 +257,19 @@ (defun extract-rectangle (start end)
     (apply-on-rectangle 'extract-rectangle-line start end lines)
     (nreverse (cdr lines))))
 
+(defun extract-rectangle-positions (start end)
+  "Return the positions of the rectangle with corners at START and END.
+Return it as a list of (START . END) boundaries, one for each line of
+the rectangle."
+  (let (positions)
+    (apply-on-rectangle
+     (lambda (startcol endcol)
+       (move-to-column startcol)
+       (push (cons (prog1 (point) (move-to-column endcol)) (point))
+	     positions))
+     start end)
+    (nreverse positions)))
+
 (defvar killed-rectangle nil
   "Rectangle for `yank-rectangle' to insert.")
 
@@ -563,6 +576,8 @@ (add-function :around redisplay-unhighlight-region-function
               #'rectangle--unhighlight-for-redisplay)
 (add-function :around region-extract-function
               #'rectangle--extract-region)
+(add-function :around region-insert-function
+              #'rectangle--insert-region)
 
 (defvar rectangle-mark-mode-map
   (let ((map (make-sparse-keymap)))
@@ -681,8 +696,12 @@
 
 
 (defun rectangle--extract-region (orig &optional delete)
-  (if (not rectangle-mark-mode)
-      (funcall orig delete)
+  (cond
+   ((not rectangle-mark-mode)
+    (funcall orig delete))
+   ((eq delete 'positions)
+    (extract-rectangle-positions (region-beginning) (region-end)))
+   (t
     (let* ((strs (funcall (if delete
                               #'delete-extract-rectangle
                             #'extract-rectangle)
@@ -696,7 +715,14 @@ (defun rectangle--extract-region (orig &optional delete)
         (put-text-property 0 (length str) 'yank-handler
                            `(rectangle--insert-for-yank ,strs t)
                            str)
-        str))))
+        str)))))
+
+(defun rectangle--insert-region (orig strings)
+  (cond
+   ((not rectangle-mark-mode)
+    (funcall orig strings))
+   (t
+    (funcall #'insert-rectangle strings))))
 
 (defun rectangle--insert-for-yank (strs)
   (push (point) buffer-undo-list)
diff --git a/lisp/emulation/cua-rect.el b/lisp/emulation/cua-rect.el
index ea8b524..98b7a3a 100644
--- a/lisp/emulation/cua-rect.el
+++ b/lisp/emulation/cua-rect.el
@@ -666,6 +666,22 @@ (defun cua--extract-rectangle ()
     	     (setq rect (cons row rect))))))
     (nreverse rect)))
 
+(defun cua--extract-rectangle-positions ()
+  (let (rect)
+    (if (not (cua--rectangle-virtual-edges))
+        (cua--rectangle-operation nil nil nil nil nil ; do not tabify
+          (lambda (s e _l _r)
+             (setq rect (cons (cons s e) rect))))
+      (cua--rectangle-operation nil 1 nil nil nil ; do not tabify
+        (lambda (s e l r _v)
+           (goto-char s)
+           (move-to-column l)
+           (setq s (point))
+           (move-to-column r)
+           (setq e (point))
+           (setq rect (cons (cons s e) rect)))))
+    (nreverse rect)))
+
 (defun cua--insert-rectangle (rect &optional below paste-column line-count)
   ;; Insert rectangle as insert-rectangle, but don't set mark and exit with
   ;; point at either next to top right or below bottom left corner
@@ -1394,6 +1410,8 @@ (defun cua--rectangle-post-command ()
 
 (add-function :around region-extract-function
               #'cua--rectangle-region-extract)
+(add-function :around region-insert-function
+              #'cua--insert-rectangle)
 (add-function :around redisplay-highlight-region-function
               #'cua--rectangle-highlight-for-redisplay)
 
@@ -1405,8 +1423,12 @@
 
 (defun cua--rectangle-region-extract (orig &optional delete)
   (cond
-   ((not cua--rectangle) (funcall orig delete))
-   ((eq delete 'delete-only) (cua--delete-rectangle))
+   ((not cua--rectangle)
+    (funcall orig delete))
+   ((eq delete 'positions)
+    (cua--extract-rectangle-positions))
+   ((eq delete 'delete-only)
+    (cua--delete-rectangle))
    (t
     (let* ((strs (cua--extract-rectangle))
            (str (mapconcat #'identity strs "\n")))

1. query-replace on rectangle regions

diff --git a/lisp/replace.el b/lisp/replace.el
index 1bf1343..de6298f 100644
--- a/lisp/replace.el
+++ b/lisp/replace.el
@@ -274,7 +274,7 @@ (defun query-replace-read-args (prompt regexp-flag &optional noerror)
 	  (and current-prefix-arg (not (eq current-prefix-arg '-)))
 	  (and current-prefix-arg (eq current-prefix-arg '-)))))
 
-(defun query-replace (from-string to-string &optional delimited start end backward)
+(defun query-replace (from-string to-string &optional delimited start end backward region)
   "Replace some occurrences of FROM-STRING with TO-STRING.
 As each match is found, the user must type a character saying
 what to do with it.  For directions, type \\[help-command] at that time.
@@ -318,22 +318,21 @@ (defun query-replace (from-string to-string &optional delimited start end backwa
 		   (if current-prefix-arg
 		       (if (eq current-prefix-arg '-) " backward" " word")
 		     "")
-		   (if (and transient-mark-mode mark-active) " in region" ""))
+		   (if (use-region-p) " in region" ""))
 	   nil)))
      (list (nth 0 common) (nth 1 common) (nth 2 common)
 	   ;; These are done separately here
 	   ;; so that command-history will record these expressions
 	   ;; rather than the values they had this time.
-	   (if (and transient-mark-mode mark-active)
-	       (region-beginning))
-	   (if (and transient-mark-mode mark-active)
-	       (region-end))
-	   (nth 3 common))))
-  (perform-replace from-string to-string t nil delimited nil nil start end backward))
+	   (if (use-region-p) (region-beginning))
+	   (if (use-region-p) (region-end))
+	   (nth 3 common)
+	   (if (use-region-p) (region)))))
+  (perform-replace from-string to-string t nil delimited nil nil start end backward region))
 
 (define-key esc-map "%" 'query-replace)
 
-(defun query-replace-regexp (regexp to-string &optional delimited start end backward)
+(defun query-replace-regexp (regexp to-string &optional delimited start end backward region)
   "Replace some things after point matching REGEXP with TO-STRING.
 As each match is found, the user must type a character saying
 what to do with it.  For directions, type \\[help-command] at that time.
@@ -398,18 +397,17 @@ (defun query-replace-regexp (regexp to-string &optional delimited start end back
 		       (if (eq current-prefix-arg '-) " backward" " word")
 		     "")
 		   " regexp"
-		   (if (and transient-mark-mode mark-active) " in region" ""))
+		   (if (use-region-p) " in region" ""))
 	   t)))
      (list (nth 0 common) (nth 1 common) (nth 2 common)
 	   ;; These are done separately here
 	   ;; so that command-history will record these expressions
 	   ;; rather than the values they had this time.
-	   (if (and transient-mark-mode mark-active)
-	       (region-beginning))
-	   (if (and transient-mark-mode mark-active)
-	       (region-end))
-	   (nth 3 common))))
-  (perform-replace regexp to-string t t delimited nil nil start end backward))
+	   (if (use-region-p) (region-beginning))
+	   (if (use-region-p) (region-end))
+	   (nth 3 common)
+	   (if (use-region-p) (region)))))
+  (perform-replace regexp to-string t t delimited nil nil start end backward region))
 
 (define-key esc-map [?\C-%] 'query-replace-regexp)
 
@@ -2054,7 +2052,7 @@
 
 (defun perform-replace (from-string replacements
 		        query-flag regexp-flag delimited-flag
-			&optional repeat-count map start end backward)
+			&optional repeat-count map start end backward region)
   "Subroutine of `query-replace'.  Its complexity handles interactive queries.
 Don't use this in your own program unless you want to query and set the mark
 just as `query-replace' does.  Instead, write a simple loop like this:
@@ -2095,6 +2093,9 @@ (defun perform-replace (from-string replacements
 
          ;; If non-nil, it is marker saying where in the buffer to stop.
          (limit nil)
+         ;; Use local binding in add-function below.
+         (isearch-filter-predicate isearch-filter-predicate)
+         (region-positions (cdr-safe (assq 'positions region)))
 
          ;; Data for the next match.  If a cons, it has the same format as
          ;; (match-data); otherwise it is t if a match is possible at point.
@@ -2107,6 +2108,24 @@ (defun perform-replace (from-string replacements
                       "Query replacing %s with %s: (\\<query-replace-map>\\[help] for help) ")
                      minibuffer-prompt-properties))))
 
+    ;; Unless a single contiguous chunk is selected, operate on multiple chunks.
+    (when (> (length region-positions) 1)
+      (setq region-positions
+            (mapcar (lambda (position)
+                      (cons (copy-marker (car position))
+                            (copy-marker (cdr position))))
+                    region-positions))
+      (add-function :after-while isearch-filter-predicate
+                    (lambda (start end)
+                      (delq nil (mapcar
+                                 (lambda (positions)
+                                   (and
+                                    (>= start (car positions))
+                                    (<= start (cdr positions))
+                                    (>= end   (car positions))
+                                    (<= end   (cdr positions))))
+                                 region-positions)))))
+
     ;; If region is active, in Transient Mark mode, operate on region.
     (if backward
 	(when end

2. downcase-region on rectangle regions

diff --git a/src/casefiddle.c b/src/casefiddle.c
index 8755353..c09d5a8 100644
--- a/src/casefiddle.c
+++ b/src/casefiddle.c
@@ -306,14 +306,30 @@
   return Qnil;
 }
 
-DEFUN ("downcase-region", Fdowncase_region, Sdowncase_region, 2, 2, "r",
+DEFUN ("downcase-region", Fdowncase_region, Sdowncase_region, 2, 3,
+       "(list (region-beginning) (region-end) (region))",
        doc: /* Convert the region to lower case.  In programs, wants two arguments.
 These arguments specify the starting and ending character numbers of
 the region to operate on.  When used as a command, the text between
 point and the mark is operated on.  */)
-  (Lisp_Object beg, Lisp_Object end)
+  (Lisp_Object beg, Lisp_Object end, Lisp_Object region)
 {
-  casify_region (CASE_DOWN, beg, end);
+  Lisp_Object positions = Qnil;
+
+  if (!NILP (region))
+    positions = CDR_SAFE (Fassq (intern ("positions"), region));
+
+  if (positions)
+    {
+      while (CONSP (positions))
+	{
+	  casify_region (CASE_DOWN, XCAR (XCAR (positions)), XCDR (XCAR (positions)));
+	  positions = XCDR (positions);
+	}
+    }
+  else
+    casify_region (CASE_DOWN, beg, end);
+
   return Qnil;
 }
 
3. shell-command-on-region on rectangle regions

diff --git a/lisp/simple.el b/lisp/simple.el
index 4ef45c5..df6aa10 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -3267,7 +3291,8 @@
 
 (defun shell-command-on-region (start end command
 				      &optional output-buffer replace
-				      error-buffer display-error-buffer)
+				      error-buffer display-error-buffer
+				      region)
   "Execute string COMMAND in inferior shell with region as input.
 Normally display output (if any) in temp buffer `*Shell Command Output*';
 Prefix arg means replace the region with it.  Return the exit code of
@@ -3330,7 +3355,8 @@ (defun shell-command-on-region (start end command
 		       current-prefix-arg
 		       current-prefix-arg
 		       shell-command-default-error-buffer
-		       t)))
+		       t
+		       (region))))
   (let ((error-file
 	 (if error-buffer
 	     (make-temp-file
@@ -3339,6 +3365,19 @@ (defun shell-command-on-region (start end command
 				    temporary-file-directory)))
 	   nil))
 	exit-status)
+    ;; Unless a single contiguous chunk is selected, operate on multiple chunks.
+    (if (> (length (cdr-safe (assq 'positions region))) 1)
+        (let ((input (concat (funcall region-extract-function 'delete) "\n"))
+              output)
+          (with-temp-buffer
+            (insert input)
+            (call-process-region (point-min) (point-max)
+                                 shell-file-name t t
+                                 nil shell-command-switch
+                                 command)
+            (setq output (split-string (buffer-string) "\n")))
+          (goto-char start)
+          (funcall region-insert-function output))
     (if (or replace
 	    (and output-buffer
 		 (not (or (bufferp output-buffer) (stringp output-buffer)))))
@@ -3428,7 +3467,7 @@ (defun shell-command-on-region (start end command
 			      exit-status output))))
 	    ;; Don't kill: there might be useful info in the undo-log.
 	    ;; (kill-buffer buffer)
-	    ))))
+	    )))))
 
     (when (and error-file (file-exists-p error-file))
       (if (< 0 (nth 7 (file-attributes error-file)))





^ permalink raw reply related	[flat|nested] 25+ messages in thread

* bug#19829: 25.0.50; Design of commands operating on rectangular regions
  2015-06-30 20:42                       ` bug#19829: 25.0.50; Design of commands operating on rectangular regions Juri Linkov
@ 2015-07-01  2:29                         ` Stefan Monnier
  2015-07-01 22:17                           ` Juri Linkov
  2015-07-07 21:27                         ` Richard Stallman
  1 sibling, 1 reply; 25+ messages in thread
From: Stefan Monnier @ 2015-07-01  2:29 UTC (permalink / raw)
  To: Juri Linkov; +Cc: Bastien, 19829

> Here is a composite patch with implementation of rectangular regions
> based on three different use cases:

Looks pretty good, thanks.

> +(defun region ()
> +  `(region
> +    (positions ,@(funcall region-extract-function 'positions))))

I don't think we want such a short name.  How 'bout `region-boundaries'?
Also, why `(region (positions ,@<foo>)) rather than something simpler
like `(region ,@<foo>)?

> -(defun query-replace (from-string to-string &optional delimited start end backward)
> +(defun query-replace (from-string to-string &optional delimited start end backward region)
[...]
> +	   (if (use-region-p) (region-beginning))
> +	   (if (use-region-p) (region-end))
> +	   (nth 3 common)
> +	   (if (use-region-p) (region)))))

I think we should re-use one of START or END rather than add a REGION argument.


        Stefan





^ permalink raw reply	[flat|nested] 25+ messages in thread

* bug#19829: 25.0.50; Design of commands operating on rectangular regions
  2015-07-01  2:29                         ` Stefan Monnier
@ 2015-07-01 22:17                           ` Juri Linkov
  2015-07-02  3:02                             ` Stefan Monnier
  0 siblings, 1 reply; 25+ messages in thread
From: Juri Linkov @ 2015-07-01 22:17 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: Bastien, 19829

>> +(defun region ()
>> +  `(region
>> +    (positions ,@(funcall region-extract-function 'positions))))
>
> I don't think we want such a short name.  How 'bout `region-boundaries'?
> Also, why `(region (positions ,@<foo>)) rather than something simpler
> like `(region ,@<foo>)?

The goal is to design the interface as general as possible
to be able to define potential future non-rectangular regions.
For instance, a circular region could be defined in the future as:

  (region
   (shape . circle)
   (radius . 42)
   (center . ...)
   ...

Then to distinguish a rectangular region we could add (shape . rectangle)
to the current information:

  (region
   (shape . rectangle)
   (positions . ...)
   ...

>> -(defun query-replace (from-string to-string &optional delimited start end backward)
>> +(defun query-replace (from-string to-string &optional delimited start end backward region)
> [...]
>> +	   (if (use-region-p) (region-beginning))
>> +	   (if (use-region-p) (region-end))
>> +	   (nth 3 common)
>> +	   (if (use-region-p) (region)))))
>
> I think we should re-use one of START or END rather than add a REGION argument.

Stuffing the region information into one of its boundary args would be too ugly.
I guess this is why you designed a cleaner interface by adding a REGION argument
to several commands:

  (defun kill-region (beg end &optional region)
  (defun kill-ring-save (beg end &optional region)
  (defun copy-region-as-kill (beg end &optional region)

with such a clean docstring:

  "The optional argument REGION if non-nil, indicates that we're not just killing
   some text between BEG and END, but we're killing the region.

that will fit other commands like ‘downcase-region’ and ‘shell-command-on-region’
when replacing “killing the region” with a more general “operating on the region”.





^ permalink raw reply	[flat|nested] 25+ messages in thread

* bug#19829: 25.0.50; Design of commands operating on rectangular regions
  2015-07-01 22:17                           ` Juri Linkov
@ 2015-07-02  3:02                             ` Stefan Monnier
  2015-07-02 22:40                               ` Juri Linkov
  0 siblings, 1 reply; 25+ messages in thread
From: Stefan Monnier @ 2015-07-02  3:02 UTC (permalink / raw)
  To: Juri Linkov; +Cc: Bastien, 19829

> The goal is to design the interface as general as possible
> to be able to define potential future non-rectangular regions.
> For instance, a circular region could be defined in the future as:
>
>   (region
>    (shape . circle)
>    (radius . 42)
>    (center . ...)
>    ...
>
> Then to distinguish a rectangular region we could add (shape . rectangle)
> to the current information:
>
>   (region
>    (shape . rectangle)
>    (positions . ...)
>    ...

Hmm... no I don't see it: this info doesn't need to be exposed anywhere,
it can stay internal to the implementation of a circular region.

IOW, either your REGION arg uses a standard format (e.g. a list of
(START . END) boundaries), or it should be just a constant saying "use
things like region-extract-function ".

> Stuffing the region information into one of its boundary args would be
> too ugly.  I guess this is why you designed a cleaner interface by
> adding a REGION argument to several commands:

No, it's definitely not cleaner: I dislike this approach I used.
I think it's hideous when one (optional) arg says "ignore those two
(mandatory) args".

I agree that hijacking one of the two existing args is ugly, but that's
only because it's asymmetric.  If the region had always been passed as
a single arg (e.g., a pair (START . END)), then it would be very natural
to extend it with more cases.

[ Tangentially related side-note: "r" is the only option in `interactive'
  which provides 2 arguments.  IMO this special case should never have
  existed, but of course we now have to live with it.  ]


        Stefan





^ permalink raw reply	[flat|nested] 25+ messages in thread

* bug#19829: 25.0.50; Design of commands operating on rectangular regions
  2015-07-02  3:02                             ` Stefan Monnier
@ 2015-07-02 22:40                               ` Juri Linkov
  2015-07-07 12:20                                 ` Stefan Monnier
  0 siblings, 1 reply; 25+ messages in thread
From: Juri Linkov @ 2015-07-02 22:40 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: Bastien, 19829

> IOW, either your REGION arg uses a standard format (e.g. a list of
> (START . END) boundaries), or it should be just a constant saying "use
> things like region-extract-function ".

Or better to check the value returned by region-extract-function
in `interactive' with:

  (defun region-nonstandard ()
    (> (length (funcall region-extract-function 'positions)) 1))

like the patch below does.

Alternative names for this predicate:

  region-noncontiguous
  region-special

> I agree that hijacking one of the two existing args is ugly, but that's
> only because it's asymmetric.  If the region had always been passed as
> a single arg (e.g., a pair (START . END)), then it would be very natural
> to extend it with more cases.
>
> [ Tangentially related side-note: "r" is the only option in `interactive'
>   which provides 2 arguments.  IMO this special case should never have
>   existed, but of course we now have to live with it.  ]

Then we could replace in `interactive' calls `region-beginning'
with `region-beginning-nonstandard' defined as:

  (defun region-beginning-nonstandard ()
    (or (region-nonstandard) (region-beginning)))

and then in a command operating on the region check if the START arg is
`t' or a number.

But I'm still not sure whether ugly is nicer than hideous,
so this patch doesn't use it yet.

The common part:

diff --git a/lisp/simple.el b/lisp/simple.el
index 4ef45c5..680f89f 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -958,15 +958,34 @@ (defcustom delete-active-region t
 (defvar region-extract-function
   (lambda (delete)
     (when (region-beginning)
-      (if (eq delete 'delete-only)
-          (delete-region (region-beginning) (region-end))
-        (filter-buffer-substring (region-beginning) (region-end) delete))))
+      (cond
+       ((eq delete 'positions)
+        (list (cons (region-beginning) (region-end))))
+       ((eq delete 'delete-only)
+        (delete-region (region-beginning) (region-end)))
+       (t
+        (filter-buffer-substring (region-beginning) (region-end) delete)))))
   "Function to get the region's content.
 Called with one argument DELETE.
 If DELETE is `delete-only', then only delete the region and the return value
 is undefined.  If DELETE is nil, just return the content as a string.
+If DELETE is `positions', then don't delete, but just return the
+positions of the region as a list of (START . END) boundaries.
 If anything else, delete the region and return its content as a string.")
 
+(defvar region-insert-function
+  (lambda (lines)
+    (let ((first t))
+      (while lines
+        (or first
+            (insert ?\n))
+        (insert-for-yank (car lines))
+        (setq lines (cdr lines)
+              first nil))))
+  "Function to insert the region's content.
+Called with one argument LINES.
+Insert the region as a list of lines.")
+
 (defun delete-backward-char (n &optional killflag)
   "Delete the previous N characters (following if N is negative).
 If Transient Mark mode is enabled, the mark is active, and N is 1,
@@ -4950,6 +4989,8 @@ (defun region-active-p ()
        ;; region is active when there's no mark.
        (progn (cl-assert (mark)) t)))
 
+(defun region-nonstandard ()
+  (> (length (funcall region-extract-function 'positions)) 1))
 
 (defvar redisplay-unhighlight-region-function
   (lambda (rol) (when (overlayp rol) (delete-overlay rol))))

1. query-replace on rectangle regions

diff --git a/lisp/replace.el b/lisp/replace.el
index 1bf1343..36ce5a0 100644
--- a/lisp/replace.el
+++ b/lisp/replace.el
@@ -274,7 +274,7 @@ (defun query-replace-read-args (prompt regexp-flag &optional noerror)
 	  (and current-prefix-arg (not (eq current-prefix-arg '-)))
 	  (and current-prefix-arg (eq current-prefix-arg '-)))))
 
-(defun query-replace (from-string to-string &optional delimited start end backward)
+(defun query-replace (from-string to-string &optional delimited start end backward region-nonstandard)
   "Replace some occurrences of FROM-STRING with TO-STRING.
 As each match is found, the user must type a character saying
 what to do with it.  For directions, type \\[help-command] at that time.
@@ -318,22 +318,21 @@ (defun query-replace (from-string to-string &optional delimited start end backwa
 	   ;; These are done separately here
 	   ;; so that command-history will record these expressions
 	   ;; rather than the values they had this time.
-	   (if (and transient-mark-mode mark-active)
-	       (region-beginning))
-	   (if (and transient-mark-mode mark-active)
-	       (region-end))
-	   (nth 3 common))))
-  (perform-replace from-string to-string t nil delimited nil nil start end backward))
+	   (if (use-region-p) (region-beginning))
+	   (if (use-region-p) (region-end))
+	   (nth 3 common)
+	   (if (use-region-p) (region-nonstandard)))))
+  (perform-replace from-string to-string t nil delimited nil nil start end backward region-nonstandard))
 
 (define-key esc-map "%" 'query-replace)
 
-(defun query-replace-regexp (regexp to-string &optional delimited start end backward)
+(defun query-replace-regexp (regexp to-string &optional delimited start end backward region-nonstandard)
   "Replace some things after point matching REGEXP with TO-STRING.
 As each match is found, the user must type a character saying
 what to do with it.  For directions, type \\[help-command] at that time.
@@ -398,18 +397,17 @@ (defun query-replace-regexp (regexp to-string &optional delimited start end back
 	   ;; These are done separately here
 	   ;; so that command-history will record these expressions
 	   ;; rather than the values they had this time.
-	   (if (and transient-mark-mode mark-active)
-	       (region-beginning))
-	   (if (and transient-mark-mode mark-active)
-	       (region-end))
-	   (nth 3 common))))
-  (perform-replace regexp to-string t t delimited nil nil start end backward))
+	   (if (use-region-p) (region-beginning))
+	   (if (use-region-p) (region-end))
+	   (nth 3 common)
+	   (if (use-region-p) (region-nonstandard)))))
+  (perform-replace regexp to-string t t delimited nil nil start end backward region-nonstandard))
 
 (define-key esc-map [?\C-%] 'query-replace-regexp)
 
@@ -2054,7 +2052,7 @@ (defun replace-dehighlight ()
 
 (defun perform-replace (from-string replacements
 		        query-flag regexp-flag delimited-flag
-			&optional repeat-count map start end backward)
+			&optional repeat-count map start end backward region-nonstandard)
   "Subroutine of `query-replace'.  Its complexity handles interactive queries.
 Don't use this in your own program unless you want to query and set the mark
 just as `query-replace' does.  Instead, write a simple loop like this:
@@ -2095,6 +2093,9 @@ (defun perform-replace (from-string replacements
 
          ;; If non-nil, it is marker saying where in the buffer to stop.
          (limit nil)
+         ;; Use local binding in add-function below.
+         (isearch-filter-predicate isearch-filter-predicate)
+         (region-positions nil)
 
          ;; Data for the next match.  If a cons, it has the same format as
          ;; (match-data); otherwise it is t if a match is possible at point.
@@ -2107,6 +2108,24 @@ (defun perform-replace (from-string replacements
                       "Query replacing %s with %s: (\\<query-replace-map>\\[help] for help) ")
                      minibuffer-prompt-properties))))
 
+    ;; Unless a single contiguous chunk is selected, operate on multiple chunks.
+    (when region-nonstandard
+      (setq region-positions
+            (mapcar (lambda (position)
+                      (cons (copy-marker (car position))
+                            (copy-marker (cdr position))))
+                    (funcall region-extract-function 'positions)))
+      (add-function :after-while isearch-filter-predicate
+                    (lambda (start end)
+                      (delq nil (mapcar
+                                 (lambda (positions)
+                                   (and
+                                    (>= start (car positions))
+                                    (<= start (cdr positions))
+                                    (>= end   (car positions))
+                                    (<= end   (cdr positions))))
+                                 region-positions)))))
+
     ;; If region is active, in Transient Mark mode, operate on region.
     (if backward
 	(when end

2. downcase-region on rectangle regions

diff --git a/src/casefiddle.c b/src/casefiddle.c
index 8755353..65f005f 100644
--- a/src/casefiddle.c
+++ b/src/casefiddle.c
@@ -306,14 +306,30 @@
   return Qnil;
 }
 
-DEFUN ("downcase-region", Fdowncase_region, Sdowncase_region, 2, 2, "r",
+DEFUN ("downcase-region", Fdowncase_region, Sdowncase_region, 2, 3,
+       "(list (region-beginning) (region-end) (region-nonstandard))",
        doc: /* Convert the region to lower case.  In programs, wants two arguments.
 These arguments specify the starting and ending character numbers of
 the region to operate on.  When used as a command, the text between
 point and the mark is operated on.  */)
-  (Lisp_Object beg, Lisp_Object end)
+  (Lisp_Object beg, Lisp_Object end, Lisp_Object region_nonstandard)
 {
-  casify_region (CASE_DOWN, beg, end);
+  Lisp_Object positions = Qnil;
+
+  if (!NILP (region_nonstandard))
+    {
+      positions = call1 (Fsymbol_value (intern ("region-extract-function")),
+			 intern ("positions"));
+
+      while (CONSP (positions))
+	{
+	  casify_region (CASE_DOWN, XCAR (XCAR (positions)), XCDR (XCAR (positions)));
+	  positions = XCDR (positions);
+	}
+    }
+  else
+    casify_region (CASE_DOWN, beg, end);
+
   return Qnil;
 }

3. shell-command-on-region on rectangle regions

diff --git a/lisp/simple.el b/lisp/simple.el
index 4ef45c5..680f89f 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -3267,7 +3291,8 @@ (defun shell-command-sentinel (process signal)
 
 (defun shell-command-on-region (start end command
 				      &optional output-buffer replace
-				      error-buffer display-error-buffer)
+				      error-buffer display-error-buffer
+				      region-nonstandard)
   "Execute string COMMAND in inferior shell with region as input.
 Normally display output (if any) in temp buffer `*Shell Command Output*';
 Prefix arg means replace the region with it.  Return the exit code of
@@ -3330,7 +3355,8 @@ (defun shell-command-on-region (start end command
 		       current-prefix-arg
 		       current-prefix-arg
 		       shell-command-default-error-buffer
-		       t)))
+		       t
+		       (region-nonstandard))))
   (let ((error-file
 	 (if error-buffer
 	     (make-temp-file
@@ -3339,6 +3365,19 @@ (defun shell-command-on-region (start end command
 				    temporary-file-directory)))
 	   nil))
 	exit-status)
+    ;; Unless a single contiguous chunk is selected, operate on multiple chunks.
+    (if region-nonstandard
+        (let ((input (concat (funcall region-extract-function 'delete) "\n"))
+              output)
+          (with-temp-buffer
+            (insert input)
+            (call-process-region (point-min) (point-max)
+                                 shell-file-name t t
+                                 nil shell-command-switch
+                                 command)
+            (setq output (split-string (buffer-string) "\n")))
+          (goto-char start)
+          (funcall region-insert-function output))
     (if (or replace
 	    (and output-buffer
 		 (not (or (bufferp output-buffer) (stringp output-buffer)))))
@@ -3428,7 +3467,7 @@ (defun shell-command-on-region (start end command
 			      exit-status output))))
 	    ;; Don't kill: there might be useful info in the undo-log.
 	    ;; (kill-buffer buffer)
-	    ))))
+	    )))))
 
     (when (and error-file (file-exists-p error-file))
       (if (< 0 (nth 7 (file-attributes error-file)))





^ permalink raw reply related	[flat|nested] 25+ messages in thread

* bug#19829: 25.0.50; Design of commands operating on rectangular regions
  2015-07-02 22:40                               ` Juri Linkov
@ 2015-07-07 12:20                                 ` Stefan Monnier
  2015-07-07 22:12                                   ` Juri Linkov
  0 siblings, 1 reply; 25+ messages in thread
From: Stefan Monnier @ 2015-07-07 12:20 UTC (permalink / raw)
  To: Juri Linkov; +Cc: Bastien, 19829

>> IOW, either your REGION arg uses a standard format (e.g. a list of
>> (START . END) boundaries), or it should be just a constant saying "use
>> things like region-extract-function ".
> Or better to check the value returned by region-extract-function
> in `interactive' with:
>   (defun region-nonstandard ()
>     (> (length (funcall region-extract-function 'positions)) 1))
> like the patch below does.

The idea of a constant saying "use the region" is also to distinguish it
from the case where the function is called non-interactively with
boundaries which aren't necessarily related to the current region.

>   region-noncontiguous

I like this name (tho with a final "-p") since it says precisely what
it means.

> Then we could replace in `interactive' calls `region-beginning'
> with `region-beginning-nonstandard' defined as:

No, I'd just replace it with the special constant that says "use things
like region-extract-function".  This constant could be just t or `region'.

> But I'm still not sure whether ugly is nicer than hideous,
> so this patch doesn't use it yet.

I think the first thing is to figure out what is the ideal API, ignoring
backward compatibility.  In this ideal case, I think we'd just want
a single arg which takes a "region descriptor" (along the lines of what
you described earlier, tho its format would be opaque) with methods like
`region-contiguous-p', `region-beginning', `region-end',
`region-chunks', `region-extract', ...

Then we can try and figure how to adapt it to the real world and how to
get from here to there.  But I think it mostly means we'll want to go
from two args (START/END) to just a single arg.  So adding an argument
doesn't seem to be the obvious best choice.


        Stefan





^ permalink raw reply	[flat|nested] 25+ messages in thread

* bug#19829: 25.0.50; Design of commands operating on rectangular regions
  2015-06-30 20:42                       ` bug#19829: 25.0.50; Design of commands operating on rectangular regions Juri Linkov
  2015-07-01  2:29                         ` Stefan Monnier
@ 2015-07-07 21:27                         ` Richard Stallman
  2015-07-07 22:15                           ` Juri Linkov
  1 sibling, 1 reply; 25+ messages in thread
From: Richard Stallman @ 2015-07-07 21:27 UTC (permalink / raw)
  To: Juri Linkov; +Cc: bzg, 19829

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > +(defvar region-insert-function
  > +  (lambda (lines)
  > +    (let ((first t))
  > +      (while lines
  > +        (or first
  > +            (insert ?\n))
  > +        (insert-for-yank (car lines))
  > +        (setq lines (cdr lines)
  > +              first nil))))
  > +  "Function to insert the region's content.
  > +Called with one argument LINES.
  > +Insert the region as a list of lines.")

What is the meaning of a list of lines as the region
if it is NOT a rectangle?  What would that kind of region mean,
and when would it be used?

(I ask because there's a different function for rectangles,
so this function won't be used with a list of lines for rectangles.)

-- 
Dr Richard Stallman
President, Free Software Foundation (gnu.org, fsf.org)
Internet Hall-of-Famer (internethalloffame.org)
Skype: No way! See stallman.org/skype.html.






^ permalink raw reply	[flat|nested] 25+ messages in thread

* bug#19829: 25.0.50; Design of commands operating on rectangular regions
  2015-07-07 12:20                                 ` Stefan Monnier
@ 2015-07-07 22:12                                   ` Juri Linkov
  0 siblings, 0 replies; 25+ messages in thread
From: Juri Linkov @ 2015-07-07 22:12 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: Bastien, 19829

> I think the first thing is to figure out what is the ideal API, ignoring
> backward compatibility.  In this ideal case, I think we'd just want
> a single arg which takes a "region descriptor" (along the lines of what
> you described earlier, tho its format would be opaque) with methods like
> `region-contiguous-p', `region-beginning', `region-end',
> `region-chunks', `region-extract', ...
>
> Then we can try and figure how to adapt it to the real world and how to
> get from here to there.  But I think it mostly means we'll want to go
> from two args (START/END) to just a single arg.  So adding an argument
> doesn't seem to be the obvious best choice.

To achieve the ideal API we need to remove at least one arg END anyway.
But when we'll find a backward-compatible way to remove one arg,
then it would be equally easy to remove two args START and END,
leaving the new arg REGION completely with the new meaning.

OTOH, it would be more difficult to achieve the ideal API while going
thru an intermediate START-OR-REGION arg with the combined meaning
because before changing the meaning of START-OR-REGION to just REGION
requires adapting of function bodies to the new meaning of this arg,
i.e. the choice is between "removing two args START and END" vs.
"removing END and adapting START-OR-REGION".





^ permalink raw reply	[flat|nested] 25+ messages in thread

* bug#19829: 25.0.50; Design of commands operating on rectangular regions
  2015-07-07 21:27                         ` Richard Stallman
@ 2015-07-07 22:15                           ` Juri Linkov
  0 siblings, 0 replies; 25+ messages in thread
From: Juri Linkov @ 2015-07-07 22:15 UTC (permalink / raw)
  To: Richard Stallman; +Cc: bzg, 19829

>   > +(defvar region-insert-function
>   > +  (lambda (lines)
>   > +    (let ((first t))
>   > +      (while lines
>   > +        (or first
>   > +            (insert ?\n))
>   > +        (insert-for-yank (car lines))
>   > +        (setq lines (cdr lines)
>   > +              first nil))))
>   > +  "Function to insert the region's content.
>   > +Called with one argument LINES.
>   > +Insert the region as a list of lines.")
>
> What is the meaning of a list of lines as the region
> if it is NOT a rectangle?  What would that kind of region mean,
> and when would it be used?

Actually this function is not intended for a rectangle.  It's a generic
implementation that works like `insert-for-yank' currently does.

But it uses a list of lines as its argument for compatibility with
the existing `cua--insert-rectangle' and the new proposed
`rectangle--insert-region' (that uses the existing `insert-rectangle')
and that both of them accept a list of lines as their argument.

> (I ask because there's a different function for rectangles,
> so this function won't be used with a list of lines for rectangles.)

The generic `region-insert-function' needs to have the same argument
(i.e. a list of lines) for the case when it's overridden by one of the
rectangle-handling functions.  But its generic implementation inserts
a list of lines the same way as `insert-for-yank' inserts a single
string where lines are separated by newlines.





^ permalink raw reply	[flat|nested] 25+ messages in thread

* bug#19829: 25.0.50; query-replace in rectangle regions do not honor boundaries
  2015-02-10 14:58 bug#19829: 25.0.50; query-replace in rectangle regions do not honor boundaries Bastien
  2015-02-10 23:40 ` Juri Linkov
@ 2015-11-13 23:32 ` Juri Linkov
  1 sibling, 0 replies; 25+ messages in thread
From: Juri Linkov @ 2015-11-13 23:32 UTC (permalink / raw)
  To: 19829-done

This is installed now before the feature freeze.





^ permalink raw reply	[flat|nested] 25+ messages in thread

end of thread, other threads:[~2015-11-13 23:32 UTC | newest]

Thread overview: 25+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-02-10 14:58 bug#19829: 25.0.50; query-replace in rectangle regions do not honor boundaries Bastien
2015-02-10 23:40 ` Juri Linkov
2015-02-12  0:57   ` Juri Linkov
2015-02-12 14:33     ` Stefan Monnier
2015-02-13  0:54       ` Juri Linkov
2015-02-14  3:59         ` Stefan Monnier
2015-02-18 18:30           ` Juri Linkov
2015-02-18 22:56             ` Stefan Monnier
2015-02-19 19:12               ` Juri Linkov
2015-02-19 21:29                 ` Stefan Monnier
2015-02-23 19:19                   ` Juri Linkov
2015-03-11 20:31                     ` Stefan Monnier
2015-03-12 19:19                       ` Juri Linkov
2015-03-13  1:04                         ` Stefan Monnier
2015-06-30 20:42                       ` bug#19829: 25.0.50; Design of commands operating on rectangular regions Juri Linkov
2015-07-01  2:29                         ` Stefan Monnier
2015-07-01 22:17                           ` Juri Linkov
2015-07-02  3:02                             ` Stefan Monnier
2015-07-02 22:40                               ` Juri Linkov
2015-07-07 12:20                                 ` Stefan Monnier
2015-07-07 22:12                                   ` Juri Linkov
2015-07-07 21:27                         ` Richard Stallman
2015-07-07 22:15                           ` Juri Linkov
2015-02-19 14:27             ` bug#19829: 25.0.50; query-replace in rectangle regions do not honor boundaries Bastien
2015-11-13 23:32 ` Juri Linkov

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

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 read-only IMAP folder(s) and NNTP newsgroup(s).