Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
Table of Contents
• 1. Elisp Snippets
• 1.1. Overview
• 1.2. Strings
• 1.2.1. Concatenate strings
• 1.2.2. Join Strings by Separator
• 1.2.3. Split String
• 1.2.4. Split String with quotes
• 1.2.5. Replace Strings
• 1.2.6. Regex
• 1.3. Text Manipulation
• 1.3.1. Text alignment
• 1.3.2. Join Multiple Lines
• 1.4. S-expressions
• 1.4.1. Parse s-expressions
• 1.4.2. Evaluate s-expressions
• 1.5. Clipboard (Kill-ring)
• 1.5.1. Copy string to clipboard
• 1.5.2. Paste string from clipboard
• 1.5.3. Copy buffer file name to clibpoard
• 1.5.4. Copy buffer directory to clibpoard
• 1.5.5. Copy buffer content to clipboard
• 1.6. Elisp
• 1.6.1. Load an Elisp file
• 1.6.2. Load all elisp files of a directory
• 1.6.3. Add directory to load path
• 1.6.4. Switch and Create the Scratch Buffer
• 1.6.5. Eval String in Clipboard
• 1.6.6. Extract Function Documentation
• 1.6.7. Describe function
• 1.7. Common Lisp Emulation Library
• 1.7.1. Reduce (fold left) function
• 1.8. Buffer and regions
• 1.8.1. Save buffer
• 1.8.2. Kill / delete buffer
• 1.8.3. Get buffer content as string
• 1.8.4. Get selected text as string
• 1.8.5. Create a scratch buffer for Programming Languages
• 1.8.6. Get all buffer's local variables
• 1.8.7. Get a specific buffer local variable
• 1.8.8. Append buffer content to file
• 1.8.9. Write file with buffer content (overwrite file it exists)
• 1.8.10. Revert / update buffer without asking to confirm
• 1.9. IO - Input and Output
• 1.9.1. Input - Read User Input
• 1.9.2. Output
• 1.10. Interacting with Operating System and External Applications
• 1.10.1. Related Documentation
• 1.10.2. Add application path to the PATH variable - Solving command not found
• 1.10.3. Synchronous Shell Commands
• 1.10.4. Pipe a region to external command
• 1.10.5. Launch apps in Asynchronous mode
• 1.10.6. Run asynchronous commands piping the output to a buffer
• 1.10.7. Run a ncurses / terminal app inside Emacs
• 1.10.8. Run apps in external terminal emulator
• 1.10.9. Launch applicatiosn from Emacs
• 1.10.10. Send regions, commands and buffer to M-x shell repl.
• 1.11. Compilation
• 1.11.1. Enhanced Compilation Command
• 1.11.2. Compile a single c++ file related to current buffer and run it.
• 1.11.3. Compile and run a single c++ file at point in dired mode
• 1.12. File
• 1.12.1. Test if file or directory exists
• 1.12.2. Expand file name
• 1.12.3. Read file to string
• 1.12.4. Open file to edit
• 1.12.5. Open file to edit silently
• 1.12.6. Edit File as Root
• 1.13. File Name Manipulation
• 1.13.1. Get absolute path to current buffer's file.
• 1.13.2. File name without path
• 1.13.3. File name to base name
• 1.13.4. Get file's path
• 1.13.5. Expand file name
• 1.13.6. Replace file extension
• 1.14. Directory
• 1.14.1. Open directory
• 1.14.2. Create directory
• 1.14.3. List directory
• 1.15. Dired mode snippets
• 1.15.1. Overview
• 1.15.2. Copy path of file at point
• 1.15.3. Paste a file from clibpboard
• 1.15.4. Create empty file (touch)
• 1.15.5. Open multiple marked files
• 1.15.6. Close multiple marked files
• 1.15.7. Open a file with default system application
• 1.15.8. Close all dired buffers
• 1.15.9. Browse bookmarked directories
• 1.15.10. Filter dired buffer by file extensions
• 1.15.11. Filter dired buffer by regex
• 1.15.12. Open directory at point with Microsoft Explorer in Windows OS.
• 1.16. Date Time
• 1.16.1. Overview
• 1.16.2. Function format-time-string
• 1.16.3. Function current-time
• 1.16.4. Function current-time-string
• 1.16.5. Function float-time
• 1.16.6. Function current-time-zone
• 1.17. Emacs Introspection
• 1.17.1. User init file
• 1.17.2. User Emacs Directory
• 1.17.3. Enviroment Variables
• 1.17.4. Get current Operating System
• 1.17.5. Test if Emacs is running in terminal or in window system
• 1.18. Web Browser
• 1.18.1. Browse Url
• 1.18.2. Browser Url setting the web browser
• 1.18.3. Search Web sites with Emacs
• 1.18.4. Browser Inside Emacs
• 1.19. Http Requests
• 1.19.1. Download File
• 1.19.2. url-retrieve-synchronously
• 1.19.3. Download a file interactively
• 1.19.4. Download a file and display it on a buffer
• 1.19.5. Http and Post Request
• 1.20. Packages
• 1.20.1. Test if package is installed
• 1.20.2. Install a package if it is not installed
• 1.20.3. Install a single-file package from URL
• 1.21. Helm Snippets
• 1.21.1. Switch between buffers in same directory
• 1.21.2. Browser Recent files
• 1.21.3. Browser Recent directories
• 1.21.4. Launch ansync shell command with helm
• 1.21.5. Switch between buffers associated with files
• 1.21.6. Switch between Emacs major modes
• 1.21.7. Open a list of web sites
• 1.21.8. Interface Makefile
• 1.22. Persistence
• 1.22.1. Save and Reload Current Session
• 1.22.2. Save and Restore Current Window Configuration
• 1.23. Non categorized
• 1.23.1. Save the scratch buffer and reload every Emacs startup
• 1.23.2. Code Navigation with Occur
• 1.23.3. Quick edit and reload Emacs Configuration File.
• 1.23.4. Refresh / Revert buffer without confirmation.
• 1.23.5. Create a menu with all color themes available
• 2. IELM - Inferior Emacs Lisp Mode
• 2.1. Change Prompt
• 2.2. Clear IELM shell
• 2.3. Send Region to IELM
• 2.4. Set other window's buffer as working buffer
• 2.5. Start IELM in other window setting the working buffer to current buffer
• 2.6. Launch IELM in other frame
• 3. Emacs Server and Client
• 4. Org-mode
• 5. Selected Gists and Source Codes
• 5.1. Gists
• 5.2. Source Codes
Top
1 Elisp Snippets
1.1 Overview
This section provides Elisp snippets and examples about Emacs API to help developers find what they
need quickly.
1.2 Strings
1.2.1 Concatenate strings
> (concat "hello" " world")
"hello world"
> (apply #'concat '("hello" " world " " elisp "))
"hello world elisp "
("/bin/app" "-x" "-y" "-z" "/home/user/some name with space/etc" "-k" "cmd")
1.2.6 Regex
1.4 S-expressions
> (clipboard/get)
"/home/arch/projects/emacs/"
1.5.5 Copy buffer content to clipboard
(defun buffer/copy-content ()
"Copy buffer content to clibpoard
Usage: M-x buffer/copy-content"
(interactive)
(clipboard/set
(buffer-substring-no-properties
(point-min)
(point-max)
)))
1.6 Elisp
"
(mapc #'load (directory-files path t "\\.el$")))
Suggestion:
Add (defalias 's #'scratch) to the init file.
You can switch to the scratch buffer with > M-x s
"
(interactive)
(switch-to-buffer buf)
(lisp-interaction-mode)
))
;;
;; Copy the following line in this comment block
;;
;; (message "Loading my copypaste file...")
ELISP> (eval-xclip)
"Loading my copypaste file..."
ELISP>
1.6.6 Extract Function Documentation elisp
Source: Generate emacs-lisp documentation Primitives:
ELISP>
ELISP> (defun sample-function (a b c)
"Function Docstring"
(+ a (* 5 b) (* 3 c)))
;; Extract Documentation
;;
ELISP> (documentation 'sample-function)
"Function Docstring"
;; Extract Code
;;
ELISP> (symbol-function 'sample-function)
(lambda
(a b c)
"Function Docstring"
(+ a
(* 5 b)
(* 3 c)))
;; Extract Arguments
ELISP> (help-function-arglist 'sample-function)
(a b c)
Final Code
(fun2org 'sample-function)
"** sample-function (a b c)\nFunction Docstring\n\n#+BEGIN_SRC emacs-lisp\
n(lambda (a b c) \"Function Docstring\" (+ a (* 5 b) (* 3 c)))\n#+END_SRC\n"
ELISP>
ELISP> (defun fun2org (function-symbol)
(let ((args (help-function-arglist function-symbol))
(doc (documentation function-symbol))
(code (symbol-function function-symbol)))
(print (format "** %s %s
%s
#+BEGIN_SRC emacs-lisp
%S
"** sample-function (a b c)
Function Docstring
ELISP> (cl-reduce (lambda (acc x) (and acc x)) '(t nil t t t f) :initial-
value t)
nil
ELISP> (cl-reduce (lambda (acc x) (and acc x)) '(t t t t t f) :initial-value
t)
f
ELISP> (cl-reduce (lambda (acc x) (and acc x)) '(t t t t t t) :initial-value
t)
t
Output:
((cursor-type . bar)
(buffer-display-time 22711 20278 987330 737000)
(buffer-display-count . 4)
(buffer-invisibility-spec
(org-babel-hide-hash . t)
(org-babel-hide-hash . t)
(org-babel-hide-hash . t)
(org-babel-hide-hash . t)
(org-babel-hide-result . t)
(org-hide-block . t)
(org-cwidth) (org-link) (outline . t) t)
(buffer-file-truename . "~/Documents/projects/emacs/Elisp_Snippets.org") (point-
before-scroll)
(buffer-auto-save-file-format . t)
(buffer-file-format) (buffer-file-coding-system . utf-8-unix)
(enable-multibyte-characters . t)
(mark-active)
(overwrite-mode) ...)
Append current buffer content to file. If the file doesn't exist, it will be created. Otherwise the buffer
content will be appended to the end of the file.
(append-to-file (point-min) (point-max) "/tmp/afile.txt")
1. Prompt functions
Function Description
read-string Read input as string
read-file-name Read input as file name
read-directory-name Read input as path to directory
read-regexp Read input as regular expression
read-passwd Read password
read-shell-command Read a shell command.
read-command Read an M-x elisp command returning a symbol.
read-envvar-name Read environment variable
read-key Read a key from the keyboard.
read-key-sequence Read a sequence of keystrokes and return as a string or vector.
read-number Read a numeric value
read-regexp Read regular expression returning it as string.
2. Read string
> (read-string "prompt > ") ;; M-x eval-print-last-sexp
"user enter some string in minibuffer"
"
(interactive)
(insert (read-file-name "file > ")))
1.9.2 Output
1. Message
Display a message at the bottom of the screen.
(message "A message to the user")
2. Print
3. Princ
4. Message box
Display a message, in a dialog box if possible. If a dialog box is not available, use the echo area.
(message-box "Emacs Alert. Time to drink a coffee!")
5. Tooltip
Show a tooltip
(tooltip-show "An Emacs tooltip")
1.10 Interacting with Operating System and External Applications
1.10.2 Add application path to the PATH variable - Solving command not found
1. Overview
In order to Emacs find where applications such as ruby shell, scala compiler and tools are
installed it is necessary to the PATH environment variable contain the path to the directories
which contains those applications.
2. Checking PATH variable
Copy this command below to the scratch buffer and enter M-x eval-print-last-last-sexp.
(getenv "PATH")
"/home/archbox/opt/scala/bin:/usr/bin:/bin: ..."
By running this command M-x show-path-varible it will print all paths in the $PATH variable in
a new buffer a easy way to read:
/home/archbox/opt/scala-2.11.8/bin
/home/archbox/opt/jdk1.8.0_74/bin/
/usr/local/sbin
/usr/local/bin
/usr/bin
/usr/lib/jvm/default/bin
/usr/bin/site_perl
/usr/bin/vendor_perl
/usr/bin/core_perl
/home/archbox/opt/java/bin
/home/archbox/opt/scala-2.11.8/bin/
Note: The character ':' is the separator for Unix-like OS (Linux/ BSD and OSX) and ';' is the
separator for Windows.
;; Add single directory
(setenv "PATH"
(concat
(expand-file-name "~/opt/scala/bin") ":"
(getenv "PATH")))
After it is done the Scala REPL will look like the picture below:
Figure 4: Scala in PATH variable.
5. Function to add multiple directories in PATH variable
(defun add-to-path-var (&rest pathlist)
(let* ((path-sep (if (equal system-type 'windows/nt)
";" ;; Windows separator
":" ;; Unix separator
)))
(setenv "PATH" (concat (apply #'concat
(mapcar
(lambda (path)
(concat (expand-file-name path)
path-sep))
pathlist))
(getenv "PATH")))))
Usage example:
(add-to-path-var "~/opt/scala/bin" "~/opt/jdk1.8.0_20/bin/")
Alternative way:
Use the function locally without pollute the namespace.
(require 'cl)
(cl-flet
((add-to-path-var
(&rest pathlist)
(let* ((path-sep (if (equal system-type 'windows/nt)
";" ;; Windows separator
":" ;; Unix separator
)))
(setenv "PATH"
(concat (apply #'concat
(mapcar
(lambda (path)
(concat (expand-file-name path)
path-sep))
pathlist))
(getenv "PATH"))))))
;; Add paths to be added to PATH variable here,
(add-to-path-var
"~/opt/scala/bin"
"~/opt/jdk1.8.0_20/bin/"
))
(defun insert-debug-info ()
(interactive)
/home/arch/.local/share/xfce4/helpers/custom-WebBrowser.desktop
/home/arch/.local/share/applications/userapp-mono-IAJQMY.desktop
/home/arch/.local/share/applications/userapp-sh-9VFBMY.desktop
/home/arch/.local/share/applications/userapp-em-FLD8LY.desktop
/home/arch/.local/share/applications/userapp-mpv-FLQ9LY.desktop
/home/arch/.local/share/applications/userapp-Firefox-SOBHMY.desktop
Pipes the buffer content to external command $wc -l and get the output as a string.
> (with-output-to-string ;; M-x eval-print-last-sexp
(shell-command-on-region (point-min) (point-max) "wc -l"))
""
1. Ping a host
• (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS
2. Tracerote a host
(defun traceroute-host (&optional hostname)
"Run traceroute command to test connection.
Usage:
- Interactive: M-x traceroute-host [Enter the hostname]
- Command: (traceroute-host <hostname>)
Example: (traceroute-host \"www.yahoo.co.uk\")."
(interactive)
(let ((hostname- (if hostname
hostname
(read-string "host to traceroute: "))))
(start-process "traceroute" "*traceroute*" "traceroute" hostname-)
(switch-to-buffer-other-frame "*traceroute*")))
1.10.7 Run a ncurses / terminal app inside Emacs
Run linux htop (task manager) inside Emacs:
(term "htop") ;; C-x C-e or M-x eval-last-sexp
To launch nmtui:
(shell-command-in-terminal "nmtui")
This comamnd can be bound to a keybiding with the code bellow that bidns the key combination
SUPER (Windows Key) + 8.
(global-set-key (kbd "s-8") #'shell-launch)
(defun shell/buffer-repl-frame ()
(interactive)
(with-selected-frame (make-frame)
(shell/buffer-repl)))
This functions are useful to send regions, lines and regions to M-x shell repl from a shell-buffer or
shell scratch buffer to the repl.
(defun shell/send-region ()
"Send selected text to M-x shell repl."
(interactive)
(comint-send-region (get-buffer-process "*shell*" )
(region-beginning) (region-end))
(comint-send-string (get-buffer-process "*shell*" ) "\n"))
(defun shell/insert-region ()
"Insert selected text into M-x shell repl and run it."
(interactive)
(let ((text (buffer-substring-no-properties (region-beginning)
(region-end)
)))
(with-current-buffer "*shell*"
(insert text)
(comint-send-input)
)))
(defun shell/send-line ()
"Send current line to M-x shell repl."
(interactive)
(comint-send-region (get-buffer-process "*shell*")
(line-beginning-position)
(line-end-position)
)
(comint-send-string (get-buffer-process "*shell*" ) "\n"))
(defun shell/insert-line ()
"Insert current line to M-x shell repl."
(interactive)
(let ((line (buffer-substring-no-properties
(line-beginning-position)
(line-end-position)
)))
(with-current-buffer "*shell*"
(insert line)
(comint-send-input)
)))
(defun shell/execute-line ()
"Execute current line as shell command."
(interactive)
(shell-command
(buffer-substring (line-beginning-position)
(line-end-position))))
(defun shell/execute-region ()
"Execute current region as shell command."
(interactive)
(shell-command
(buffer-substring (region-beginning)
(region-end))))
(defun shell/insert-buffer ()
"Insert all buffer content into M-x shell repl and run it."
(interactive)
(let ((text (buffer-substring-no-properties (point-min)
(point-max)
)))
(with-current-buffer "*shell*"
(insert text)
(comint-send-input)
)))
Example:
1. User runs M-x shell/buffer-repl-frame. It will open a frame like in the picture bellow.
1. User select the region with some code and runs M-x shell/insert-region. It will send the current
region to the shell repl and display the output, in this case the content of root directory.
Figure 13: Example of M-x shell/buffer-repl-frame.
Figure 14: Demonstration of M-x shell/buffer-repl-frame and shell/insert-region
1.11 Compilation compile tool building shell process
The advantage of this command is that user doesn't need to type the file name to be compiled.
(setq compile2-command-history "")
(defun compile2 ()
"Enhanced compilation command.
- %f - is expanded to current buffer file name.
- %d - is expanded to current buffer current directory.
- %n - is expanded to current buffer base name.
1.11.2 Compile a single c++ file related to current buffer and run it.
Usage: When the user run the command M-x cpp/compile-run-buffer at the current buffer (file
code1.cpp) it will compile and run this file running the command $ g++ code1.cpp -o
code1.bin && ./code1.bin.
(defun cpp/compile-run-buffer ()
"Compile and run current c++ buffer (single-file C++ code).
Usage: By running M-x cpp/compile-buffer-run at current buffer (file code1.cpp)
will run $ g++ code1.cpp -o code1.bin && ./code1.bin"
(interactive)
(let* ((file-name (file-name-nondirectory (buffer-file-name)))
;; Change file name extension to .bin
(output (concat (file-name-base file-name) ".bin")))
(save-buffer)
(compile (format "g++ %s -o %s && ./%s"
file-name
output
output
))))
1.11.3 Compile and run a single c++ file at point in dired mode
Usage: In dired mode mode, place the cursor at the file to be compiled and run M-x cpp/compile-run-
dired.
(defun cpp/compile-run-dired ()
"Compile single c++ file at point in dired mode.
Usage: Position the cursor at the file to be compiled and
run M-x cpp/compile-dired."
(interactive)
(let* ((file-name (file-name-nondirectory (dired-file-name-at-point)))
;; Change file name extension to .bin
(output (concat (file-name-base file-name) ".bin")))
(save-buffer)
(compile (format "g++ %s -o %s && ./%s"
file-name
output
output
))))
1.12 File
order hosts,bind
multi on
# End of file
;; Example:
;; ELISP> (open-as-root "/etc/host.conf")
;;
;;
;; Open an already opened buffer as root
;;
;; M-x open-buffer-as-root
;;
(defun open-buffer-as-root ()
(interactive)
(let
(
;; Get the current buffer file name
(filename (buffer-file-name (current-buffer)))
;; Get the current file name
(bufname (buffer-name (current-buffer)))
)
(progn
(kill-buffer bufname) ;; Kill current buffer
(open-as-root filename)))) ;; Open File as root
"/home/archbox/.emacs.d/init.py"
ELISP>
or
(defun file-replace-extension (ext file)
(concat (file-name-directory file)
(file-name-base file)
ext
))
1.14 Directory directory
.
..
Xorg.0.log
Xorg.0.log.old
btmp
faillog
httpd
journal
lastlog
old
pacman.log
samba
speech-dispatcher
wtmp
/var/log/.
/var/log/..
/var/log/Xorg.0.log
/var/log/Xorg.0.log.old
/var/log/btmp
...
1.15.1 Overview
The dired mode is the mode used by Emacs to browser directories.
See also: How do you customize dired?
Source: hiroina/.emacs
;;; Linux
(gnu/linux (let ((process-connection-type nil))
(start-process
"proc"
nil
;; Command
"xdg-open" (expand-file-name filename))))
;; Windows 7, 8, 10 - Kernel NT
(windows-nt (start-process
"proc"
nil
;; Command
"cmd" "/C" "start" "" (expand-file-name filename)
))))
Function: dired-xdg
(defun dired-xdg ()
"Open file at point with systems' default app.
Usage: In the dired mode select a file and type M-x dired-xdg
to execute the file with the system default app.
"
(interactive)
(with-current-buffer
(xdg-open (dired-get-filename))))
(buffer-list)))
(defun dired-bookmarks ()
"Open a directory by selecting it in Helm menu."
(interactive)
(helm
:prompt "Bookmarks: "
:sources `((
(name . "Bookmark: ")
(candidates . dired-bookmarks-path-list)
(action . dired)
))))
It will only show files ending with extensions *.exe and *.dll.
To show all files of dired buffer again type 'g'."
(interactive)
(dired-mark-files-regexp
(mapconcat 'identity
(mapcar (lambda (ext) (format "\\.%s$" ext))
(split-string (read-string "Extension: ")))
"\\\|"
))
(dired-toggle-marks)
(dired-do-kill-lines))
Unix time stamp (Number of seconds or microseconds since January first of 1970):
ELISP> (format-time-string "%s")
"1500103484"
ELISP>
ELISP>
(if window-system
(message "Running in Window System / GUI")
(message "Running in terminal ")
))
;; In GUI
;;-----------------------------
> (test-window-system) ;; M-x eval-print-last-sexp
"Running in Window System / GUI"
;; In Terminal
;;------------------------------
> (test-window-system) ;; M-x eval-print-last-sexp
"Running in terminal "
;; Or
;;; Or
;;; Or
1. Search google
Usage: M-x search-google
(require 'url-util)
(defun search-google ()
(interactive)
"Search www.google.ca."
(browse-url
(format "http://www.google.ca?gws_rd=ssl#q=%s"
(url-encode-url
(read-string "Google: ")))))
(require 'url-util)
(defun search-hackernews-with-google ()
(interactive)
(search-google-url "https://news.ycombinator.com" (read-string "Hnews:
")))
(defun search-reddit-with-google ()
(interactive)
(search-google-url "https://www.reddit.com" (read-string "Reddit: ")))
(defun search-stackoverflow-with-google ()
(interactive)
(search-google-url "http://stackoverflow.com" (read-string "S.O Search:
")))
3. Search github
(require 'url-util)
(defun search-github ()
(interactive)
"Search www.google.ca"
(browse-url
(format "https://github.com/search?q=%s"
(url-encode-url
(read-string "Github Search: ")))))
4. Search gisthub
(require 'url-util)
(defun search-gisthub ()
"Search gisthub : http://gist.github.com.
Usage: M-x search-gisthub"
(interactive)
(browse-url
(format "https://gist.github.com/search?p=50&q=%s&ref=searchresults"
(url-encode-url
(read-string "Gisthub Search: ")))))
Key Bindings
1.19.2 url-retrieve-synchronously http web download sync
(url-retrieve-synchronously URL &optional SILENT INHIBIT-COOKIES)
Example:
(with-current-buffer (url-retrieve-synchronously "http://www.httpbin.org/get")
(buffer-substring-no-properties (point-min) (point-max)))
Output:
HTTP/1.1 200 OK
Server: nginx
Date: Fri, 23 Sep 2016 23:44:21 GMT
Content-Type: application/json
Content-Length: 304
Connection: keep-alive
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
{
"args": {},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip",
"Extension": "Security/Digest Security/SSL",
"Host": "www.httpbin.org",
"Mime-Version": "1.0",
"User-Agent": "URL/Emacs"
},
"origin": "179.176.152.199",
"url": "http://www.httpbin.org/get"
}
(url-copy-file
url
;; Get file name.
(read-file-name "File name: "
(car (last (split-string url "/")))))
1.20 Packages package install library
(defun buffer/switch-in-directory ()
"Switch between buffers in same directory."
(interactive)
(helm
:prompt "Buffer switch: "
:sources `((
(name . "Dir: ")
(candidates . ,(mapcar
(lambda (b) (cons (buffer-name b) b))
;; filter buffers not in this directory (code
bellow)
(remove-if-not (lambda (b)
(buffer/with-file-in-directory-p
(or (file-name-directory
(buffer-file-name))
default-directory
)
b
))
(buffer-list)
)))
(action . switch-to-buffer)
))))
(defun helm-recent-files ()
(interactive)
(helm
:prompt "File: "
:sources `((
(name . "File: ")
(candidates . ,recentf-list)
(action . find-file)
))))
1.21.3 Browser Recent directories
Usage M-x helm-recent-dirs
(require 'helm)
(defun helm-recent-dirs ()
(interactive)
(helm
:prompt "Dir: "
:sources `((
(name . "Dir: ")
(candidates . (lambda ()
(unique
(map #'file-name-directory recentf-list))))
(action . dired)))))
(defun helm-launcher ()
"Launches apps available in $PATH without blocking Emacs.
Usage M-x heml-launcher"
(interactive)
(let ((data (mapcar (lambda (p)
(cons (file-name-nondirectory p)
p
))
(get-executables)
)))
(helm
:prompt "Shell: "
:sources `((
(name . "Shell: ")
(candidates . ,data)
(action . run-async)
)))))
(defun helm-web ()
(interactive)
(helm
:prompt "Web Site: "
:sources `((
(name . "Bookmarks")
(candidates . helm-url-default-url-list)
(action . (lambda (c) (browse-url (cdr c))) )
))))
1.21.8 Interface Makefile
This command extracts the build tasks from a Makefile and shows it as a helm menu where the user
can select the task to be executed. It will be run as a asynchronous process.
Usage: M-x helm-make
Version1:
;; Taken from: http://emacs.stackexchange.com/questions/7148/get-all-regexp-
matches-in-buffer-as-a-list
(defun re-seq (regexp string)
"Get a list of all regexp matches in a string"
(save-match-data
(let ((pos 0)
matches)
(while (string-match regexp string pos)
(push (match-string 0 string) matches)
(setq pos (match-end 0)))
matches)))
(defun helm-make ()
(interactive)
(let ((tasks
(re-seq "^\\w+"
(with-temp-buffer
(insert-file "Makefile")
(buffer-substring-no-properties
(point-min)
(point-max))))))
(helm
:prompt "Makefile task: "
:sources `((
(name . "Task")
(candidates . ,tasks)
(action . (lambda (task)
(start-process "make"
"*make*"
"make" task
))))))
(switch-to-buffer "*make*")))
Example: Assuming that the current directory has the Makefile with content. The command M-x helm-
make will show the tasks all, html, browse and clean.
all: html
html:
mkdir -p dist
emacs --batch -q -l build.el --kill
mv dist/README.html dist/index.html
cp -r -v images dist/images
cp -r *.org dist/
browse:
firefox dist/index.html
clean:
rm -rf dist/*.html dist/*.html~
1.22 Persistence
ELISP>
ELISP> (format "(setq last-session-files '%S)" (remove-if 'null (mapcar 'buffer-
file-name (buffer-list))))
"(setq last-session-files '(\"/home/tux/.emacs.d/init.el\" \"/sudo:root@localhost:/
etc/host.conf\"))"
ELISP> (setq code (format "(setq last-session-files '%S)" (remove-if 'null (mapcar
'buffer-file-name (buffer-list)))))
"(setq last-session-files '(\"/home/tux/.emacs.d/init.el\" \"/sudo:root@localhost:/
etc/host.conf\"))"
ELISP>
ELISP>
Joining Everything
File: sessions.el
(setq session-file "~/.emacs.d/lastsession.el")
(defun make-session-code ()
(interactive)
(format "(setq last-session-files '%S)" (remove-if 'null (mapcar 'buffer-file-
name (buffer-list)))))
(defun save-session ()
"Save Current Session"
(interactive)
(when (file-exists-p session-file) (delete-file session-file))
(write-file session-file (make-session-code)))
(defun load-session ()
(interactive)
(load-file session-file)
(mapcar 'find-file last-session-files)
)
(message "Reloaded")
(defun restore-view ()
"Restore saved window configuration"
(interactive)
(set-window-configuration winconf)
(message "View loaded"))
1.23.1 Save the scratch buffer and reload every Emacs startup
Saves the scratch buffer to a file every times Emacs is closed.
Source: scratch.el
(setq scratch-buffer-file "~/.emacs.d/scratch.el")
;; window-setup-hook
;; @see info 38.1.1 Summary: Sequence of Actions at Startup
(add-hook 'kill-buffer-hook; *scratch*
(lambda ()
(if (equal (buffer-name) "*scratch*") (scratch-save))))
(add-hook 'after-save-hook
(lambda ()
(unless (get-buffer "*scratch*") (scratch-resume))))
(defun scratch-save ()
(let ((buf (get-buffer "*scratch*")))
(when buf
(set-buffer buf)
(write-file scratch-buffer-file)
(ignore-errors (kill-buffer "scratch.el")))))
(defun scratch-resume ()
"*scratch* "
(interactive)
(set-buffer (get-buffer-create "*scratch*"))
(funcall initial-major-mode)
(insert-file-contents scratch-buffer-file nil nil nil t)
Example:
It can also be useful to Scan code tags like: @FIXME, @TODO, @README, @NOTE. This fuction
can be excuted by typing: M-x scan-code-tags
Example:
(defun scan-code-tags ()
"Scan code tags: @TODO: , @FIXME:, @BUG:, @NOTE:."
(interactive)
(split-window-horizontally)
(occur "@FIXME:\\|@TODO:\\|@BUG:\\|@NOTE:"))
1.23.3 Quick edit and reload Emacs Configuration File. elisp customization
It is useful to quick edit and reload ~/emacs.d/init.el without restart emacs. Those functions can be put
in the init.el file.
;; Usage: M-x reload-init-file
;;
(defun reload-init-file ()
"Reload init.el file."
(interactive)
(load user-init-file)
(message "Reloaded init.el OK."))
Usage:
#+ENDSRC M-x refresh #+ENDSRC
(defun make-menu-rows ()
(mapcar
(lambda (x)
(format "[\"%s\" (load-theme '%s)]" (symbol-name x) (symbol-name x) ))
(custom-available-themes)))
(defun make-color-menu-code ()
(format
"
(easy-menu-define djcb-menu global-map \"Color Themes\"
'(\"Color Themes\"
%s
)
)
"
(mapconcat 'identity (make-menu-rows) "\n")))
;;
;; "Eval is evil". It must be avoided, because, it is hard to refactor,
;; hard to debug and vulnerable to code injection on Web Apps, so a better
;; way to write it is to use Elisp macros.
;;
;; @DONE: Change eval-string to an Elisp macro.
;;
(eval-string (make-color-menu-code))
Using Macros
Developement:
ELISP> (custom-available-themes)
(cyberpunk adwaita deeper-blue dichromacy leuven light-blue manoj-dark misterioso
tango-dark tango tsdh-dark tsdh-light wheatgrass whiteboard wombat)
ELISP> (mapcar
(lambda (sym) `[,(symbol-name sym) (load-theme (quote ,sym))])
(custom-available-themes)
)
(["adwaita"
(load-theme 'adwaita)]
["deeper-blue"
(load-theme 'deeper-blue)]
["dichromacy"
(load-theme 'dichromacy)]
["leuven"
(load-theme 'leuven)]
["light-blue"
(load-theme 'light-blue)]
["manoj-dark"
(load-theme 'manoj-dark)]
["misterioso"
(load-theme 'misterioso)]
["tango-dark"
(load-theme 'tango-dark)]
...
;;; Now execute the generated code, the menu will pop up.
;;;
Final code
(defun make-menu-rows ()
(mapcar
(lambda (sym) `[,(symbol-name sym) (load-theme (quote ,sym))])
(custom-available-themes)))
(defmacro make-color-menu ()
`(easy-menu-define djcb-menu global-map "Color Themes"
'("Color Themes"
,@(make-menu-rows))))
(make-color-menu)
(progn
(defun make-menu-rows ()
(mapcar
(lambda (sym) `[,(symbol-name sym) (load-theme (quote ,sym))])
(custom-available-themes)))
(defmacro make-color-menu ()
`(easy-menu-define djcb-menu global-map "Color Themes"
'("Color Themes"
,@(make-menu-rows))))
(make-color-menu))
2.5 Start IELM in other window setting the working buffer to current buffer
This command starts IELM in other window setting the working buffer to current buffer. It allows the
user to manipulate the current buffer.
Usage: M-x ielm-this-buffer
(defun ielm-this-buffer ()
"Start IELM in other window with current buffer set to current windows' buffer."
(interactive)
(let ((buf (current-buffer)))
(ielm-other-window)
(ielm-change-working-buffer buf)
(ielm-print-working-buffer)))
4 Org-mode
Moved to: org-mode.html
5.1 Gists
• extract archives from eshell
• garaud/pipe-to-emacs.py - Pipe to Emacs: Insert a result from an UNIX command into a new
Emacs buffer
• dvnmk/process - Play youtube playlist using Emacs + mpv player.
• TikhonJelvis/epage - "A little pager script I wrote that calls out to emacsclient."
• Elisp code to create a rails console
Strings
The empty string (zero-length string, null string, …):
(zerop (string-match "" "")) ;; O(n)
==> t
As a (very minor) space and performance optimization, starting with Emacs 23, Emacs keeps an
interned copy of the empty string as a single object
(eq "" "") ;; O(1)
==> t ; nil prior to Emacs 23
Substrings
(substring "abcdefg" 0 3)
==> "abc"
(substring "abcdefg" -3 -1)
==> "ef"
Buffers:
(with-temp-buffer (insert "abcdefg") (buffer-substring 2 4))
==> "bc"
Custom functions:
(defun string/ends-with (s ending)
"Return non-nil if string S ends with ENDING."
(cond ((>= (length s) (length ending))
(let ((elength (length ending)))
(string= (substring s (- 0 elength)) ending)))
(t nil)))
Faster, simpler:
(defun string/ends-with (string suffix)
"Return t if STRING ends with SUFFIX."
(and (string-match (rx-to-string `(: ,suffix eos) t)
string)
t))
The first argument to rx-to-string `(: ,suffix eos) is a regular expression in sexp form. The
help page for “rx” elucidates the syntax:
(: SEXP1 SEXP2 ...)
matches what SEXP1 matches, followed by what SEXP2 matches, etc.
,suffix is SEXP1 and eos is SEXP2 '(: suffix eos) would create a list of three elements:
The symbol named “:”, the symbol named “suffix”, and the symbol named “eos”. But that’s not what
this function wants. It wants the value of the symbol named “suffix”, not the symbol itself. ` is special
syntax (note the backtick, not just tick) that allows some things in the list to be preceded by a comma,
which are then evaluated. `(: ,suffix eos) is convenience syntax for (list ': suffix
'eos). The only symbol that is evaluated is suffix. Because there is no , before : or eos, both : and eos
are not evaluated. Symbols are not evaluated by default in the `( … ) syntax and require a , if you want
them to be evaluated. Thanks to <forcer> on #emacs-beginners irc channel for the explanation.
(defun string/starts-with (string prefix)
"Return t if STRING starts with prefix."
(and (string-match (rx-to-string `(: bos ,prefix) t)
string)
t))
Processing characters
Reversing a string:
(defun string/reverse (str)
"Reverse the str where str is a string"
(apply #'string
(reverse
(string-to-list str))))
See CharacterProcessing and StringModification. See tr for an example mixing strings and characters.
Looking at characters in a temporary buffer:
(with-temp-buffer
(insert "abcdefg")
(goto-char (point-min))
(while (not (= (char-after) ?b)) (forward-char))
(point))
==> 2
Trim whitespace
Trim whitespace from the end of a string:
(setq test-str "abcdefg ")
(when (string-match "[ \t]*$" test-str)
(message (concat "[" (replace-match "" nil nil test-str) "]")))
Splitting strings
See SplitString.
Joining strings
Use ‘mapconcat’ to join strings, interpolating a separator string and possibly transforming each
string before joining.
For no transformation (‘identity’), use this:
(mapconcat 'identity '("" "home" "alex " "elisp" "erc") "/")
==> "/home/alex /elisp/erc"
If you have an Emacs version greater than 25.3 then you can alternatively use ‘string-join’ for
that simple case:
(string-join '("foo" "bar" "baz") ", ")
==> "foo, bar, baz"
For the even simpler case where you have no separator (it is "", you can just use ‘concat’ or
‘format’:
(concat "hello, " "world")
==> "hello, world"
Serialization
Convert forms to strings using ‘prin1-to-string’, then convert back from a string using
‘read’.
(length (read (prin1-to-string (make-list 1000000 '(x)))))
==> 1000000
(read (prin1-to-string "Hello World!"))
==> "Hello World!"
This works only in the simplest cases. Unfortunately, it doesn’t work for all EmacsLisp data types.
(read (prin1-to-string (make-hash-table))) ;; Error before Emacs 23.
==> #s(hash-table size 65 test eql rehash-size 1.5 [...] data ())
Formatting
Killing text
As the ElispManual says, “Most of the kill commands are primarily for interactive use […] When you
need to delete text for internal purposes within a Lisp function, you should normally use deletion
functions, so as not to disturb the kill ring contents.”
The following mimic the ‘kill-’ commands but without disturbing the kill ring. To make them kill,
use ‘kill-region’ instead of ‘delete-region’.
Delete region
The Lisp equivalent of ‘kill-region’ (‘C-w’) but without kill-ring side effects::
(delete-region (region-beginning) (region-end))
According to the ElispManual, “Few programs need to use the ‘region-beginning’ and
‘region-end’ functions.” This is because Lisp code should not rely on nor “alter the mark unless
altering the mark is part of the user-level functionality of the command. (And, in that case, this effect
should be documented.) To remember a location for internal use in the Lisp program, store it in a Lisp
variable. For example: […]”
Delete line
The equivalent of ‘kill-line’ (‘C-k’) but without kill-ring side effects:
(let ((beg (point)))
(forward-line 1)
(forward-char -1)
(delete-region beg (point)))
The examples with ‘forward-line’ are shown for comparison with other examples, below.
Or just:
(delete-region (line-beginning-position)
(line-end-position))
Delete word
The equivalent of ‘kill-word’ (‘M-d’) but without kill-ring side effects:
(let ((beg (point)))
(forward-word 1)
(delete-region beg (point)))
Delete sentence
The equivalent of ‘kill-sentence’ (‘M-k’) but without kill-ring side effects:
(let ((beg (point)))
(forward-sentence 1)
(delete-region beg (point)))
Numbers
Test whether a string represents a number
(defun string-integer-p (string)
(if (string-match "\\`[-+]?[0-9]+\\'" string)
t
nil))
(string-integer-p "1234")
==> t
(string-integer-p "x1234")
==> nil
(string-integer-p "3.141592653589793")
==> nil
(string-float-p "1234")
==> nil
(string-float-p "3.141592653589793")
==> t
(string-float-p ".1")
==> nil
(string-float-p "1.")
==> t
String to number
The following example is for instruction. Normally standard function ‘string-to-number’ would
be used.
(defun decimal-number (string)
(let ((n (string-to-number string)))
(save-match-data
(if (and (not (zerop n))
(string-match "\\`\\s-*0+\\.?0*\\s-*\\'" string))
n
nil))))
(decimal-number "536870911")
==> 536870911
(decimal-number "536870912")
==> 536870912.0
(decimal-number "3.141592653589793")
==> 3.141592653589793
(decimal-number "042")
==> 42
(decimal-number "000")
==> 0
(decimal-number "0.0")
==> 0.0
Random numbers
(random 2) ;coin toss (0 or 1)
(+ (random 6) 1) ;dice
(group-number 299792458)
==> "299,792,458"
(group-number "149597870691" 4 " ")
==> "1495 9787 0691"
Increment numbers
See IncrementNumber.
See InsertingTodaysDate.
Formatting dates
Use the function ‘format-time-string’ which is a build in function in both Emacsen and works
like ‘strftime’:
;; Year-Month-Day:
(insert (format-time-string "%Y-%m-%d"))
;; Hour:Minutes:Seconds
(insert (format-time-string "%H:%M:%S"))
Conversions
Read a date from a string.
(let ((time (date-to-time "Tue, 27-Sep-83 12:35:59 EST")))
(set-time-zone-rule t) ;; Use Universal time.
(prog1 (format-time-string "%Y-%m-%d %T UTC" time)
(set-time-zone-rule nil))) ;; Reset to default time zone.
==> "1983-09-27 17:35:59 UTC"
Pattern matching
“Patterns” refers to RegularExpressions.
There’s a set of functions that work in strings, and a set that work in buffers.
Finding
(string-match "foo*" "Fight foo for food!")
==> 6
The functions working on buffers move point to the end of the occurrence found and return it. That’s
why the result is 10 instead of 6.
Verifying
Sometimes you just want to check whether you’re at the right place:
(with-temp-buffer
(insert "Fight foo for food!")
(goto-char (point-min))
(looking-at "fight"))
==> t
This loads EmacsLisp files listed one per line in a text file.
(with-current-buffer (find-file-noselect "~/load-files.txt")
(while (re-search-forward "^.*\\.el\\(\\.gz\\)?$" nil t)
(let ((filename (match-string 0)))
(when (file-exists-p filename)
(load-file filename)))))
Usually you would use *let* instead of *setq* but this is just a simple self-contained example. See
also DynamicBindingVsLexicalBinding.
Here’s an example:
(let ((str "time help"))
(string-match "time \\([A-Za-z]+\\)$" str)
(match-strings-all str))
==> ("time help" "help")
Code Comments
Move to the beginning of the current comment:
(require 'newcomment)
(comment-beginning)
Sequences
Datatypes used to represent sequences of things:
_____________________________________________
| |
| Sequence |
| ______ ________________________________ |
| | | | | |
| | List | | Array | |
| | | | ________ ________ | |
| |______| | | | | | | |
| | | Vector | | String | | |
| | |________| |________| | |
| | ____________ _____________ | |
| | | | | | | |
| | | Char-table | | Bool-vector | | |
| | |____________| |_____________| | |
| |________________________________| |
|_____________________________________________|
Lists
List basics are explained at ListStructure. Lists can shrink and grow, but access to elements towards the
end of the list is slow if the list is long.
Use ‘cons’, ‘push’, or ‘add-to-list’ to prepend a new element to a list. Use ‘nth’ to
access an element of a list.
(let ((words '("fight" "foo" "for" "food!")))
(when (string= "foo" (nth 1 words))
(setq words (cons "bar" words)))
words)
==> ("bar" "fight" "foo" "for" "food!")
Note how ‘push’ adds an element to the front of the list, so that usually the list has to be reversed
after the loop. ‘nreverse’ is particularly efficient because it does this destructively. See
DestructiveOperations for more about this.
Copying:
Use ‘copy-sequence’ to make a shallow copy of a list without changing the original.
(let* ((orig '((1 2) (3 4)))
(copy (copy-sequence orig)))
(setcdr copy '((5 6)))
(list orig copy))
==> (((1 2) (3 4)) ((1 2) (5 6)))
The elements in the copy remain in the original. More importantly, they are in fact the same elements
(i.e., ‘eq’), not copies. The list is copied, but its elements are shared with the original list.
(let* ((orig '((1 2) (3 4)))
(copy (copy-sequence orig)))
(setcdr (cadr copy) '(0))
(list orig copy))
==> (((1 2) (3 0)) ((1 2) (3 0)))
Filtering:
A ‘filter’ macro has been added to the Emacs development tree. It does what you expect: filters a
list, returning a copy that keeps elements that satisfy a predicate and omitting elements that do not
satisfy it.
If your Emacs does not yet have this built in, you can use ‘dolist’ or ‘mapcar’ to iterate over a
list with a conditional, and then use ‘delq’ to remove the ‘nil’ values.
(defun my-filter (condp lst)
(delq nil
(mapcar (lambda (x) (and (funcall condp x) x)) lst)))
Therefore,
(my-filter 'identity my-list)
is equivalent to
(delq nil my-list)
For example:
(let ((num-list '(1 'a 2 "nil" 3 nil 4)))
(my-filter 'numberp num-list))
==> (1 2 3 4)
Package ‘cl-seq’ has functions ‘remove-if’ and ‘remove-if-not’. The latter can be used
instead of ‘my-filter’.
(let ((num-list '(1 'a 2 "nil" 3 nil 4)))
(remove-if-not 'numberp num-list))
==> (1 2 3 4)
The following function was written by tali713 in response to hypnocat’s question regarding a filter
function in #emacs:
(defun keep-when (pred seq)
(let ((del (make-symbol "del")))
(remove del (mapcar (lambda (el)
(if (funcall pred el) el del)) seq))))
Use:
(keep-when 'atom '(1 2 3 (4 5) 6 nil t foo))
==> (1 2 3 6 nil t foo)
Updated 31/05/2013.
Tranposing:
Create a list from multiple lists:
((lambda (&rest args)
(mapcar (lambda (n)
(delq nil (mapcar (lambda (arg) (nth n arg)) args)))
(number-sequence 0 (1- (apply 'max (mapcar 'length args))))))
'(1 2 3) '(a b c) '(A B C))
==> ((1 a A) (2 b B) (3 c C))
A more concise version is possible with the the higher-arity version of ‘mapcar’ available from
library ‘cl’.
((lambda (&rest args)
(apply (function mapcar*) (function list) args))
'(1 2 3) '(a b c) '(A B C))
==> ((1 a A) (2 b B) (3 c C))
Searching:
You can check for presence of a value in a list using ‘member’ or ‘memq’.
(let ((words '("fight" "foo" "for" "food!")))
(car (member "for" words)))
==> "for"
In the latter, a more efficient algorithm would use a loop (a non-local exit).
Association lists
The ElispManual has examples of finding and deleting values in an association list, or alist. Here are
cases when the car values are strings.
(assoc "2" '(("2" . 2) ("1" . 1) ("2") ("3" . 3)))
==> ("2" . 2)
Deleting:
(let ((alist '(("a" . 1) ("b" . 2))))
(delq (assoc "a" alist) alist))
==> (("b" . 2))
The alist functions are useful for finding the first instance of a value in any list, not just association
lists, and even when there are duplicates.
The following uses ‘mapcar’ to associate the ‘major-mode’ to each buffer returned by
‘buffer-list’, then ‘assq’ to find the first buffer where the major mode is ‘fundamental-
mode’.
(assq 'fundamental-mode
(mapcar
(lambda (b)
(cons (buffer-local-value 'major-mode b) b))
(buffer-list)))
==> (fundamental-mode . #<buffer *Messages*>)
You can also find values in regular lists, by converting them to association lists with a null cdr.
Here’s an association list of random numbers with no associated value.
'((8 . nil) (3 . nil) (1 . nil) (7 . nil) (3 . nil) (6 . nil) (9 . nil))
==> ((8) (3) (1) (7) (3) (6) (9))
This is really just making a list for each number – a “list of lists” – which can be done with ‘mapcar’
and ‘list’.
(mapcar 'list '(8 3 1 7 3 6 9))
==> ((8) (3) (1) (7) (3) (6) (9))
(assq 3 (mapcar 'list '(8 3 1 7 3 6 9)))
==> (3)
Vectors
Vectors are fixed in size, and their elements can be accessed in constant time (neither of which is the
case for lists).
(let ((words ["fight" "foo" "for" "food!"]))
(when (string= "foo" (aref words 1))
(aset words 1 "bar"))
words)
==> ["fight" "bar" "for" "food!"]
Hash tables
Hash tables map keys to values. They are similar to alists, but they are typically more efficient for a
large number of keys.
See HashMap.
Iterate:
(let ((nick-table (make-hash-table :test 'equal))
nicks)
(puthash "kensanata" "Alex Schroeder" nick-table)
(puthash "e1f" "Luis Fernandes" nick-table)
(puthash "pjb" "Pascal J. Bourguignon" nick-table)
(maphash (lambda (nick real-name)
(setq nicks (cons nick nicks)))
nick-table)
nicks)
==> ("pjb" "e1f" "kensanata")
Sorting keys
Use ‘maphash’ to build up a list of keys, sort it, and then loop through the list:
(let ((nick-table (make-hash-table :test 'equal))
nicks)
(puthash "kensanata" "Alex Schroeder" nick-table)
(puthash "e1f" "Luis Fernandes" nick-table)
(puthash "pjb" "Pascal J. Bourguignon" nick-table)
(maphash (lambda (nick real-name)
(setq nicks (cons nick nicks)))
nick-table)
(mapcar (lambda (nick)
(concat nick " => " (gethash nick nick-table)))
(sort nicks 'string<)))
==> ("e1f => Luis Fernandes"
"kensanata => Alex Schroeder"
"pjb => Pascal J. Bourguignon")
Files
Read
A file can be inserted at point with ‘insert-file-contents’ or ‘insert-file-
contents-literally’. To get a file as a string,
(defun file-string (file)
"Read the contents of a file and return as a string."
(with-temp-buffer
(insert-file-contents file)
(buffer-string)))
On the chance that a buffer may already be actively visiting the file, consider using ‘find-file-
noselect’
(defun file-string (file)
"Read the contents of a file and return as a string."
(with-current-buffer (find-file-noselect file)
(buffer-string)))
Filter
Processing a file is usually done with a temporary buffer:
(defun process-file (file)
"Read the contents of a file into a temp buffer and then do
something there."
(when (file-readable-p file)
(with-temp-buffer
(insert-file-contents file)
(goto-char (point-min))
(while (not (eobp))
;; do something here with buffer content
(forward-line)))))
Write
To write something to a file you can create a temporary buffer, insert the things to write there and write
the buffer contents to a file. The following example read a string and a filename (with completion, but
doesn’t need to exist, see InteractiveCodeChar F) and write the string to that file.
(defun write-string-to-file (string file)
(interactive "sEnter the string: \nFFile to save to: ")
(with-temp-buffer
(insert string)
(when (file-writable-p file)
(write-region (point-min)
(point-max)
file))))
Stat
An interface to the kernel’s stat(2) is provided by the function file-attributes.
(let* ((attrs (file-attributes (buffer-file-name)))
(atime (nth 4 attrs))
(mtime (nth 5 attrs))
(ctime (nth 6 attrs)))
(concat "File last accessed on "
(format-time-string "%Y-%m-%d %T" atime) "\n"
"File last modified on "
(format-time-string "%Y-%m-%d %T" mtime) "\n"
"File last changed on "
(format-time-string "%Y-%m-%d %T" ctime) "\n"))
Deleting
(if (file-exists-p filename)
(delete-file filename))
Recursion
Here’s an example of using ‘directory-files’ to find all subdirectories in a subdirectory.
Traversing
A file-tree-walk function has been added to the Emacs development tree. Until it lands in your version,
you can use this:
(defun walk-path (dir action)
"walk DIR executing ACTION with (dir file)"
(cond ((file-directory-p dir)
(or (char-equal ?/ (aref dir(1- (length dir))))
(setq dir (file-name-as-directory dir)))
(let ((lst (directory-files dir nil nil t))
fullname file)
(while lst
(setq file (car lst))
(setq lst (cdr lst))
(cond ((member file '("." "..")))
(t
(and (funcall action dir file)
(setq fullname (concat dir file))
(file-directory-p fullname)
(walk-path fullname action)))))))
(t
(funcall action
(file-name-directory dir)
(file-name-nondirectory dir)))))
(defun walk-path-visitor (dir file)
"Called by walk-path for each file found"
(message (concat dir file)))
Path splitting
Splitting the path can be done with ‘split-string’ and with the slash. Previously, Emacs would
determine the character separating directory names with ‘directory-sep-char’. However, the
variable is obselete with Emacs 21.1.
(split-string default-directory "/")
==> ("" "usr" "share" "emacs" "22.2" "lisp" "")
For splitting a path variable, Emacs already has the ‘parse-colon-path’ function.
(parse-colon-path (getenv "PATH"))
==> ("/usr/lib/qt-3.3/bin/" "/usr/kerberos/bin/" "/usr/local/bin/" "/usr/bin/" "/
bin/" "/usr/local/sbin/" "/usr/sbin/" "/sbin/")
Processes
Running a program
Run a command without caring about its output.
(async-shell-command "emacs")
Run a command return and insert its output at point in the current buffer.
(insert (shell-command-to-string "date"))
Handling signals
Sockets
Tcp client
Tcp server
Perhaps EmacsEchoServer and EmacsDaytimeServer can be useful here. Also Edit with Emacs' edit-
server.el which is a more complete server implementation.
Keys
Call function bound to key
(funcall (key-binding (kbd "M-TAB")))
or
(call-interactively (key-binding (kbd "M-TAB")))
Test code
Sometimes you might want to insert some demonstration code in a module. The code should not be run
when the module is loaded via ‘require’ or ‘load’ but when you ‘eval-current-
buffer’. All you need to do add is add a test condition of ‘eval-buffer-list’:
(dont-compile
(when (eq (car eval-buffer-list) (current-buffer))
...))
This work is licensed to you under version 2 of the GNU General Public License. Alternatively, you
may choose to receive this work under any other license that grants the right to use, copy, modify, and/
or distribute the work, as long as that license imposes the restriction that derivative works have to grant
the same rights and impose the same restriction. For example, you may choose to receive this work
under the GNU Free Documentation License, the CreativeCommons ShareAlike License, the XEmacs
manual license, or similar licenses.
Please note our Privacy Statement.