Emacs Lisp unique window name for split identification and deletion - emacs

I am trying to uniquely identify a window,
so that I can select and delete the window if I press a key over again, though I am having trouble doing this.
(setq split-window-right-toggle-var nil)
(defun split-window-right-toggle ()
(interactive)
(if split-window-right-toggle-var
(progn
(right-split-undo)
(setq split-window-right-toggle-var nil))
(progn
(right-split-do)
(setq split-window-right-toggle-var t))))
(defun right-split-do ()
(interactive)
(split-window-right)
(other-window 1))
(defun right-split-undo ()
(interactive)
(other-window -1)
(delete-window))
The issue with this code is that it heavily depends on which window is active, there for can
change the state of my windows and delete the wrong window, can I uniquely give my window a name then target that window name for deletion ? I am really new at Emacs lisp and would appreciate any help thanks.

You can try out something like this:
(setq window-names (make-hash-table :test 'equal ))
(defun name-window ()
(interactive)
(let ((name (read-input "Name: ")))
(setf (gethash name window-names) (selected-window))))
(defun del-window ()
(interactive)
(let ((name (read-input "Name: ")))
(delete-window (gethash name window-names))))

(selected-window) returns a reference to the current window.
(next-window) returns the next window. Use Emacs' self documenting features
to find out more or refer to the manual.
Here is how I would write your command
(defvar ej-spit-window-saved nil)
(defun ej-split-window-right-toggle ()
"toggle split right"
(interactive)
(setq ej-split-window-saved
(if (and ej-split-window-saved
(frame-visible-p (window-frame ej-split-window-saved)))
(delete-window ej-split-window-saved)
(split-window-right))))
Notes
prefix functions/variables for easier debugging.
it's never too early to document code.

Related

Making Document View in Emacs fit to width of page

I'm trying to use Document View in Emacs to read PDFs, but I can't figure out how to make it behave similarly to the 'fit to width' command many PDF readers have. Is there an internal way to do this?
The following snippet defines a new minor-mode doc-view-autofit-mode, which I have activated below using doc-view-mode-hook. It works for me on Emacs 24.3 on Ubuntu 14.04, even to the point of resizing the zoom when I resize the window!
(There is usually a short resize delay thanks to doc-view-autofit-timer-start, but I'm happy to live with this.)
I take no credit for the solution; I found this code on the emacs-devel mailing list.
(require 'cl)
;;;; Automatic fitting minor mode
(defcustom doc-view-autofit-timer-start 1.0
"Initial value (seconds) for the timer that delays the fitting when
`doc-view-autofit-fit' is called (Which is when a window
configuration change occurs and a document needs to be fitted)."
:type 'number
:group 'doc-view)
(defcustom doc-view-autofit-timer-inc 0.02
"Value to increase (seconds) the timer (see `doc-view-autofit-timer-start')
by, if there is another window configuration change occuring, before
it runs out."
:type 'number
:group 'doc-view)
(defcustom doc-view-autofit-default-fit 'width
"The fitting type initially used when mode is enabled.
Valid values are: width, height, page."
:type 'symbol
:group 'doc-view)
(defvar doc-view-autofit-mode-map
(let ((map (make-sparse-keymap)))
(define-key map (kbd "C-c W") 'doc-view-autofit-width)
(define-key map (kbd "C-c H") 'doc-view-autofit-height)
(define-key map (kbd "C-c P") 'doc-view-autofit-page)
map)
"Keymap used by `doc-view-autofit-mode'.")
(defun doc-view-autofit-set (type)
"Set autofitting to TYPE for current buffer."
(when doc-view-autofit-mode
(setq doc-view-autofit-type type)
(doc-view-autofit-fit)))
(defun doc-view-autofit-width ()
"Set autofitting to width for current buffer."
(interactive) (doc-view-autofit-set 'width))
(defun doc-view-autofit-height ()
"Set autofitting to height for current buffer."
(interactive) (doc-view-autofit-set 'height))
(defun doc-view-autofit-page ()
"Set autofitting to page for current buffer."
(interactive) (doc-view-autofit-set 'page))
(defun doc-view-autofit-fit ()
"Fits the document in the selected window's buffer
delayed with a timer, so multiple calls in succession
don't cause as much overhead."
(lexical-let
((window (selected-window)))
(if (equal doc-view-autofit-timer nil)
(setq doc-view-autofit-timer
(run-with-timer
doc-view-autofit-timer-start nil
(lambda ()
(if (window-live-p window)
(save-selected-window
(select-window window)
(cancel-timer doc-view-autofit-timer)
(setq doc-view-autofit-timer nil)
(cond
((equal 'width doc-view-autofit-type)
(doc-view-fit-width-to-window))
((equal 'height doc-view-autofit-type)
(doc-view-fit-height-to-window))
((equal 'page doc-view-autofit-type)
(doc-view-fit-page-to-window))))))))
(timer-inc-time doc-view-autofit-timer doc-view-autofit-timer-inc))))
(define-minor-mode doc-view-autofit-mode
"Minor mode for automatic (timer based) fitting in DocView."
:lighter " AFit" :keymap doc-view-autofit-mode-map :group 'doc-view
(when doc-view-autofit-mode
(set (make-local-variable 'doc-view-autofit-type)
doc-view-autofit-default-fit)
(set (make-local-variable 'doc-view-autofit-timer) nil)
(add-hook 'window-configuration-change-hook
'doc-view-autofit-fit nil t)
(doc-view-autofit-fit))
(when (not doc-view-autofit-mode)
(remove-hook 'window-configuration-change-hook
'doc-view-autofit-fit t)
(when doc-view-autofit-timer
(cancel-timer doc-view-autofit-timer)
(setq doc-view-autofit-timer nil))
(setq doc-view-autofit-type nil)))
(add-hook 'doc-view-mode-hook 'doc-view-autofit-mode)
It works for me:
(add-hook 'doc-view-mode-hook 'doc-view-fit-width-to-window)
Update: It doesn't work correctly if a conversion (to png or something else) is still ongoing (First opening the document). There is alternative, more reliable way, which handles this special case (it doesn't use hook at all but uses advice):
(defadvice doc-view-display (after fit-width activate)
(doc-view-fit-width-to-window))
The following is a slight modification of the answer by Chris -- it provides compatibility with functions like find-file-other-window -- e.g., when the selected-window is different than the one displaying the *.pdf file.
(defvar last-displayed-doc-view-buffer nil)
(defun get-last-displayed-doc-view-buffer ()
(setq last-displayed-doc-view-buffer (current-buffer)))
(add-hook 'doc-view-mode-hook 'get-last-displayed-doc-view-buffer)
(defun doc-view-autofit-fit ()
"Fits the document in the selected window's buffer
delayed with a timer, so multiple calls in succession
don't cause as much overhead."
(if (null doc-view-autofit-timer)
(setq doc-view-autofit-timer
(run-with-timer doc-view-autofit-timer-start nil (lambda ()
(let* (
(selected-window
(cond
((eq major-mode 'doc-view-mode)
(selected-window))
(t
(get-buffer-window last-displayed-doc-view-buffer))))
(current-buffer
(cond
((eq major-mode 'doc-view-mode)
(current-buffer))
(t
(get-buffer last-displayed-doc-view-buffer))))
(selected-fit
(when (buffer-live-p (get-buffer current-buffer))
(with-current-buffer (get-buffer current-buffer)
doc-view-autofit-type))) )
(when (window-live-p selected-window)
(with-selected-window selected-window
(when doc-view-autofit-timer (cancel-timer doc-view-autofit-timer))
(setq doc-view-autofit-timer nil)
(cond
((eq 'width selected-fit)
(doc-view-fit-width-to-window))
((eq 'height selected-fit)
(doc-view-fit-height-to-window))
((eq 'page selected-fit)
(doc-view-fit-page-to-window)))))))))
(timer-inc-time doc-view-autofit-timer doc-view-autofit-timer-inc)))
And, as noted in my earlier comment to Chris' answer, the following variables need definitions:
(defvar doc-view-autofit-timer nil)
(defvar doc-view-autofit-type nil)
Because the modification above adds a new function to the doc-view-mode-hook to obtain the current-buffer, which is needed for the function doc-view-autofit-fit, it is necessary to ensure that the latter function is appended to the end of the doc-view-mode-hook. So the change looks like this -- i.e., we add a t for the append argument:
(add-hook 'doc-view-mode-hook 'doc-view-autofit-mode t)
Everything else from Chris's answer that has not been superseded by the above modifications remain in effect.
TO DO:
Create a test to examine each page while scrolling to make certain that the view coincides with the autofit-type. Presently, errors occur in page size when dealing with a long *.pdf file.
Just a note: (require 'cl) is out of date. Since emacs-24.3 it should be
(require ‘cl-lib)
See http://www.emacswiki.org/emacs/CommonLispForEmacs

local keymap for emacs outline-minor-mode

I want to set the outline-minor-mode for init.el file and when TAB key is pressed on the lines starting with ; the function outline-toggle-children should be called in order to fold and expand the sub headings.
Below is the code for hook. But it does not work for the "TAB" key binding as expected.
(add-hook 'emacs-lisp-mode-hook
(lambda ()
(if (equal (buffer-name) "init.el")
(progn
(outline-regexp "^;+")
(outline-minor-mode 1)
(local-set-key (kbd "TAB") ; this does not work
(lambda ()
(if (string-match outline-regexp (thing-at-point 'line))
(outline-toggle-children))))))))
I presume that the error you get is wrong-type-argument commandp. This happens because functions bound to keys must be "interactive" functions. You need to add an (interactive) declaration to the function, so that Emacs knows how to invoke the function in response to an event:
(lambda ()
(interactive)
(if (string-match outline-regexp (thing-at-point 'line))
(outline-toggle-children)))

Jump to the first occurrence of symbol in Emacs

I use the excellent highlight-symbol.el to move between different occurrences of the same symbol.
In this screenshot, foo_bar is highlighted, and I can call highlight-symbol-prev to jump to it. Note that this is syntax-aware, so it's smart enough to know that foo_bar_baz is different (something isearch doesn't understand).
I'd really like to be able to jump to the first occurrence of a symbol. This would be brilliant for finding where symbols were imported. How would I go about this?
Something along these lines should do what you want.
(defun goto-first-reference ()
(interactive)
(eval
`(progn
(goto-char (point-min))
(search-forward-regexp
(rx symbol-start ,(thing-at-point 'symbol) symbol-end))
(beginning-of-thing 'symbol))))
(eval-when-compile (require 'cl))
(require 'highlight-symbol)
(defmacro save-mark-ring (&rest body)
"Save mark-ring; execute BODY; restore the old mark-ring."
`(let ((old-mark-ring mark-ring))
,#body
(setq mark-ring old-mark-ring)))
(defun highlight-symbol-jump-to-first ()
"Jump to the first occurrence of the symbol at point."
(interactive)
(push-mark)
(save-mark-ring
(let (earliest-symbol-pos)
(loop do
(highlight-symbol-jump -1)
(setq earliest-symbol-pos (point))
while (< (point) earliest-symbol-pos)))))

Emacs and ansi-term: Elisp iterate through a list of buffers

I'm using the following code, to open ansi-term. I found this here.
(require 'term)
(defun visit-ansi-term ()
"If the current buffer is:
1) a running ansi-term named *ansi-term*, rename it.
2) a stopped ansi-term, kill it and create a new one.
3) a non ansi-term, go to an already running ansi-term
or start a new one while killing a defunt one"
(interactive)
(let ((is-term (string= "term-mode" major-mode))
(is-running (term-check-proc (buffer-name)))
(term-cmd "/usr/local/bin/bash")
(anon-term (get-buffer "*ansi-term*")))
(if is-term
(if is-running
(if (string= "*ansi-term*" (buffer-name))
(call-interactively 'rename-buffer)
(if anon-term
(switch-to-buffer "*ansi-term*")
(ansi-term term-cmd)))
(kill-buffer (buffer-name))
(ansi-term term-cmd))
(if anon-term
(if (term-check-proc "*ansi-term*")
(switch-to-buffer "*ansi-term*")
(kill-buffer "*ansi-term*")
(ansi-term term-cmd))
(ansi-term term-cmd)))))
(global-set-key (kbd "<f2>") 'visit-ansi-term)
Now I want to modify this, such that after renaming a buffer it remembers its name and when I use a keyboard shortcut to iterate through the renamed buffers list.
so if I press [F2] and it finds that ansi-term is running, it asks me if I want to rename it. I rename it to say, BUILD. I would like a function and bind to Say [F3] to iterate thorough the list of ansi-terms opened.
I'm a ELISP illiterate. would be glad it someone pointed be references which might help me doing this.
Thanks.
The following code/binding cycles through all the buffers whose major mode is term-mode:
(global-set-key (kbd "<f3>") 'cycle-ansi-term)
(defun cycle-ansi-term ()
"cycle through buffers whose major mode is term-mode"
(interactive)
(when (string= "term-mode" major-mode)
(bury-buffer))
(let ((buffers (cdr (buffer-list))))
(while buffers
(when (with-current-buffer (car buffers) (string= "term-mode" major-mode))
(switch-to-buffer (car buffers))
(setq buffers nil))
(setq buffers (cdr buffers)))))

Emacs - set mark on edit location

I want emacs to add last edit location to the mark ring, so I can jump back to previous edit locations.
Ideally this would only mark one edit location per line. When I edit another line, the last edit location on that line would be added to the ring, and so forth.
I'm not familiar with Lisp to implement this myself. If anyone knows of a plugin or can kindly provide a solution that would be great! :)
You can install a package goto-last-change which allows you to jump sequentially to the buffer undo positions (last edit locations).
Session.el provides this functionality bound to "C-x C-/" or session-jump-to-last-change.
Session dos it per buffer. I'm unaware of anything that does it globally.
I implement a similar function, by recording 2 file's last edit locations(not per buffer), and cycle them when requested. Somewhat like how eclipse does(but less powerful, only 2 file's are recorded)
emacs-last-edit-location
the code:
;;; record two different file's last change. cycle them
(defvar feng-last-change-pos1 nil)
(defvar feng-last-change-pos2 nil)
(defun feng-swap-last-changes ()
(when feng-last-change-pos2
(let ((tmp feng-last-change-pos2))
(setf feng-last-change-pos2 feng-last-change-pos1
feng-last-change-pos1 tmp))))
(defun feng-goto-last-change ()
(interactive)
(when feng-last-change-pos1
(let* ((buffer (find-file-noselect (car feng-last-change-pos1)))
(win (get-buffer-window buffer)))
(if win
(select-window win)
(switch-to-buffer-other-window buffer))
(goto-char (cdr feng-last-change-pos1))
(feng-swap-last-changes))))
(defun feng-buffer-change-hook (beg end len)
(let ((bfn (buffer-file-name))
(file (car feng-last-change-pos1)))
(when bfn
(if (or (not file) (equal bfn file)) ;; change the same file
(setq feng-last-change-pos1 (cons bfn end))
(progn (setq feng-last-change-pos2 (cons bfn end))
(feng-swap-last-changes))))))
(add-hook 'after-change-functions 'feng-buffer-change-hook)
;;; just quick to reach
(global-set-key (kbd "M-`") 'feng-goto-last-change)