How to get selected text in Emacs Lisp? - emacs

I need to get selection as a string in my Emacs Lisp function.

Selected text is called region in Emacs universe. See How do I access the contents of the current region in Emacs Lisp?

The accepted answer pointed me to the right answer. I want to leave this piece of code for more ELisp beginners like me. regionp contains the "selection" (known as region in ELisp) as a variable in the ELisp function. The if condition checks if the region is active.
(defun get-selected-text (start end)
(interactive "r")
(if (use-region-p)
(let ((regionp (buffer-substring start end)))
(message regionp))))

Related

Emacs copy region/line and comment at the same time

I am trying to implement the following: duplicate the currently selected region or a line (if there is no selection) and comment out the original region with the help of comment-or-uncomment-region-or-line.
I figured I could use kill-region followed by yank but then my original selection is lost, so I can't comment. If on the other hand I comment first I will get both copies of my region commented out.
The other idea I have (which I think is better because I use evil-mode) is to use evil-yank and then evil-visual-restore to restore the selection so that I can comment it out. But I can't figure what arguments to pass to evil-yank to specify the selected region.
What am I missing here?
The main thing you are missing is function copy-region-as-kill.
(defun copy-and-comment-region (beg end &optional arg)
"Duplicate the region and comment-out the copied text.
See `comment-region' for behavior of a prefix arg."
(interactive "r\nP")
(copy-region-as-kill beg end)
(goto-char end)
(yank)
(comment-region beg end arg))

giving region to search in emacs

Is there a way to provide a region to isearch?
I want to overload isearch so that:
C-s ->
1. isearch as usual if no region is selected, OR
2. isearch with region as to-be-used-for-search string
example: i 'select' the words "no exit", then C-s should search the buffer for "no exit".
In a way this can be done with C-s C-w C-w when the cursor is at the beginning of "no".
I wonder if there is a way to reverse this, so first select (some how) and then use the selection for searching
You may find the commands narrow-to-region and widen useful, do C-hfnarrow-to-regionRET and C-hfwidenRET to know more
UPDATE
Here is some quick and dirty code to do what you want, I have not handled some cases for simplicity but this should give an idea
(add-hook 'isearch-mode-end-hook (lambda ()
(when (buffer-narrowed-p)
(widen))))
(defun my-isearch(&optional start end)
(interactive "r")
(when (region-active-p)
(narrow-to-region start end))
(call-interactively 'isearch-forward-regexp))
UPDATE 2
Try the following function, this should do what you want
(defun my-isearch(&optional start end)
(interactive "r")
(if (region-active-p)
(progn
(let ((string (buffer-substring-no-properties start end)))
(deactivate-mark)
(isearch-resume string nil nil t string nil)))
(call-interactively 'isearch-forward-regexp)))
This is exactly what is available with Isearch+ (isearch+.el). Whether searching is restricted to the active region is controlled by Boolean option isearchp-restrict-to-region-flag.
You can use C-x n (command
isearchp-toggle-region-restriction) during search to toggle this behavior.
A second Boolean option, isearchp-deactivate-region-flag, controls whether the region is to be deactivated during search (e.g., so you can better see the search region).
Both options are true by default (search is restricted to the active region, and the region is deactivated during search).
(For Isearch to be limited to the active region in Info, you must also use library Info+ (info+.el).
UPDATE
Well, it was exactly what you described initially. Your later reply to comments shows that you do not in fact want to search the text in the region; you want to search for the text in the region, elsewhere in the buffer. This does the former, not the latter.

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

Bracket selected text in Emacs

I want to use Emacs for simple text annotation. Is there a command which surrounds a selected region of text with brackets or other characters?
The most structured and flexible way to do this is with autopair. I
would say it has become the canonical solution for inserting paired delimiters
and wrapping content in paired delimiters.
Joao (autopair's author) has also written yasnippet, which is a very
popular templating library in Emacs. yasnippet can be used to wrap
region in arbitrary text.
Both libraries model their behaviour on Textmate.
I don't know if there is a standard emacs command to do this, but this one should do the trick:
(defun surround-brackets ()
"Surround current region with brackets"
(interactive)
(when (use-region-p)
(save-excursion
(let ((beg (region-beginning))
(end (region-end)))
(goto-char end)
(insert "]")
(goto-char beg)
(insert "[")))))
EDIT As noted in the comments, this question proposes the following solution, which is much simpler but requires you to use a key binding ending with [
(global-set-key (kbd "M-[") 'insert-pair)

how to know current buffer have set-mark

is there any way know there is set-mark beginning and where is the start point query in lisp
Use the variable mark-active:
mark-active is a variable defined in `C source code'.
Its value is nil
Local in buffer whole-line-or-region.el; global value is nil
Automatically becomes buffer-local when set in any fashion.
Documentation:
Non-nil means the mark and region are currently active in this buffer.
You might also want to check if mark === point, if it's really a region you're looking for:
(if (and mark-active
(/= (point) (mark)))
If you want to write a function that requires a region be defined, you can use interactive, like so:
(defun my-fn-that-requires-a-region (beg end)
"Some documentation string mentioning BEG and END."
(interactive "r")
(message "%d / %d" beg end))
If called interactively, mark must be set or an error is generated. Called programatically, any two values must be passed in; no validation of the parameters is done.
I'd recommend turning on transient-mark-mode
(setq transient-mark-mode t)
transient-mark-mode will highlight the region between the mark and your current point.
Alternatively, you can press C-x C-x to jump between the current point and the mark to see where the mark is set.