Mostly for my own edification I'm trying to list all of the global variables loaded in the current Emacs session. What I was thinking about doing is producing an HTML file with all of the functions listed. Of course, what would also be useful is the file where the function, var, etc was defined.
Is there anything already built into emacs to help?
L-
Something along these lines should do:
(let ((result '()))
(mapatoms (lambda (x)
(when (boundp x)
(let ((file (ignore-errors
(find-lisp-object-file-name x 'defvar))))
(when file
(push (cons x file) result))))))
result)
Warning: it takes a long time to finish.
Related
Under Linux, eshell-autojump will do case sensitive matching which I just find a nuisance. I've tried to circumvent this by advising eshell/j with a eshell-under-windows-p that always returns t but to my chagrin eshell-under-windows-p invoked in eshell/j is unaffected by cl-letf. I've modified my eshell/j a bit to give me some debug info:
;; Modified eshell/j inside eshell-autojump.el to this
(defun eshell/j (&rest args) ; all but first ignored
"Jump to a directory you often cd to.
This compares the argument with the list of directories you usually jump to.
Without an argument, list the ten most common directories.
With a positive integer argument, list the n most common directories.
Otherwise, call `eshell/cd' with the result."
(setq args (eshell-flatten-list args))
(let ((path (car args))
(candidates (eshell-autojump-candidates))
(case-fold-search (eshell-under-windows-p))
result)
(when (not path)
(setq path 10))
(message "case-fold-search = %S" case-fold-search)
(message "eshell-under-windows-p returns %s from inside eshell/j" (eshell-under-windows-p))
(if (and (integerp path) (> path 0))
(progn
(let ((n (nthcdr (1- path) candidates)))
(when n
(setcdr n nil)))
(eshell-lisp-command (mapconcat 'identity candidates "\n")))
(while (and candidates (not result))
(if (string-match path (car candidates))
(setq result (car candidates))
(setq candidates (cdr candidates))))
(eshell/cd result))))
My init.el adds the advice to attempt to make eshell/j caseless by trying to trick it to think we are on Windows:
;; Added to init.el
(require 'eshell-autojump)
(advice-add 'eshell/j :around
(lambda (orig-fun &rest xs)
(cl-letf (((symbol-function 'eshell-under-windows-p) (lambda () t)))
(progn (message "eshell-under-windows-p returns %s from lambda" (eshell-under-windows-p)) (apply orig-fun xs)))))
But all I get in Messages buffer when I try to jump in eshell is:
;; I get in *Messages*
eshell-under-windows-p returns t from lambda
case-fold-search = nil
eshell-under-windows-p returns nil from inside eshell/j
My rookie knowledge of elisp is not enough to wrestle with probable scoping issues here. Can anyone decode why eshell-under-window-p is unaffected when called from eshell/j here?
I've found the answer. cl-letf does not work for byte compiled functions. As eshell-autojump is a package it gets byte compiled upon installation and cl-letf cannot be used to modify it's internal behavior. I had to resort to redefining the eshell/j which is a suboptimal solution.
Common Lisp built-in functions are probably implemented in C. But I imagine macros are implemented in lisp (sorry if I'm wrong about any of two sentences). Is there any way (through some function or some macro) to see the implementations of built-in macros in Common Lisp? I'm using CLisp.
The ability to inspect function and macro definitions is a feature of your development environment. These days it is typical to use SLIME or SLY with emacs as the basis of a Lisp development environment. I personally use SLIME, but I have heard good things about SLY, too.
In SLIME you can invoke slime-edit-definition (either by keying M-x slime-edit-definition or by using the keybinding M-.) to visit a definition for the symbol under the cursor in a source file. This works both when editing in a source file, or from the REPL. This feature is extremely useful when you want to inspect some library code you are working with, but you can also view a lot of built-in definitions this way. You can even jump to a new definition from a new symbol found in whatever definition you are currently inspecting.
After you are done looking at a definition, you can use M-x slime-pop-find-definition-stack, or the easier to remember keybinding M-, (M-* will also work), to back out through the previously viewed definitions, eventually returning to your starting point.
Here is an example, in SBCL:
CL-USER> with-open-file[press M-.]
(Note that the "[press M-.]" above is not typed, but only meant to remind what action is taken here). With the cursor on or right after the symbol with-open-file, press M-. to see the definition:
(sb-xc:defmacro with-open-file ((stream filespec &rest options)
&body body)
(multiple-value-bind (forms decls) (parse-body body nil)
(let ((abortp (gensym)))
`(let ((,stream (open ,filespec ,#options))
(,abortp t))
,#decls
(unwind-protect
(multiple-value-prog1
(progn ,#forms)
(setq ,abortp nil))
(when ,stream
(close ,stream :abort ,abortp)))))))
This time after keying M-. SLIME gives a choice of definitions to view:
CL-USER> and[press M-.]
Displayed in an emacs buffer:
/path-to-source/sbcl-2.0.4/src/code/macros.lisp
(DEFMACRO AND)
/path-to-source/sbcl-2.0.4/src/pcl/ctypes.lisp
(DEFINE-METHOD-COMBINATION AND)
We want to see the macro definition, so move the cursor to the line showing (DEFMACRO AND), and the following definition is displayed:
;; AND and OR are defined in terms of IF.
(sb-xc:defmacro and (&rest forms)
(named-let expand-forms ((nested nil) (forms forms) (ignore-last nil))
(cond ((endp forms) t)
((endp (rest forms))
(let ((car (car forms)))
(cond (nested
car)
(t
;; Preserve non-toplevelness of the form!
`(the t ,car)))))
((and ignore-last
(endp (cddr forms)))
(car forms))
;; Better code that way, since the result will only have two
;; values, NIL or the last form, and the precedeing tests
;; will only be used for jumps
((and (not nested) (cddr forms))
`(if ,(expand-forms t forms t)
,#(last forms)))
(t
`(if ,(first forms)
,(expand-forms t (rest forms) ignore-last))))))
There is more stuff here, since you are now actually in the source file that contains the definition for and; if you scroll down a bit you can also find the definition for or.
A lot of SBCL functions are written in Lisp; SBCL has a very high-quality compiler, so a lot of stuff that you might otherwise expect to be written in C can be written in Lisp without loss of performance. Here is the definition for the function list-length:
CL-USER> list-length[press M-.]
(defun list-length (list)
"Return the length of the given List, or Nil if the List is circular."
(do ((n 0 (+ n 2))
(y list (cddr y))
(z list (cdr z)))
(())
(declare (type fixnum n)
(type list y z))
(when (endp y) (return n))
(when (endp (cdr y)) (return (+ n 1)))
(when (and (eq y z) (> n 0)) (return nil))))
The same thing can be done when using CLISP with SLIME. Here is with-open-file as defined in CLISP:
CL-USER> with-open-file[press M-.]
(defmacro with-open-file ((stream &rest options) &body body)
(multiple-value-bind (body-rest declarations) (SYSTEM::PARSE-BODY body)
`(LET ((,stream (OPEN ,#options)))
(DECLARE (READ-ONLY ,stream) ,#declarations)
(UNWIND-PROTECT
(MULTIPLE-VALUE-PROG1
(PROGN ,#body-rest)
;; Why do we do a first CLOSE invocation inside the protected form?
;; For reliability: Because the stream may be a buffered file stream,
;; therefore (CLOSE ,stream) may produce a disk-full error while
;; writing the last block of the file. In this case, we need to erase
;; the file again, through a (CLOSE ,stream :ABORT T) invocation.
(WHEN ,stream (CLOSE ,stream)))
(WHEN ,stream (CLOSE ,stream :ABORT T))))))
But, many CLISP functions are written in C, and those definitions are not available to inspect in the same way as before:
CL-USER> list-length[press M-.]
No known definition for: list-length (in COMMON-LISP-USER)
In Emacs, I want to vary the values of my environment variables in different buffers.
My emacs environment depends on environment variables (flymake, compile etc), however I want to be able to be able to have multiple projects open at once in one emacs session but these projects might have conflicting environments.
For example something like different INCLUDE_PATH environment variables for flymake.
You can do this by making process-environment buffer-local:
(defun setup-some-mode-env ()
(make-local-variable 'process-environment)
;; inspect buffer-file-name and add stuff to process-environment as necessary
...)
(add-hook 'some-major-mode 'setup-some-mode-env)
A more elaborate example is this code that imports the Guile environment setup created by an external script. The script is designed to be "sourced" in the shell, but here its result gets imported into a single Emacs buffer:
(defun my-guile-setup ()
(make-local-variable 'process-environment)
(with-temp-buffer
(call-process "bash" nil t nil "-c"
"source ~/work/guileenv; env | egrep 'GUILE|LD_LIBRARY_PATH'")
(goto-char (point-min))
(while (not (eobp))
(setq process-environment
(cons (buffer-substring (point) (line-end-position))
process-environment))
(forward-line 1))))
(add-hook 'guile-hook 'my-guile-setup)
I put the following in .dir-locals.el at the root of the tree where I want to define some environment vars:
;; variables local to this directory and its children
((nil . ((eval . (setenv "SOME_VARIABLE" "TRUE")))))
This will warn the first time you open a file in that directory tree. After you accept, the given environment var will be defined for each buffer you open there.
One solution would be to temporary change the environment when you spawn an external command. The command will inherit the current environment. Remember that Emacs is a single-treaded application, so we don't have to worry about race conditions etc.
You can pick one of two ways of doing this:
1) Write you own functions like my-compile that changes the environment temporarily and calls the normal compile command.
2) Modify the low-level process functions and ensure that they modify the environment accordingly. Typically, you can do this with defadvice.
It may be possible to use dynamic binding for those variables.
Dynamic binding and Dynamic scoping are a bit hard to explain, for explanations see http://www.emacswiki.org/emacs/DynamicBindingVsLexicalBinding and
http://en.wikipedia.org/wiki/Scope_(computer_science)#Dynamic_scoping.
Here is an example where I create a local process-environment without necessarily making it buffer-local. The advantage is that the settings only affect the running process and they disappear once the process ends. In this example, I set the timzezone environmental variable and call the function with (funcall my-start-process ....) and everything else is just like start-process in terms of arguments and so forth.
(let* ((my-start-process
(lambda (name buffer program &rest program-args)
(unless (fboundp 'make-process)
(error "Emacs was compiled without subprocess support"))
(let* (
(temp (mapcar 'concat process-environment))
(newenv
(cond
((equal (car (cdr (current-time-zone))) "PDT")
(setenv-internal temp "TZ" "UTC+7" t))
((equal (car (cdr (current-time-zone))) "PST")
(setenv-internal temp "TZ" "UTC+8" t))))
(process-environment (or newenv temp)))
(apply #'make-process
(append (list :name name :buffer buffer)
(when program
(list :command (cons program program-args))))))))
(proc (funcall my-start-process ...))))
I would like to recursively walk down the directory structure from a particular point and call copyright-update-directory at each level.
Is there a function included with Emacs 24 that would help with this? For example something like:
(recursive-directory-walk "~/src/foo" '(copyright-update-directory))
If no such function exists, some pointers on getting started implementing this (or a working implementation) would be great.
The f.el library (github) on MELPA contains functions for filesystem traversal.
(mapc 'copyright-update-directory (f-directories "~/path" nil t))
This will descend the directory hierarchy recursively. See the documentation for f-directories.
Not sure if exists, but not very hard to write your own.
(defun folder-dirs (folder)
(delete-if-not 'file-directory-p
(mapcar (lambda(arg) (file-name-as-directory (concat (file-name-as-directory folder) arg)))
(delete-if (lambda (arg) (or (string= ".." arg) (string= "." arg)))
(directory-files folder)))))
(defun recursively-run-on-every-dir (fn folder)
"FN - function, taking one argument;
FOLDER - initial forder"
(funcall fn folder)
(mapc (lambda(arg) (recursively-run-on-every-dir fn arg))
(folder-dirs folder))
nil)
;; use your function instead of print
(recursively-run-on-every-dir 'print "/your/initial/path/")
Just use find-lisp
(require 'find-lisp)
;; a simple function, just to test
(defun my-funct (x)
(princ x)
(terpri))
(mapc 'my-funct (find-lisp-find-files "~/src/foo/" "\\.txt$"))
Emacs has the build-in function directory-files-recursively for this purpose:
(mapc #'YOUR-FUNCTION
(remove-if-not
#'file-directory-p ;only dirs
(directory-files-recursively YOUR-DIRECTORY "" t)))
It's also much faster than the f-directories function mentioned in the other answer because it doesn't use recursion internal.
I think Chris Barrett's answer is the correct and idiomatic one. However, for learning purposes i wanted to implement Python's os.walk, a general function for breadth-first traversing of directory trees. I used dash.el list library and f.el file and directory libraries. This is a stack-based implementation translated from Python.
(defun walk (path)
(let ((stack (list (f-full path)))
result)
(while stack
(let* ((path (pop stack))
(ds_ (f-directories path))
(ds (-map 'f-relative ds_))
(fs (-map 'f-relative (f-files path))))
(--each ds_ (!cons it stack))
(!cons (list path ds fs) result)))
(reverse result)))
See functions: f-full, pop, f-directories, f-relative, f-files, --each, !cons, reverse. Now you can use it in loops the same you would use it in Python:
(loop for (b ds fs) in (walk path)
do (copyright-update-directory b "*"))
I've been using Emacs for a couple months now, and I want to get started in elisp programming. Specifically, I'd like to write my own interactive function. However, I'm more than a bit lost. (interactive ...) has tons of options and I'm not sure which one I want. Then, I don't really know the names of the functions I need. If someone could kindly help me turn my pseudocode into real code, I would be mighty appreciative! (And as always, any links to informative places would be good. Right now I've just been reading this.)
Here is pseudocode for what I'd like to do:
(defun my-func (buffer) ; I think I need the buffer as an arg?
"does some replacements"
(interactive ???) ; ?
(let (replacements (list
'("a-regexp-string" . "a-replacement-string-with-backreferences")
...)) ; more of the above
(while replacements
(let (current (car replacements)) ; get a regexp-replacement pair
(some-regexp-replace-func buffer (car current) (cdr current)) ; do the replacement
(setq replacements (cdr replacements))))))
First, from the looks of your function you would probably be doing it in the current buffer, so no, you don't need to have a 'buffer' argument. If that's a bad assumption, I can change the code. Next, in a 'let' if you are assigning to variables you need another set of parens around each pair of var/value. Finally, when looping through a list I prefer to use functional-programming-like functions (mapcar, mapc, etc.). I'll try to inline some comments here:
(defun my-func ()
"Do some replacements"
(interactive)
(let ((replacements (list '("foo" . "bar")
'("baz" . "quux"))))
(save-excursion ; So point isn't moved after this function
(mapc (lambda (x) ; Go through the list, with this 'inline' function
; being called with each element as the variable 'x'
(goto-char (point-min)) ; Start at the beginning of the buffer
(while (re-search-forward (car x) nil t) ; Search for the car of the replacement
(replace-match (cdr x)))) ; And replace it with the cdr
replacements)))) ; The list we're mapc'ing through
As for what to read, I'd suggest the Elisp manual that comes with Emacs.