Test for one long word greater than window-width - emacs

The screenshot below was generated using visual-line-mode. I am seeking to test whether a particular line could not be wrapped at word-end because the entire word exceeded the width of a window.
For example:  if the cursor is anywhere on line number 1, I would like to return t if point-at-bol to point-at-eol is both one long word that cannot be broken and it exceeds the window-width.
The same test should return nil if the cursor is anywhere on line 3.
I tried placing the cursor immediately before and immediately after the \ symbol in the right-hand margin and attempting to identify that character with what-cursor-position but that particular symbol is not reachable with that function. In other words, \ doesn't seem to occupy a (point) in the usual sense of testing a point at window edge.
(source: lawlist.com)

The following function tests if the last word on the line is longer than the window width.
(defun too-long-p ()
"Returns t if last word on the line is longer than the window's
column width."
(save-excursion
(end-of-line)
(> (length (thing-at-point 'word))
(window-total-width))))
And here's a version that addresses the "both" issue you raised, but I suspect the former may be closer to what you want.
(defun too-long-p ()
"Returns t if last word on the line is longer than the window's
column width."
(save-excursion
(beginning-of-line)
(forward-word)
(and (eolp)
(> (length (thing-at-point 'word))
(window-total-width)))))
In response to the comments, try this one (although I can't recall if tabs break lines, so you may need to edit the regexp):
(defun too-long-p ()
"Returns t if last word on the line is longer than the window's
column width."
(save-excursion
(beginning-of-line)
(unless (re-search-forward "[ \t]"
(+ (point-at-bol) (window-total-width)) t)
(> (length (thing-at-point 'line)) (window-total-width)))))

Related

How could I found surrounding characters in select region in Emacs?

My question comes from I expect a function with could convert org-mode table to ditaa diagram. What I try to do is:
find "|" if there's any "-" at left/right/above/below, change it to "+"
find "+" if there's no "|" at left/right/above/below, change it to "-"
Can anyone show me how to search the character above/below or the entire function?
You could use a function like this to check what's on the next line:
(defun get-char-on-next-line (&optional point)
"Return the character one line down from POINT.
If POINT is nil or omitted, use the current position of point."
(save-excursion
(when point
(goto-char point))
(let ((column (current-column))
(line-move-visual nil))
;; next-line preserves the current column if possible
(next-line)
(when (= column (current-column))
(char-after)))))
Replace next with previous for the opposite function.
First, say thank you to #legoscia for the original solution.
When I try the (next-line)/(previous-line) I got some problems like "end of buffer, begin of buffer". Then I searched in elisp manual. It suggests using forward-line. Then I got my solution here:
(defun get-char-below (&optional point)
"Return the character one line down from POINT.
If POINT is nil or omitted, use the current position of point."
(save-excursion
(when point
(goto-char point))
(let ((column (current-column)))
(if (= (forward-line 1) 0)
(if (= column (move-to-column column))
(char-after)
nil)
nil))))

How to show the whole line in the window?

I'm using Emacs 24.2 with a line-wrapping activated.
When I read log files of various simulations which contain messages like: "Error: ...some message...", I perform an incremental search: C-s error RET, C-s, C-s...
I find it very annoying that the highlighted result of the search (the word Error) is displayed at the bottom of the screen, and all the additional wrapped lines can't be seen:
I'd like to add modifications which ensure that the whole line of text will be displayed in the buffer, like this:
I found this question concerning re-centering of the search results. It seems that I could use the same defadvice statements for the search functions, but rather than re-centering the line I need just scroll the screen down by the number of wrapped parts.
How to do this?
You can use the solution on the question you reference, but changing recenter-top-bottom by this highly untested function:
(defun scroll-if-truncated()
(scroll-up
(/ (- (save-excursion
(end-of-line) (point))
(save-excursion
(beginning-of-line) (point)))
(window-body-width))))
After playing a bit with the code according to #juanleon's advice, I ended up with this:
;; Execute after each update in isearch-mode
(setq isearch-update-post-hook 'show-whole-line)
(defun show-whole-line ()
"Scroll such that the whole line (which contains the point) will be visible."
;; If it is the top part which is truncated
(if (not (pos-visible-in-window-p (line-beginning-position)))
(let
((amount
;; the required number of lines to scroll
(ceiling (/
(- (window-start)
(line-beginning-position))
(float (window-body-width))))))
;; don't scroll at all if the search result will be scrolled out
(if (< amount (/
(- (window-end)
(point) )
(float (window-body-width))))
(scroll-down amount)))
;; Else
(if (not (pos-visible-in-window-p (line-end-position)))
(let
((amount
(min
;; the required number of lines to scroll
(ceiling (/
(-
(line-end-position)
(window-end (selected-window) t))
(float (window-body-width))) )
;; however not to scroll out the first line
(/ (- (line-beginning-position) (window-start)) (window-body-width)))))
(scroll-up amount)))))
Few explanations:
Setting defadvice for isearch-forward is not enough - this function is not called again when you add chars to the search string. After a quick review of isearch.el.gz package I decided to advice to isearch-update function. This also eliminates the need of adding a separate advice for isearch-repeat-forward and etc. Later I noticed that there is a predefined hook in isearch-update, therefore no need for defadvice here.
show-whole-line function checks whether the beginning of the current line is visible. If not, it scrolls-down to show the beginning of the line, unless this scrolling will result in hiding the search match itself.
If the beginning of the line is visible, show-whole-line checks whether the end of the line is also visible. If not, it scrolls-up to show the end of the line, unless this scrolling will result in hiding the beginning of the line. I prefer to be able to see the beginning of the line.
This function and a hook work pretty well, but there is one annoying thing about it: the function is called when you initially press C-s (before you typed in any search string). This means that if the point is at a line which has its beginning or end out of the window, a simple invocation of C-s will result in scrolling in some manner.
While not critical at all, I'll be glad to hear suggestions how to remove the above side effect.
You should be able to get the behavior you want using variables scroll-conservatively and scroll-margin, in particular the latter.

'Semantic' movement across a line

Consider the following line of Lisp code:
(some-function 7 8 | 9) ;; some comment. note the extra indentation
The point is placed between '8' and '9'. If I perform (move-beginning-of-line), the point will be placed at the absolute beginning of the line, rather than at '('.
Same for move-end-of-line: I'd find it more desirable for it to place the point at ')' if I perform it once, and at the absolute end of the line if I perform it a second time. Some IDEs behave like that.
I tried to implement this but got stuck, my solution behaves particularly bad near the end of a buffer, and on the minibuffer as well. Is there a library that provides this functionality?
I don't know of any library, but it can be done in a few lines of Elisp.
For the beginning of line part, the bundled functions beginning-of-line-text and back-to-indentation (M-m) move to the beginning of the “interesting” part of the line. back-to-indentation ignores only whitespace whereas beginning-of-line-text skips over the fill prefix (in a programming language, this is typically the comment marker, if in a comment). See Smart home in Emacs for how to flip between the beginning of the actual and logical line.
For the end of line part, the following function implements what you're describing. The function end-of-line-code moves to the end of the line, except for trailing whitespace and an optional trailing comment. The function end-of-line-or-code does this, except that if the point was already at the target position, or if the line only contains whitespace and a comment, the point moves to the end of the actual line.
(defun end-of-line-code ()
(interactive "^")
(save-match-data
(let* ((bolpos (progn (beginning-of-line) (point)))
(eolpos (progn (end-of-line) (point))))
(if (comment-search-backward bolpos t)
(search-backward-regexp comment-start-skip bolpos 'noerror))
(skip-syntax-backward " " bolpos))))
(defun end-of-line-or-code ()
(interactive "^")
(let ((here (point)))
(end-of-line-code)
(if (or (= here (point))
(bolp))
(end-of-line))))
Some suggestions that almost do what you ask:
In lisp code, you can sort-of do what you want, with the sexp movement commands. To get to the beginning of the expression from somewhere in the middle, use backward-up-list, which is bound to M-C-u. In your example, that would bring you to the open parenthesis. To move backwards over individual elements in the list, use backward-sexp, bound to M-C-b; forward-sexp moves the other way, and is bound to M-C-f. From the beginning of an sexp, you can skip to the next with M-C-n; reverse with M-C-p.
None of these commands are actually looking at the physical line you are on, so they'll go back or forward over multiple lines.
Other options include Ace Jump mode, which is a very slick way to quickly navigate to the beginning of any word visible on the screen. That might eliminate your need to use line-specific commands. For quick movement within a line, I usually use M-f and M-b to jump over words. Holding the M key down while tapping on b or f is quick enough that I end up using that by default most of the time.
Edit:
Forgot one other nice command - back-to-indentation, bound to M-m. This will back you up to the first non-whitespace character in a line. You could advice this to behave normally on the first call, and then to back up to the beginning of the line on the second call:
(defadvice back-to-indentation (around back-to-back)
(if (eq last-command this-command)
(beginning-of-line)
ad-do-it))
(ad-activate 'back-to-indentation)
I just wrote these two functions that have the behavior you are looking for.
(defun move-beginning-indent ()
(interactive)
(if (eq last-command this-command)
(beginning-of-line)
(back-to-indentation))
)
(defun move-end-indent ()
(interactive)
(if (eq last-command this-command)
(end-of-line)
(end-of-line)
(search-backward-regexp "\\s)" nil t) ; searches backwards for a
(forward-char 1)) ; closed delimiter such as ) or ]
)
(global-set-key [f7] 'move-beginning-indent)
(global-set-key [f8] 'move-end-indent)
Just try them out, they should behave exactly the way you'd want them to.
I use this:
(defun beginning-of-line-or-text (arg)
"Move to BOL, or if already there, to the first non-whitespace character."
(interactive "p")
(if (bolp)
(beginning-of-line-text arg)
(move-beginning-of-line arg)))
(put 'beginning-of-line-or-text 'CUA 'move)
;; <home> is still bound to move-beginning-of-line
(global-set-key (kbd "C-a") 'beginning-of-line-or-text)
(defun end-of-code-or-line ()
"Move to EOL. If already there, to EOL sans comments.
That is, the end of the code, ignoring any trailing comment
or whitespace. Note this does not handle 2 character
comment starters like // or /*. Such will not be skipped."
(interactive)
(if (not (eolp))
(end-of-line)
(skip-chars-backward " \t")
(let ((pt (point))
(lbp (line-beginning-position))
(comment-start-re (concat (if comment-start
(regexp-quote
(replace-regexp-in-string
"[[:space:]]*" "" comment-start))
"[^[:space:]][[:space:]]*$")
"\\|\\s<"))
(comment-stop-re "\\s>")
(lim))
(when (re-search-backward comment-start-re lbp t)
(setq lim (point))
(if (re-search-forward comment-stop-re (1- pt) t)
(goto-char pt)
(goto-char lim) ; test here ->
(while (looking-back comment-start-re (1- (point)))
(backward-char))
(skip-chars-backward " \t"))))))
(put 'end-of-code-or-line 'CUA 'move)
;; <end> is still bound to end-of-visual-line
(global-set-key (kbd "C-e") 'end-of-code-or-line)

Change mark-paragraph behaviour

How to change default emacs mark-paragraph function behaviour to not select first empty line?
my emacs http://dl.dropbox.com/u/1019877/e2.PNG
I've made Bohzidars upgraded version and it works for first line too.
(global-set-key (kbd "M-h") (lambda ()
(interactive)
(mark-paragraph)
(if (> (line-number-at-pos) 1)
(next-line))
(beginning-of-line)))
thanks guys for the tips.
The currently accepted answer has two disadvantages: 1) doesn't accept arguments and 2) doesn't allow to mark more paragraphs by repeated calls (especially this is very useful). Here is my solution - it is the original mark-paragraph with a next-line command at the end. The condition assures it works also on the first of the file.
Possibly a more economic solution is to use advices, but I don't know how to use them yet :).
(defun rs-mark-paragraph (&optional arg allow-extend)
"The original default mark-paragraph, but doesn't mark the first
empty line. Put point at beginning of this paragraph, mark at
end. The paragraph marked is the one that contains point or
follows point.
With argument ARG, puts mark at end of a following paragraph, so that
the number of paragraphs marked equals ARG.
If ARG is negative, point is put at end of this paragraph, mark is put
at beginning of this or a previous paragraph.
Interactively, if this command is repeated
or (in Transient Mark mode) if the mark is active,
it marks the next ARG paragraphs after the ones already marked."
(interactive "p\np")
(unless arg (setq arg 1))
(when (zerop arg)
(error "Cannot mark zero paragraphs"))
(cond ((and allow-extend
(or (and (eq last-command this-command) (mark t))
(and transient-mark-mode mark-active)))
(set-mark
(save-excursion
(goto-char (mark))
(forward-paragraph arg)
(point))))
(t
(forward-paragraph arg)
(push-mark nil t t)
(backward-paragraph arg)
(if (/= (line-number-at-pos) 1)
(next-line)))))
You cannot change the behaviour of mark-paragraph, but you can easily bind another command to the C-M-h keystroke (to resemble the original M-h):
(global-set-key (kbd "C-M-h") (lambda ()
(interactive)
(mark-paragraph)
(next-line)
(beginning-of-line)))
Something like this should do the trick.
I'm not sure I see a convenient way to do this. mark-paragraph calls forward-paragraph and backward-paragraph to do the bulk of the work, and in the documentation for backward-paragraph, we have "if the first real line of a paragraph is preceded by a blank line, the paragraph starts at that blank line."
The most relevant variables to look at appear to be paragraph-start and paragraph-separate, two regular expressions used inside paragraphs.el to figure out this sort of thing. I'd be leary of changing them though, as they are going to have quite a lot of other effects.
Another option is to write your own function that does something like the following:
(defun dg-mark-paragraph ()
(interactive)
(mark-paragraph)
(goto-char (region-beginning))
(when (= (string-match paragraph-separate (thing-at-point 'line)) 0)
(forward-line)))

How can I kill a rectangle of text in Emacs if the first and last lines are not long enough?

In Emacs, I sometimes want to kill or copy a rectangle of text such as this one:
XX first line
XX second line is longer
XX 3rd line short
I want to copy the three lines without the leading "XX" on every line. However, it is impossible to mark both corners of the required rectangle, because the first and third lines do not reach to the right edge of the rectangle that I'm after. So how would I copy the three lines above without the leading "XX" in emacs?
Start marking the rectangle from the first line and when you are at the end of the 3d line then just type spaces until the line is long enough. That's what I usually do.
After copying you can type M-\ (delete-horizontal-space) to remove the added spaces.
I see two options that jump out.
The first is to use M-x artist-mode,
this will let you move to the position on the first/last line you want.
At which point you cut the rectangle C-x r k, and then paste
it wherever you want. Don't forget to type C-c C-c to exit artist mode.
The second is to just cut all three lines using the regular C-w
and then when you paste, delete the rectangle of XXs at the beginning of the lines.
You can have a look at the cua-selection-mode (M-x cua-selection-mode).
It allows you to do what you want, but only in the graphical emacs (not in the Terminal). The key bindings are a bit different: you start the region with C-RET (instead of C-SPC) and cut/yank the rectangle simply with C-w/C-y (not using the rectangle commands).
You can find an example in this blog.
To permanently enable the mode just add
(cua-selection-mode t)
to your .emacs.
P.S. the full cua-mode will also change further key bindings. It is not necessary to use it.
simple modifications of inbulit defuns. kill-right-rectangle function does what you want.
I am sure there would much better way to do it. Nonetheless it works.
Two points about the following code.
- Since the idea is to get the text upto end of the line, you don't even need to specify the last column. simply mark at first line (in you example point at "f") and go down to third line to "3" call the function. (we only need one column, so don't need to move cursor to any right)
- this doesn't work if the buffer is read only. its just not implemented.
(defun end-column (POINT)
"returns end column"
(save-excursion
(goto-char POINT)
(move-end-of-line 1)
(current-column)))
(defun apply-on-right-rectangle (function start end &rest args)
(let (startcol startpt endcol endpt final-point)
(save-excursion
(goto-char start)
(setq startcol (current-column))
(beginning-of-line)
(setq startpt (point))
(goto-char end)
(setq endcol (current-column))
(forward-line 1)
(setq endpt (point-marker))
;; ensure the start column is the left one.
(if (< endcol startcol)
(let ((col startcol))
(setq startcol endcol endcol col)))
;; start looping over lines
(goto-char startpt)
(while (< (point) endpt)
(setq endcol (end-column (point)))
(apply function startcol endcol args)
(setq final-point (point))
(forward-line 1)))
final-point))
(defun delete-extract-right-rectangle (start end &optional fill)
(let ((lines (list nil)))
(apply-on-right-rectangle 'delete-extract-rectangle-line start end lines fill)
(nreverse (cdr lines))))
(defun kill-right-rectangle (start end &optional fill)
(interactive "r\nP")
(condition-case nil
(setq killed-rectangle (delete-extract-right-rectangle start end fill))
((buffer-read-only text-read-only)
(setq killed-rectangle (extract-rectangle start end))
(if kill-read-only-ok
(progn (message "Read only text copied to kill ring") nil)
(barf-if-buffer-read-only)
(signal 'text-read-only (list (current-buffer)))))))