How to Copy Org-Mode Contents Under a Heading - emacs

In org-mode I need to quickly copy content under a heading to the kill ring excluding the heading itself. I found the function org-copy-subtree, but it copies the entire subtree with the heading.
In the following example I would like to copy "Sample text line 1" and "Sample text line 2" when my cursor is somewhere in the "My Sample Heading 1":
* My Sample Heading 1
Sample text line 1
Sample text line 2
* My Sample Heading 2
Sample text line 3
Sample text line 4
Is there a way to do it?

This will return a substring of everything under the current headline. If you want to kill the contents directly, just replace buffer-substring-no-properties with kill-region.
(save-excursion
(org-back-to-heading)
(forward-line)
(unless (= (point) (point-max))
(let ((b (point))
(e (or (outline-next-heading) (point-max))))
(buffer-substring-no-properties b e))))

This might be a bit of a dead question, but here's my solution in case anyone happens upon this and wants to use the org-mark-subtree way of doing it:
(defun my/org-copy-text-under-heading ()
(interactive)
;; Select the current Org subtree
(org-mark-subtree)
;; Deselect the heading line
(next-line 1)
;; Copy the current region
(kill-ring-save
(region-beginning)
(region-end))
;; Deselect the region after copying
(deactivate-mark))
I've just tried to explain that answer a little more fully (as I assume the jy will only work with Evil Mode?).

I use org-mark-subtree then jy.

Related

In Emacs org-mode, how to refile highlighted text under an org heading?

In Emacs org-mode, is there a way to automatically refile highlighted text under an org heading? i.e. to cut the highlighted text and automatically paste it under the org-heading of my choice?
You could call it org-refile-region. Similar to org-refile, but to refile not the entire subtree, but only the highlighted region under any heading in the current document.
UPDATE:
Ideally this functionality would be independent of the org-agenda files used by org-refile, so as to avoid displaying irrelevant headings as possible targets.
Currently this is doable by doing:
1. select text
2. cut
3. other-window
4. navigate to desired target heading
5. paste text
6. other window
The proposed new function would make this much more efficient:
1. select text
2. org-refile-region
3. choose target
The most useful form of this would allow you to choose a target from among any currently open documents. My use case involves selecting text from one buffer and refiling it from among org-headings in another buffer, i.e. moving text from a source document displayed in one window and refiling to targets within the hierarchy of a target document displayed in another window, like so:
If you are using emacs 24.1 or later, you can try
(setq org-refile-active-region-within-subtree t)
which will almost do what you want, but turn the line in which you have highlighted text (the emacs term is "active region") into a headline.
If you want to move the text you have highlighted to another heading, you have to extend org-mode. Fortunately, org provides the tools you need. Here is an example:
(defvar org-refile-region-format "\n%s\n")
(defvar org-refile-region-position 'top
"Where to refile a region. Use 'bottom to refile at the
end of the subtree. ")
(defun org-refile-region (beg end copy)
"Refile the active region.
If no region is active, refile the current paragraph.
With prefix arg C-u, copy region instad of killing it."
(interactive "r\nP")
;; mark paragraph if no region is set
(unless (use-region-p)
(setq beg (save-excursion
(backward-paragraph)
(skip-chars-forward "\n\t ")
(point))
end (save-excursion
(forward-paragraph)
(skip-chars-backward "\n\t ")
(point))))
(let* ((target (save-excursion (org-refile-get-location)))
(file (nth 1 target))
(pos (nth 3 target))
(text (buffer-substring-no-properties beg end)))
(unless copy (kill-region beg end))
(deactivate-mark)
(with-current-buffer (find-file-noselect file)
(save-excursion
(goto-char pos)
(if (eql org-refile-region-position 'bottom)
(org-end-of-subtree)
(org-end-of-meta-data-and-drawers))
(insert (format org-refile-region-format text))))))
We use org-refile-get-location to apply the org refiling mechanism and extract the file and the location. Then we go to that location and insert the copied text. Two variables added for convenience.
org-refile-targets lets you control which files to consider, e.g.:
nil ;; only the current file
'((org-agenda-files :maxlevel . 2)) ;; all agenda files, 1st/2nd level
'((org-files-list :maxlevel . 4)) ;; all agenda and all open files
'((my-org-files-list :maxlevel . 4)) ;; all files returned by `my-org-files-list'
To restrict refiling to the currently open org buffers, define a function
(defun my-org-files-list ()
(mapcar (lambda (buffer)
(buffer-file-name buffer))
(org-buffer-list 'files t)))
And then either
(setq org-refile-targets '((my-org-files-list :maxlevel . 4)))
or use
M-x customize-option <ret> org-refile-targets
select "Function" from the "value menu", and type my-org-files-list

How to hide extra information in Emacs

I want to open an XML file and process it in a special way in Emacs. (Let's say a major mode which is customized to open XML files and process it and present it in a special way)
What I want to do is to hide the extra markup tags in XML and show just the content to the user. Can anyone advice me how I should do this?
`<name id=22> Luke </name>`
=> I just want "Luke" to be shown.
One way to do this would be to use a regular expression to extract the element information from your XML, and then open a temporary buffer for viewing into which you paste that element information. i'm not sure that narrowing is granular enough to hide the markup and display only the element information.
Having said that, an alternative to the temporary buffer approach would be to extract the element information, paste it into the bottom of the file, and then narrow to just that portion of the file so that the source markup is invisible.
The function below does approximately what I have in mind:
(defun show-xml-entities ()
(interactive)
(save-excursion
(let ((old-max (point-max))) ;; save current end of buffer
(goto-char (point-min)) ;; go to beginning of buffer
(while (re-search-forward ">\\([^<>]+\\)<" nil t) ;; search for elements until not found
(when (> (length (match-string-no-properties 1)) 0) ;; if match is non-zero length
(setq temp (point-marker)) ;; save end of match
(goto-char (point-max)) ;; go to end of buffer
;; paste current match to end of buffer
(insert (concat (buffer-substring-no-properties (match-beginning 1) (match-end 1))))
(goto-char (marker-position temp)) ;; return to end of current match
)
)
(narrow-to-region old-max (point-max))) ;; narrow to newly pasted element text
)
)
Logical steps would be
- calculate starting buffer end position (point-max) and sav in a var
- loop through your XML, collecting your entity information and pasting it after the saved position
- when done call (narrow-to-region original-point-max (point-max)). This will hide all the XML so that only your entity text is visible.
M-x sgml-hide-tags RET
see in menu SGML section VIEW some more related commands

Emacs org-mode: textual reference to a file:line

I am using org-mode in Emacs to document my development activities. One of the tasks which I must continuously do by hand is to describe areas of code. Emacs has a very nice Bookmark List: create a bookmark with CTRL-x r m, list them with CTRL-x r l. This is very useful, but is not quite what I need.
Org-mode has the concept of link, and the command org-store-link will record a link to the current position in any file, which can be pasted to the org-file. The problem with this is two-fold:
It is stored as an org-link, and the linked position is not directly visible (just the description).
It is stored in the format file/search, which is not what I want.
I need to have the bookmark in textual form, so that I can copy paste it into org-mode, end edit it if needed, with a simple format like this:
absolute-file-path:line
And this must be obtained from the current point position. The workflow would be as simple as:
Go to the position which I want to record
Call a function: position-to-kill-ring (I would bind this to a keyboard shortcut)
Go to the org-mode buffer.
Yank the position.
Edit if needed (sometimes I need to change absolute paths by relative paths, since my code is in a different location in different machines)
Unfortunately my lisp is non-existent, so I do not know how to do this. Is there a simple solution to my problem?
(defun position-to-kill-ring ()
"Copy to the kill ring a string in the format \"file-name:line-number\"
for the current buffer's file name, and the line number at point."
(interactive)
(kill-new
(format "%s:%d" (buffer-file-name) (save-restriction
(widen) (line-number-at-pos)))))
You want to use the org-create-file-search-functions and org-execute-file-search-functions hooks.
For example, if you need the search you describe for text-mode files, use this:
(add-hook 'org-create-file-search-functions
'(lambda ()
(when (eq major-mode 'text-mode)
(number-to-string (line-number-at-pos)))))
(add-hook 'org-execute-file-search-functions
'(lambda (search-string)
(when (eq major-mode 'text-mode)
(goto-line (string-to-number search-string)))))
Then M-x org-store-link RET will do the right thing (store a line number as the search string) and C-c C-o (i.e. M-x org-open-at-point RET) will open the file and go to this line number.
You can of course check for other modes and/or conditions.
An elisp beginner myself I though of it as a good exercise et voila:
Edit: Rewrote it using the format methode, but I still think not storing it to the kill-ring is less intrusive in my workflow (don't know about you). Also I have added the capability to add column position.
(defvar current-file-reference "" "Global variable to store the current file reference")
(defun store-file-line-and-col ()
"Stores the current file, line and column point is at in a string in format \"file-name:line-number-column-number\". Insert the string using \"insert-file-reference\"."
(interactive)
(setq current-file-reference (format "%s:%d:%d" (buffer-file-name) (line-number-at-pos) (current-column))))
(defun store-file-and-line ()
"Stores the current file and line oint is at in a string in format \"file-name:line-number\". Insert the string using \"insert-file-reference\"."
(interactive)
(setq current-file-reference (format "%s:%d" (buffer-file-name) (line-number-at-pos))))
(defun insert-file-reference ()
"Inserts the value stored for current-file-reference at point."
(interactive)
(if (string= "" current-file-reference)
(message "No current file/line/column set!")
(insert current-file-reference)))
Not tested extensively but working for me. Just hit store-file-and-line or store-file-line-and-col to store current location and insert-file-reference to insert the stored value at point.
BTW, if you want something better than FILE:LINE, you can try to use add-log-current-defun (in add-log.el) which should return the name of the current function.
;; Insert a org link to the function in the next window
(defun insert-org-link-to-func ()
(interactive)
(insert (with-current-buffer (window-buffer (next-window))
(org-make-link-string
(concat "file:" (buffer-file-name)
"::" (number-to-string (line-number-at-pos)))
(which-function)
))))
This func generates link with the function name as the description.
Open two windows, one is the org file and the other is src code.
Then M-x insert-org-link-to-func RET

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)))))))

How do I get Emacs to fill sentences, but not paragraphs?

I've seen at least two recommendations on StackOverflow to insert newlines between sentences when editing LaTeX documents. The reason being that the practice facilitates source control, diffing, and collaborative editing.
I'm basically convinced, but I'm lazy, and I don't want to have to think about it.
So I'm searching for some emacs incantation to handle it for me. Could be a minor mode, could be a set of variables that need to be set.
I think what I don't want is
Soft wrapping of text (say using the longlines and (set long-lines-auto-wrap 't)). This is because I don't want to impose requirements on my collaborators' editors, and I sometimes use other unix tools to examine these files.
I think what I do want is
For fill-paragraph to fill between newlines that look like they mark the end of a sentence.
A solution that works with auto-fill-mode would be a bonus.
That is:
chat chat chat.
A new sentence
with goofed up wrapping that needs to be fixed.
Mumble mumble
Transformed to:
chat chat chat.
A new sentence with goofed up wrapping that needs to be fixed.
Mumble mumble
Your comments and suggestions are appreciated.
Edit: The suggestion by Jouni K. Seppänen pointed me at LaTeX-fill-break-at-separators, which suggests that emacs almost knows how to do this already. Anyway, I'm off to read some code, and will report back. Thanks again.
More general version of the same question: Editor showdown: Maintain newlines at the ends of sentences. Thanks, dreeves.
Here's what I use, which was mostly cribbed from Luca de Alfaro:
(defun fill-sentence ()
(interactive)
(save-excursion
(or (eq (point) (point-max)) (forward-char))
(forward-sentence -1)
(indent-relative t)
(let ((beg (point))
(ix (string-match "LaTeX" mode-name)))
(forward-sentence)
(if (and ix (equal "LaTeX" (substring mode-name ix)))
(LaTeX-fill-region-as-paragraph beg (point))
(fill-region-as-paragraph beg (point))))))
I bind this to M-j with
(global-set-key (kbd "M-j") 'fill-sentence)
The references to "LaTeX" are for AUCTeX support. If you don't use AUCTeX, the let can be simplified to
(let (beg (point))
(forward-sentence)
(fill-region-as-paragraph beg (point)))
I have been meaning to do this forever and I recently found this blog post which worked fairly well for me. So here is (a slightly modified version of) what I have been using for a few days.
(defun auto-fill-by-sentences ()
(if (looking-back (sentence-end))
;; Break at a sentence
(progn
(LaTeX-newline)
t)
;; Fall back to the default
(do-auto-fill)))
(add-hook 'LaTeX-mode-hook (lambda () (setq auto-fill-function 'auto-fill-by-sentences)))
;; Modified from http://pleasefindattached.blogspot.com/2011/12/emacsauctex-sentence-fill-greatly.html
(defadvice LaTeX-fill-region-as-paragraph (around LaTeX-sentence-filling)
"Start each sentence on a new line."
(let ((from (ad-get-arg 0))
(to-marker (set-marker (make-marker) (ad-get-arg 1)))
tmp-end)
(while (< from (marker-position to-marker))
(forward-sentence)
;; might have gone beyond to-marker---use whichever is smaller:
(ad-set-arg 1 (setq tmp-end (min (point) (marker-position to-marker))))
ad-do-it
(ad-set-arg 0 (setq from (point)))
(unless (or (looking-back "^\\s *")
(looking-at "\\s *$"))
(LaTeX-newline)))
(set-marker to-marker nil)))
(ad-activate 'LaTeX-fill-region-as-paragraph)
If you put a comment marker at the end of each sentence, Emacs knows not to move the next line inside the comment:
chat chat chat.%
A new sentence
with goofed up wrapping that needs to be fixed.%
Mumble mumble%
Then M-q fills each sentence separately, at least in AUCTeX 11.85. (If you test this in Emacs, there seems to be a bug where if this is the first paragraph in the buffer and you type M-q, you get an error message. Just put a newline before the text to work around it.)
If you don't want to type the comment characters, you could take LaTeX-fill-paragraph and modify it so that sentence-ending punctuation at end of line works similarly to comments.
(defun wrap-at-sentences ()
"Fills the current paragraph, but starts each sentence on a new line."
(interactive)
(save-excursion
;; Select the entire paragraph.
(mark-paragraph)
;; Move to the start of the paragraph.
(goto-char (region-beginning))
;; Record the location of the end of the paragraph.
(setq end-of-paragraph (region-end))
;; Wrap lines with 'hard' newlines (i.e., real line breaks).
(let ((use-hard-newlines 't))
;; Loop over each sentence in the paragraph.
(while (< (point) end-of-paragraph)
;; Determine the region spanned by the sentence.
(setq start-of-sentence (point))
(forward-sentence)
;; Wrap the sentence with hard newlines.
(fill-region start-of-sentence (point))
;; Delete the whitespace following the period, if any.
(while (char-equal (char-syntax (preceding-char)) ?\s)
(delete-char -1))
;; Insert a newline before the next sentence.
(insert "\n")))))
(global-set-key (kbd "M-q") 'wrap-at-sentences)
May not work in all circumstances, but:
(defun my-fill-sentence ()
"Fill sentence separated by punctuation or blank lines."
(interactive)
(let (start end)
(save-excursion
(re-search-backward "\\(^\\s-*$\\|[.?!]\\)" nil t)
(skip-syntax-forward "^w")
(setq start (point-at-bol)))
(save-excursion
(re-search-forward "\\(^\\s-*$\\|[.?!]\\)" nil t)
(setq end (point-at-eol)))
(save-restriction
(narrow-to-region start end)
(fill-paragraph nil))))
To make it work with auto-fill-mode, add (setq normal-auto-fill-function 'my-fill-sentence) to your LaTeX mode hook (I think).
I am assuming you know elisp.
There are a few approaches you can take:
Hook into auto-fill-mode. There are a lot of hard-coded
conditionals there, so it might not work for you. You can
potentially play with auto-fill-function and see if you have
the hook you need there.
Make a character (probably .) "electric" so that when you press
it, it inserts itself and then calls a function to determine how
to fill the line you're on.
Set an after-change-hook to call a function that determines how
to fill the sentence. This function will be called after every
change to the buffer, so do it efficiently. (This mechanism is
used by font-lock, so don't worry about it too much. It sounds
slow, but really isn't -- people type slowly.)
Once you have hooked in at the right place, you just have to implement
the filling logic. The source for sentence-at-point (from thingatpt) may be
instructive.
Anyway, I've never heard of anyone doing this... but it is definitely possible. Like most things in Emacs, it's just a Simple Matter Of Programming.
If the other answers are too automatic, here's a semiautomatic approach.
It's basically what you would do repeatedly if you were going to manually reformat, but condensed so you can hit a single key repeatedly instead.
;; - go to the end of the line,
;; - do ^d to suck the previous line onto this one,
;; - make sure there's only one space between the now-concatenated
;; lines, and then
;; - jump to the end and hit space so that (with auto-fill-mode)
;; the line nicely rewraps itself:
;; (turn on auto-fill-mode with M-x auto-fill-mode)
(defalias 'fill-sentence
(read-kbd-macro "C-e C-d SPC M-x just- one- space RET C-e SPC <backspace>"))
(define-key global-map [f4] 'fill-sentence) ; or whatever key you like
I like Chris Conway's macro a lot but it only works after you manually line-break each sentence. I'm a lazy guy so I want emacs to do it for me. This morning I finally sat down and looked into the problem. The solution I have now is to hack the built-in macro fill-region-as-paragraph.
After applying the following hack, a new option newline-after-sentence will be set to true. The standard M-q (fill-paragraph) will automatically fill and create line-breaks between sentences. Note that tests are only done with GNU Emacs 23.3.1 — use it at your own risk.
The full macro is long so I won't post it here. The idea is to add the following loops in fill-region-as-paragraph
...
;; Insert a line break after each sentence
(while (< (point) to)
(forward-sentence)
(if (< (point) to) (fill-newline)))
;; This is the actual filling loop.
(goto-char from)
(let (sentbeg sentend)
(while (< (point) to)
(setq sentbeg (point))
(end-of-line)
(setq sentend (point))
(fill-one-line sentbeg sentend justify) ;; original filling loop
(forward-line)))))
...
You can find the full macro in my git repository. Some details are also written in my blog. In case you don't want to read my poor English, you can simply use
$ curl http://fermi.mycloudnas.com/cgit.cgi/fill/plain/hack.el >> ~/.emacs
to append the hack to your ~/.emacs and give it a try. Comments and bug reports are all welcome.
An alternative approach would be to leave your .tex file as is, and use a tool like latexdiff
(described in this StackExchange post) instead of Unix diff. This produces a .tex file with Word-style track changes marks, and handles whitespace correctly so you don't have to worry about where your sentences end.
I wrote the following which loops over a region and inserts newlines. Instead of using forward-sentence which didn't work for me, I use re-search-forward "[.?!][]\"')}]*\\( \\)", which finds all sentences followed only by two spaces (the regexp is a modified sentence-end). The newline is made using newline-and-indent.
(defun fill-sentences-in-paragraph ()
"Put a newline at the end of each sentence in paragraph."
(interactive)
(save-excursion
(mark-paragraph)
(call-interactively 'fill-sentences-in-region)))
(defun fill-sentences-in-region (start end)
"Put a newline at the end of each sentence in region."
(interactive "*r")
(call-interactively 'unfill-region)
(save-excursion
(goto-char start)
(while (re-search-forward "[.?!][]\"')}]*\\( \\)" end t)
(newline-and-indent))))
To be able to fix improperly formatted text such as the example "chat chat chat...", fill-sentences-in-region first calls unfill-region which gets rid of sentence-breaking whitespace:
(defun unfill-region (beg end)
"Unfill the region, joining text paragraphs into a
single logical line. This is useful, e.g., for use
with 'visual-line-mode'."
(interactive "*r")
(let ((fill-column (point-max)))
(fill-region beg end)))
I use visual-line-mode and replace my default paragraph fill M-q to fill-sentences-in-paragraph with (global-set-key "\M-q" 'fill-sentences-in-paragraph).