2009-08-13

emacs: combining just-one-space n delete-blank-lines

Deniz Dogan wrote:
; have long wanted to change the behavior of just-one-space to not
; only delete spaces and tab characters, but newline characters as well.
; Attached is the patch for this change.

; I don't think that this is such a controversial modification and I
; believe very few user macros will break. If I'm wrong, let me know!

i share this view.

though, in my experiment, i find that there are often situations where shrinking all whitespaces including EOL is not convenient. Here's a example:

-----------------------------
numRep=0
for couple in findreplace:
c numRep += s.count(couple[0])
outtext=s.replace(couple[0],couple[1])
s=outtext
-----------------------------

where the c is the cursor point.
If you shrink all whitespaces including EOL, then the current line becomes joined with previous line.

what i find more ideal is this:

when the current line contain non-whitespace chars, then shrink just spaces and tabs, but if the current line does not contain non-whitespace chars (it's all white space), then shrink all all spaces, tab, EOL.

the code i've been using is this:

(defun shrink-whitespaces ()
"Remove white spaces around cursor to just one or none.
If current line contains non-white space chars, then shrink any whitespace char surrounding cursor to just one space.
If current line does not contain non-white space chars, then remove blank lines to just one."
(interactive)
(let (
cursor-point
line-has-meat-p ; current line contains non-white space chars
spaceTabNeighbor-p
whitespace-begin whitespace-end
space-or-tab-begin space-or-tab-end
line-begin-pos line-end-pos
)
(save-excursion
;; todo: might consider whitespace as defined by syntax table, and also consider whitespace chars in unicode if syntax table doesn't already considered it.
(setq cursor-point (point))

(setq spaceTabNeighbor-p (if (or (looking-at " \\|\t") (looking-back " \\|\t")) t nil) )
(move-beginning-of-line 1) (setq line-begin-pos (point) )
(move-end-of-line 1) (setq line-end-pos (point) )
;; (re-search-backward "\n$") (setq line-begin-pos (point) )
;; (re-search-forward "\n$") (setq line-end-pos (point) )
(setq line-has-meat-p (if (< 0 (count-matches "[[:graph:]]" line-begin-pos line-end-pos)) t nil) )
(goto-char cursor-point)

(skip-chars-backward "\t ")
(setq space-or-tab-begin (point))

(skip-chars-backward "\t \n")
(setq whitespace-begin (point))

(goto-char cursor-point) (skip-chars-forward "\t ")
(setq space-or-tab-end (point))
(skip-chars-forward "\t \n")
(setq whitespace-end (point))
)


(if line-has-meat-p
(progn
(when spaceTabNeighbor-p
(delete-region space-or-tab-begin space-or-tab-end)
(insert " "))
)

(progn
;; (delete-region whitespace-begin whitespace-end)
;; (insert "\n")
(delete-blank-lines)
)
;; todo: possibly code my own delete-blank-lines here for better efficiency, because delete-blank-lines seems complex.
)
)
)

Xah
--------------------

but in general, considering this thread in whole, i share your view with merging just-one-space with delete-blank-lines, and the behavior be depending on context. Something like a shrink-whitespace-dwim.

I feel there are too many small functions on shrinking white spaces, esp those with a shortcut.
e.g. C-x C-o for delete-blank-lines and just-one-space with M-SPC.

i think that these can be merged into a single dwim version with a single shortcut, because i think most of the time context can correctly guess the desired behavior.

i think this applies to few other emacs editing functions for user convenience. One example i came to is about the 9 or so commands on letter case changing. Some work on word, some on region... with transient-mark-mode on now, the region versions could be merged. The lower case and upper case and cap first versions can also be merged, i think, into one dwim version that just cycles.

• Usability Problems With Emacs's Letter-Case Commands
http://xahlee.org/emacs/modernization_upcase-word.html

Xah

No comments:

Post a Comment