If my current buffer is foo, and I run C-x C-b (aka list-buffers), my Emacs window splits in two, with foo occupying one of the two resulting windows, and a dedicated *Buffer List* buffer occupying the other one. At the end of this operation, foo remains the active buffer, and point remains were it was before C-x C-b was executed.
I want to write an interactive function that displays a multi-page output in a similar way: split window if necessary, bring up a dedicated buffer, leave the active buffer as it was before the function was run.
The best I've managed to do is a function with the following structure:
(defun my-func ()
(interactive)
(let ((this-buffer (current-buffer))
(other-buffer (get-buffer-create "*my-func's Dedicated Buffer*")))
(switch-to-buffer-other-window other-buffer)
(erase-buffer)
(insert (compute-pages-and-pages-of-stuff))
(beginning-of-buffer)
(switch-to-buffer-other-window this-buffer)))
This works, more or less, but I thought that Emacs already had built-in syntax to streamline such code.
IOW, I thought there was a special form analogous to the (fictional) WITH-BUFFER-OTHER-WINDOW in the snippet below:
(defun my-func ()
(interactive)
(let ((other-buffer (get-buffer-create "*my-func's Dedicated Buffer*")))
(WITH-BUFFER-OTHER-WINDOW other-buffer
(erase-buffer)
(insert (compute-pages-and-pages-of-stuff))
(beginning-of-buffer))))
or maybe even
(defun my-func ()
(interactive)
(let ((other-buffer (get-buffer-create "*my-func's Dedicated Buffer*")))
(WITH-BUFFER-OTHER-WINDOW other-buffer
(compute-pages-and-pages-of-stuff))))
I've tried forms like save-excursion and save-current-buffer, but they don't reproduce the desired behavior.
Is there a built-in way to carry out the operation described above?
This is the shortest you can get by leveraging the built-ins display-buffer and with-current-buffer:
(defun my-func ()
(interactive)
(let ((buffer (get-buffer-create "*my-func's Dedicated Buffer*")))
(with-current-buffer buffer
(erase-buffer)
(insert (compute-pages-and-pages-of-stuff))
(goto-char (point-min)))
(display-buffer buffer)))
If you use this pattern so much that it starts annoying you, feel free to define a helper macro:
(defmacro my-setup-and-display-buffer (name &rest body)
(declare (indent 1))
(let ((buffer (make-symbol "buffer")))
`(let ((,buffer (get-buffer-create ,name)))
(with-current-buffer ,buffer
,#body)
(display-buffer ,buffer))))
(my-setup-and-display-buffer "*my-func's Dedicated Buffer*"
(erase-buffer)
(insert (compute-pages-and-pages-of-stuff))
(goto-char (point-min)))
Related
(defun jira-view-git-branch ()
(interactive)
(markdown-mode)
(shell-command (format "./jira-view.sh &")))
So how to make the output buffer to be in markdown mode?
I tried the following
(defun jira-view-git-branch ()
(interactive)
(with-output-to-temp-buffer "*jira*"
(shell-command (format "./jira-view.sh &") "*jira*" "*Messages*")
(pop-to-buffer "*jira*"))
(with-current-buffer "*jira*"
(markdown-mode)))
but got this in *Messages*
error in process filter: read-from-minibuffer: Wrong type argument: markerp, nil
error in process filter: Wrong type argument: markerp, nil
Without knowing what your shell command jira-view.sh does exactly, I find it hard to come up with a good solution for this.
At least, the following should give you some pointers:
(defun jira-md (buffer)
(interactive "Bbuffer name: ")
(let ((b (get-buffer-create buffer)))
(switch-to-buffer b)
(markdown-mode)
(insert (shell-command-to-string "echo '# title'"))))
You can ask for a (possibly not yet existing) buffer when calling this function by having B be the first character in the argument to interactive
Once you have a buffer name, you can switch to that buffer and then set the major mode.
You could also make the setting of major mode optional by first examining if the major mode is not already set to markdown-mode. Something like:
(unless (eq major-mode 'markdown-mode)
(markdown-mode))
In Emacs 25.2, suddenly the variable edebug-trace ceased to exist. When I set it with setq, it has no effect (the trace buffer does not appear). What could have happened and how can I fix it?
In the meanwhile, is there another way to know which function gets called when I click on an org-mode link
You could use trace.el to trace all org functions like so (I suggest not evaluating this until you're ready to click the link).
(mapatoms
(lambda (sym)
(and (fboundp sym)
(string-prefix-p "org-" (symbol-name sym))
(trace-function-foreground sym))))
Afterwards, you can remove the traces with:
M-x untrace-all RET
Edit: We could also convert that into a command ala elp-instrument-package:
(defun my-trace-package (prefix)
"Trace all functions which start with PREFIX.
For example, to trace all ELP functions, do the following:
\\[my-trace-package] RET elp- RET"
(interactive ;; derived from `elp-instrument-package'.
(list (completing-read "Prefix of package to trace: "
obarray 'my-traceable-p)))
(if (zerop (length prefix))
(error "Tracing all Emacs functions would render Emacs unusable"))
(mapc (lambda (name)
(trace-function-foreground (intern name)))
(all-completions prefix obarray 'my-traceable-p))
(message "Use %s to cease tracing."
(substitute-command-keys "\\[untrace-all]")))
(defun my-traceable-p (fun)
"Predicate for `my-trace-package'."
(or (functionp fun) (macrop fun)))
I want to stop using finder in OSX and use dired instead. OSX has a command, "open ", to open any file in the default app from the cli. (Example: "open $the_file"). This works fine with C-! followed by me entering "open " but I'd like to do both those thing with a key combination, say C-0.
How can I create a function that does the equivalent of "C-!" -> "open " in dired when I press C-0 with the cursor over a filepath?
(EDIT: I found a solution, macros!)
I reset lawlist-filename to nil at the end of each example so that it can be used in a variety of other functions, including, but not limited to, dired-read-file-name: dired-read-file-name: pop-up dired mode to read-file-name
EDIT: Rewritten with the help of #phils -- uses let bindings, instead of global variables.
(eval-after-load "dired" '(progn
;; open anything externally with OSX default app -- Wide-Open-Throttle!
(define-key dired-mode-map (kbd "z") (lambda () (interactive)
(let ((lawlist-filename (dired-get-file-for-visit)))
(start-process "default-app" nil "open" lawlist-filename))))
;; open *.pdf file externally with the OSX default *.pdf viewer.
(define-key dired-mode-map (kbd "<SPC>") (lambda () (interactive)
(let ((lawlist-filename (dired-get-file-for-visit)))
(if (equal (file-name-extension lawlist-filename) "pdf")
(start-process "default-pdf-app" nil "open" lawlist-filename)))))
;; open *.pdf file externally using Skim.
(define-key dired-mode-map (kbd "v") (lambda () (interactive)
(let* (
(lawlist-filename (dired-get-file-for-visit))
(skim "/Applications/Skim.app/Contents/MacOS/Skim") )
(if (equal (file-name-extension lawlist-filename) "pdf")
(start-process "pdf-with-skim" nil "open" "-a" skim lawlist-filename)))))
))
This works, but it seems inelegant:
http://www.emacswiki.org/emacs/KeyboardMacros
I used a macro:
(fset 'my_macro
[?! ?o ?p ?e ?n ? return])
I try to write a function based on the code from: Latex, Emacs: automatically open *TeX Help* buffer on error and close it after correction of the error?
I would like to replace latexmk by texi2dvi, but TeX-master-file does not contain the file ending .tex (which seems to be required for texi2dvi). I found out that one can add .tex by using TeX-master-file t. However, I can't make it work (I'm not an elisp programmer). Here is what I tried:
;; texi2dvi
(defun run-texi2dvi ()
(interactive)
(let ((TeX-save-query nil)
(TeX-process-asynchronous nil)
(master-file (expand-file-name (TeX-master-file t)))); append `.tex`
(TeX-save-document "")
(TeX-run-TeX "texi2dvi"
(TeX-command-expand "PDFLATEX='pdflatex -synctex=1' texi2dvi -p %s" 'TeX-master-file)
master-file)
(if (plist-get TeX-error-report-switches (intern master-file))
(TeX-next-error t)
(progn
(demolish-tex-help)
(minibuffer-message "texi2dvi: done.")))))
No clue if there's a better way to do it, but this version should work. Basically, TeX-command-expand was given the function TeX-master-file as a symbol which was called internally, and there it was called without the I-want-the-extension argument. The replacing lambda forces that.
(defun run-texi2dvi ()
(interactive)
(let ((TeX-save-query nil)
(TeX-process-asynchronous nil)
(master-file (expand-file-name (TeX-master-file t)))); append `.tex`
(TeX-save-document "")
(TeX-run-TeX "texi2dvi"
(TeX-command-expand
"PDFLATEX='pdflatex -synctex=1' texi2dvi -p %s"
(lambda (ext-ignored nondir)
(TeX-master-file t nondir)))
master-file)
(if (plist-get TeX-error-report-switches (intern master-file))
(TeX-next-error t)
(progn
(demolish-tex-help)
(minibuffer-message "texi2dvi: done.")))))
See here for a more detailed description of the issue and a simple workaround: https://tex.stackexchange.com/questions/67244/how-to-set-up-texi2dvi-with-synctex-and-error-handling/67384#67384
I have a Lisp (SBCL 1.0.40.0.debian) application (myfitnessdata), which uses the following code to process command line arguments:
(:use :common-lisp)
(:export #:main))
(in-package :myfitnessdata)
(require :sb-posix)
;; snip
(defun main ()
(if (= (length sb-ext:*posix-argv*) 3)
(let ((username (nth 0 sb-ext:*posix-argv*))
(password (nth 1 sb-ext:*posix-argv*))
(path (nth 2 sb-ext:*posix-argv*)))
(scrape (username password path)))
(show-usage)))
I am compiling this application using the following Lisp code:
(load "myfitnessdata.lisp")
(save-lisp-and-die "myfitnessdata.bin" :executable t :toplevel 'myfitnessdata:main)
This produces an executable that I can run. However, the sb-ext:*posix-argv* list is always empty. If I run the following:
./myfitnessdata.bin myusername mypassword /home/me/data
... then all I get is the usage instructions produced by (show-usage).
I think I must be missing something simple again - could someone please let me know how to (save-lisp-and-die) such that the resultant executable takes command line arguments?
The solution, as suggested by the good folks on sbcl-help, is to use a tool like buildapp to compile the app. You can specify an entry point, which is assumed to be a function with one argument. At run-time, that function is called with a list of command-line parameters.
Using buildapp, my main function is now:
(defun main (args)
(if (= (length args) 4)
(let ((username (nth 1 args))
(password (nth 2 args))
(path (nth 3 args)))
(scrape username password path))
(show-usage)))