https://wikemacs.org/api.php?action=feedcontributions&user=98.248.36.235&feedformat=atomWikEmacs - User contributions [en]2024-03-28T22:54:05ZUser contributionsMediaWiki 1.35.14https://wikemacs.org/index.php?title=Emacs_Lisp_Cookbook&diff=3046Emacs Lisp Cookbook2012-06-25T05:09:06Z<p>98.248.36.235: /* Strings vs buffer content */ Removed spammy text</p>
<hr />
<div>This page contains snippets of code that demonstrate basic [[Emacs Lisp]]<br />
programming operations in the spirit of O'Reilly's Cookbook<br />
series of books. For every task addressed, a worked-out solution<br />
is presented as a short, focused, directly usable piece of code.<br />
<br />
All this stuff can be found elsewhere, but it is scattered about in<br />
libraries, manuals, etc. It would be helpful to have it here in one<br />
spot.<br />
<br />
These recipes should be pastable into the '''*scratch*''' buffer so that<br />
users can hit '''C-j''' and evaluate them step by step.<br />
<br />
== Strings ==<br />
<br />
The empty string (zero-length string, null string, ...):<br />
<br />
<syntaxhighlight lang="lisp"><br />
(zerop (string-match "" "")) ;; O(n)<br />
==> t<br />
<br />
(string-equal "" "") ;; O(n)?<br />
==> t<br />
<br />
(equal "" "") ;; O(n)?<br />
==> t<br />
<br />
(zerop (length "")) ;; O(1)<br />
==> t<br />
<br />
(eq "" "") ;; O(1)<br />
==> t<br />
</syntaxhighlight><br />
<br />
As a space and performance optimization, Emacs keeps an intern-ed copy<br />
of the empty string as a single object<br />
<br />
<syntaxhighlight lang="lisp"><br />
(eq "" (purecopy ""))<br />
==> t<br />
<br />
(eq "" (propertize "" 'face 'italic))<br />
==> t<br />
</syntaxhighlight><br />
<br />
=== Strings vs buffer content ===<br />
<br />
While it is quite common in other programming languages to work on<br />
strings contained in variables in Emacs it is even more idiomatic to<br />
work on strings in buffers. That's why the following contains examples<br />
of both.<br />
<br />
=== Processing characters ===<br />
<br />
Reversing a string:<br />
<br />
<syntaxhighlight lang="lisp"><br />
(string-to-list "foo")<br />
==> (102 111 111)<br />
(reverse (string-to-list "foo"))<br />
==> (111 111 102)<br />
(apply 'string (reverse (string-to-list "foo")))<br />
==> "oof"<br />
</syntaxhighlight><br />
<br />
See CharacterProcessing and StringModification. See [[tr]] for an example of you sometimes need to mix strings and characters.<br />
<br />
Looking at characters in buffers:<br />
<br />
<syntaxhighlight lang="lisp"><br />
(with-temp-buffer<br />
(insert "abcdefg")<br />
(goto-char (point-min))<br />
(while (not (= (char-after) ?b))<br />
(forward-char))<br />
(point))<br />
==> 2<br />
</syntaxhighlight><br />
<br />
=== Trim whitespace ===<br />
<br />
Trim whitespace from the end of a string:<br />
<br />
<syntaxhighlight lang="lisp"><br />
(setq test-str "abcdefg ")<br />
(when (string-match "[ \t]*$" test-str)<br />
(message (concat "[" (replace-match "" nil nil test-str) "]")))<br />
</syntaxhighlight><br />
<br />
Trim whitespace from a string with a Perl-like chomp function:<br />
<br />
<syntaxhighlight lang="lisp"><br />
(defun chomp (str)<br />
"Chomp leading and tailing whitespace from STR."<br />
(while (string-match "\\`\n+\\|^\\s-+\\|\\s-+$\\|\n+\\'"<br />
str)<br />
(setq str (replace-match "" t t str)))<br />
str)<br />
</syntaxhighlight><br />
<br />
=== Splitting strings ===<br />
<br />
The 'split-string' function is defined in 'subr.el' as<br />
<br />
<source lang="lisp"><br />
(defun split-string (string &optional separators omit-nulls)<br />
...)<br />
</source><br />
<br />
where 'separators' is a regular expression describing where to split the string. 'separators' defaults to white-space characters (spaces, form feeds, tabs, newlines, carriage returns, and vertical tabs). If 'omit-nulls' is set as 't' then zero-length strings are deleted from output.<br />
<br />
<source lang="lisp"><br />
(split-string "1 thing 2 say 3 words 4 you" "[1-9]")<br />
==> ("" " thing " " say " " words " " you")<br />
</source><br />
<br />
Omitting nulls:<br />
<source lang="lisp"><br />
(split-string "1 thing 2 say 3 words 4 you" "[1-9]" t)<br />
(" thing " " say " " words " " you")<br />
</source><br />
<br />
=== Joining strings ===<br />
<br />
Use `mapconcat' to join a list into a string using a separator ("glue") between elements in the string.<br />
<br />
Example:<br />
<br />
<syntaxhighlight lang="lisp"><br />
(mapconcat 'identity '("" "home" "alex " "elisp" "erc") "/")<br />
==> "/home/alex /elisp/erc"<br />
</syntaxhighlight><br />
<br />
=== Serialization ===<br />
<br />
The basic idea is to convert forms to strings with `prin1-to-string' and convert it back from a string with `read'.<br />
<br />
<syntaxhighlight lang="lisp"><br />
(length (read (prin1-to-string (make-list 1000000 '(x)))))<br />
==> 1000000<br />
<br />
(read (prin1-to-string "Hello World!"))<br />
==> "Hello World!"<br />
</syntaxhighlight><br />
<br />
This only works in the simplest cases. Unfortunately, this doesn't work for all Emacs data types for programming or the editor.<br />
<br />
<syntaxhighlight lang="lisp"><br />
(read (prin1-to-string (make-hash-table))) ;; Error before Emacs 23.<br />
==> #s(hash-table size 65 test eql rehash-size 1.5 [...] data ())<br />
<br />
(read (prin1-to-string (current-buffer)))<br />
==> Lisp error: (invalid-read-syntax "#")<br />
</syntaxhighlight><br />
<br />
=== Formatting ===<br />
<br />
== Killing text ==<br />
<br />
As the Emacs Lisp Manual says, "Most of the kill commands are primarily for<br />
interactive use [...] When you need to delete text for internal<br />
purposes within a Lisp function, you should normally use deletion<br />
functions, so as not to disturb the kill ring contents."<br />
<br />
The following mimic the `kill-' commands but without disturbing the kill ring.<br />
<br />
=== Delete region ===<br />
<br />
The Lisp equivalent of `kill-region' (`C-w') but without kill ring side effects::<br />
<br />
<syntaxhighlight lang="lisp"><br />
(delete-region (region-beginning) (region-end))<br />
</syntaxhighlight> <br />
<br />
According to the ElispManual, "Few programs need to use the<br />
`region-beginning' and `region-end' functions." This is because<br />
Lisp code should not rely on nor "alter the mark unless altering<br />
the mark is part of the user-level functionality of the<br />
command. (And, in that case, this effect should be documented.)<br />
To remember a location for internal use in the Lisp program,<br />
store it in a Lisp variable. For example: [...]"<br />
<br />
<syntaxhighlight lang="lisp"><br />
(let ((beg (point)))<br />
(forward-line 1)<br />
(delete-region beg (point)))<br />
</syntaxhighlight><br />
<br />
=== Delete line ===<br />
<br />
The equivalent of `kill-line' (`C-k') but without kill ring side effects:<br />
<br />
<syntaxhighlight lang="lisp"><br />
(let ((beg (point)))<br />
(forward-line 1)<br />
(forward-char -1)<br />
(delete-region beg (point)))<br />
</syntaxhighlight><br />
<br />
Alternatively, replacing the `let' with `save-excursion'.<br />
<br />
<syntaxhighlight lang="lisp"><br />
(delete-region (point)<br />
(save-excursion<br />
(forward-line 1)<br />
(forward-char -1)<br />
(point)))<br />
</syntaxhighlight> <br />
<br />
Or simplest of all,<br />
<br />
<syntaxhighlight lang="lisp"><br />
(delete-region (point) (line-end-position))<br />
</syntaxhighlight> <br />
<br />
The examples with `forward-line' are shown because the paradigm is used later, see below.<br />
<br />
=== Delete line backwards ===<br />
<br />
The equivalent of killing the line backwards (`C-0 C-k') but without kill ring side effects:<br />
<br />
<syntaxhighlight lang="lisp"><br />
(let ((beg (point)))<br />
(forward-line 0)<br />
(delete-region (point) beg))<br />
</syntaxhighlight> <br />
<br />
Alternatively, replacing the `let' with `save-excursion'.<br />
<br />
<syntaxhighlight lang="lisp"><br />
(delete-region (save-excursion<br />
(forward-line 0)<br />
(point))<br />
(point))<br />
</syntaxhighlight> <br />
<br />
Or simplest of all,<br />
<br />
<syntaxhighlight lang="lisp"><br />
(delete-region (line-beginning-position) (point))<br />
</syntaxhighlight> <br />
<br />
<br />
=== Delete line to next line ===<br />
<br />
The equivalent of killing the line and the newline (`C-1 C-k') but without kill ring side effects:<br />
<br />
<syntaxhighlight lang="lisp"><br />
(let ((beg (point)))<br />
(forward-line 1)<br />
(delete-region beg (point)))<br />
</syntaxhighlight> <br />
<br />
Alternatively, replacing the `let' with `save-excursion'.<br />
<br />
<syntaxhighlight lang="lisp"><br />
(delete-region (point)<br />
(save-excursion<br />
(forward-line 1)<br />
(point)))<br />
</syntaxhighlight> <br />
<br />
=== Delete whole line ===<br />
<br />
The equivalent of `kill-whole-line' (`C-S-DEL') but without kill ring side effects:<br />
<br />
<syntaxhighlight lang="lisp"><br />
(let ((beg (progn (forward-line 0)<br />
(point))))<br />
(forward-line 1)<br />
(delete-region beg (point)))<br />
</syntaxhighlight> <br />
<br />
Alternatively, replacing the `let' with `save-excursion'.<br />
<br />
<syntaxhighlight lang="lisp"><br />
(delete-region (save-excursion<br />
(forward-line 0)<br />
(point))<br />
(save-excursion<br />
(forward-line 1)<br />
(point)))<br />
</syntaxhighlight> <br />
<br />
Or simplest of all,<br />
<br />
<syntaxhighlight lang="lisp"><br />
(delete-region (line-beginning-position) (line-end-position))<br />
</syntaxhighlight> <br />
<br />
=== Delete word ===<br />
<br />
The equivalent of `kill-word' (`M-d') but without kill ring side effects:<br />
<br />
<syntaxhighlight lang="lisp"><br />
(let ((beg (point)))<br />
(forward-word 1)<br />
(delete-region beg (point)))<br />
</syntaxhighlight> <br />
<br />
Alternatively, replacing the `let' with `save-excursion'.<br />
<br />
<syntaxhighlight lang="lisp"><br />
(delete-region (point)<br />
(save-excursion<br />
(forward-word 1)<br />
(point)))<br />
</syntaxhighlight> <br />
<br />
=== Delete sentence ===<br />
<br />
The equivalent of `kill-sentence' (`M-k') but without kill ring side effects:<br />
<br />
<syntaxhighlight lang="lisp"><br />
(let ((beg (point)))<br />
(forward-sentence 1)<br />
(delete-region beg (point)))<br />
</syntaxhighlight> <br />
<br />
Alternatively, replacing the `let' with `save-excursion'.<br />
<br />
<syntaxhighlight lang="lisp"><br />
(delete-region (point)<br />
(save-excursion<br />
(forward-sentence 1)<br />
(point)))<br />
</syntaxhighlight><br />
<br />
Забавно!недавно был очень похожий случай.есть функция:string addsign(char sign, const srnitg & s){1) return sign+s; // так нельзя2) return srnitg(s1)+s; //тоже нельзя3) return srnitg(s1, 1)+s;// только так можно... но блин не сразу допетриваешь }Решил это сам проверить, на компиляторе gcc 3.4.2.вот такая программулинка:#include <string>#include <stdio.h>using namespace std;string addsign(char s1, const srnitg & s){//1)return s1+s; // так нельзя//2)return srnitg(s1)+s; //тоже нельзя//3)return srnitg(s1, 1)+s;// только так можно... но блин не сразу допетриваешь//4)return srnitg(&s1, 1)+s;}int main(int n, char **args){ srnitg text = "1.9876"; srnitg res = addsign('-', text); puts(res.c_str()); return 0;}выдала мне срвсем другое:первый вариант (как "нельзя") выдал правильный результат: -1.9876, второй вариант - ошибку компиляции, а третий(который "только так и можно") дал нечто невразумительное - кучу смеющихся рожиц и в конце-число 1.9876. Мне даже непонятно, как у автора сообщения получился нормальный результат.Последний (4-ый, "мой" вариант) дал тоже верный результат: -1.9876<br />
<br />
== Dates and times ==<br />
<br />
=== Get today's date ===<br />
<br />
<syntaxhighlight lang="lisp"><br />
(format-time-string "%d %B %Y")<br />
</syntaxhighlight><br />
<br />
or <br />
<br />
<syntaxhighlight lang="lisp"><br />
(eshell/date)<br />
</syntaxhighlight><br />
<br />
I discovered Emacs in '97 when I was doing C++ depnmovleet for BellSouth (the Sun depnmovleet tools had great integration with either vi, Emacs or XEmacs editors). I'd been a hardcore vi user since 1990 (still am), but I could adapt Emacs (actually, for some reason I opted for XEmacs at the time can't remember why maybe it had better fonts) better for the job at hand. Syntax highlighting check (vi never had this it only arrived with vim), split buffers (top for the .h, bottom for the .cpp) check, tab completion for finding files check, nice macro record/playback features check, nice search/replace check,control behavior of tab key check, auto replace tabs with 4 spaces check. So, after a while you can imagine I crafted a pretty customized/personal .emacs file. I even continued to use emacs for a while after switching to Java in 2000 (it wasn't until Eclipse 2.0 before I switched to an IDE and left Emacs behind).Then I moved on, and for some reason the .emacs file got left behind. Shame really I haven't really used Emacs since it's not the same without my .emacs file and I don't have the time or inclination to re-create it.<br />
<br />
=== Conversions ===<br />
<br />
Read a date from a string.<br />
<br />
<syntaxhighlight lang="lisp"><br />
(let ((time (date-to-time "Tue, 27-Sep-83 12:35:59 EST")))<br />
(set-time-zone-rule t) ;; Use Universal time.<br />
(prog1 (format-time-string "%Y-%m-%d %T UTC" time)<br />
(set-time-zone-rule nil))) ;; Reset to default time zone.<br />
==> "1983-09-27 17:35:59 UTC"<br />
</syntaxhighlight> <br />
<br />
Decode a time object.<br />
<br />
<syntaxhighlight lang="lisp"><br />
(decode-time (date-to-time "Tue, 27-Sep-83 12:35:59 EST"))<br />
==> (59 35 13 27 9 1983 2 t -14400)<br />
</syntaxhighlight> <br />
<br />
Get the seconds from the unix epoch.<br />
<br />
<syntaxhighlight lang="lisp"><br />
(let ((time (date-to-time "13 Feb 2009 23:31:30 UTC")))<br />
(float-time time))<br />
==> 1234585890.0<br />
</syntaxhighlight> <br />
<br />
Find the date for seconds from the unix epoch.<br />
<br />
<syntaxhighlight lang="lisp"><br />
(format-time-string "%Y-%m-%d %T UTC" (seconds-to-time 1234585890))<br />
==> "2009-02-13 23:31:30 UTC"<br />
</syntaxhighlight> <br />
<br />
Find the date 30 seconds in the future.<br />
<br />
<syntaxhighlight lang="lisp"><br />
(format-time-string "%Y-%m-%d %T UTC" (time-add (current-time)<br />
(seconds-to-time 30)))<br />
==> "2012-02-13 10:07:11 UTC"<br />
</syntaxhighlight> <br />
<br />
Formatting elapsed time in years, days, hours, minutes and seconds.<br />
<br />
<syntaxhighlight lang="lisp"><br />
(format-seconds "%Y %D %h:%m:%s" (1- (* 367 24 3600)))<br />
==> "1 year 1 day 23:59:59"<br />
</syntaxhighlight> <br />
<br />
Find the days between two dates.<br />
<br />
<syntaxhighlight lang="lisp"><br />
(let ((days1 (time-to-days (date-to-time "Tue, 27-Sep-83 12:35:59 EST")))<br />
(days2 (time-to-days (date-to-time "2009-02-13 23:31:30 UTC"))))<br />
(- days2 days1))<br />
==> 9271<br />
</syntaxhighlight> <br />
<br />
Getting the day in the year.<br />
<br />
<syntaxhighlight lang="lisp"><br />
(time-to-day-in-year (current-time))<br />
==> 44<br />
</syntaxhighlight> <br />
<br />
Build a date based on the day of the year.<br />
<br />
<syntaxhighlight lang="lisp"><br />
(format-time-string "%j"<br />
(encode-time 0 0 0 44 1 2012))<br />
==> "044"<br />
</syntaxhighlight> <br />
<br />
=== Timers ===<br />
<br />
TODO<br />
<br />
Its funny that your example uses std::string beaucse it has the solution you're looking for.What you're trying to do is initialize a class member before initializing the base class, and you found that you can't. The typical way to get around this is to abandon hope of extending Foo and implement the wrapper in terms of Foo. (has-a vs. is-a) This solution has the annoyance of you needing to redeclare each and every method you want to use and then forwarding those calls to Foo, and you won't be able to use a FooWrapper in place of a Foo as well, meaning you may need to change a ton of references in your code. However, all you have to do is have FooWrapper expose its underlying Foo and you're good. (kinda like what string::c_str() does)Check out your copy of Effective C++. From the TOC I think item 40 discusses this.<br />
<br />
== Sequences ==<br />
<br />
Datatypes used to represent sequences of things:<br />
<br />
_____________________________________________<br />
| |<br />
| Sequence |<br />
| ______ ________________________________ |<br />
| | | | | |<br />
| | List | | Array | |<br />
| | | | ________ ________ | |<br />
| |______| | | | | | | |<br />
| | | Vector | | String | | |<br />
| | |________| |________| | |<br />
| | ____________ _____________ | |<br />
| | | | | | | |<br />
| | | Char-table | | Bool-vector | | |<br />
| | |____________| |_____________| | |<br />
| |________________________________| |<br />
|_____________________________________________|<br />
<br />
<br />
=== Lists ===<br />
<br />
List basics are explained on ListStructure.<br />
Lists can shrink and grow, but access to elements towards the end of the list is slow if the list is long.<br />
<br />
Use `cons' to append a new element to the front of a list.<br />
Use `nth' to access an element of the list.<br />
<br />
<syntaxhighlight lang="lisp"><br />
(let ((words '("fight" "foo" "for" "food!")))<br />
(when (string= "foo" (nth 1 words))<br />
(setq words (cons "bar" words)))<br />
words)<br />
==> ("bar" "fight" "foo" "for" "food!")<br />
</syntaxhighlight> <br />
<br />
See ListModification for more ways of changing a list.<br />
<br />
Iteration:<br />
<br />
<syntaxhighlight lang="lisp"><br />
(let ((result))<br />
(dolist (word '("fight" "foo" "for" "food!"))<br />
(when (string-match "o" word)<br />
(setq result (cons word result))))<br />
(nreverse result))<br />
==> ("foo" "for" "food!")<br />
</syntaxhighlight> <br />
<br />
Note how `cons' adds an element to the front of the list,<br />
so that usually the list has to be reversed after the loop.<br />
`nreverse' is particularly efficient because it does this<br />
destructively by swiveling pointers around. See<br />
DestructiveOperations for more about this.<br />
<br />
Copying:<br />
<br />
Use `copy-sequence' to make a copy of a list that won't change the<br />
elements of the original.<br />
<br />
<syntaxhighlight lang="lisp"><br />
(let* ((orig '((1 2) (3 4)))<br />
(copy (copy-sequence orig)))<br />
(setcdr copy '((5 6)))<br />
(list orig copy))<br />
==> (((1 2) (3 4)) ((1 2) (5 6)))<br />
</syntaxhighlight> <br />
<br />
However, the elements in the copy are still from the original.<br />
<br />
<syntaxhighlight lang="lisp"><br />
(let* ((orig '((1 2) (3 4)))<br />
(copy (copy-sequence orig)))<br />
(setcdr (cadr copy) '(0))<br />
(list orig copy))<br />
==> (((1 2) (3 0)) ((1 2) (3 0)))<br />
</syntaxhighlight> <br />
<br />
The function `copy-tree' is the recursive version of `copy-sequence'.<br />
<br />
<syntaxhighlight lang="lisp"><br />
(let* ((orig '((1 2) (3 4)))<br />
(copy (copy-tree orig)))<br />
(setcdr (cadr copy) '(0))<br />
(list orig copy))<br />
==> (((1 2) (3 4)) ((1 2) (3 0)))<br />
</syntaxhighlight> <br />
<br />
Filtering:<br />
<br />
Emacs Lisp doesn't come with a `filter' function to keep elements that satisfy a conditional and excise the elements that do not satisfy it. One can use `mapcar' to iterate over a list with a conditional, and then use `delq' to remove the `nil' values.<br />
<br />
<syntaxhighlight lang="lisp"><br />
(defun my-filter (condp lst)<br />
(delq nil<br />
(mapcar (lambda (x) (and (funcall condp x) x)) lst)))<br />
</syntaxhighlight> <br />
<br />
Therefore,<br />
<br />
<syntaxhighlight lang="lisp"><br />
(my-filter 'identity my-list)<br />
</syntaxhighlight> <br />
<br />
is equivalent to<br />
<br />
<syntaxhighlight lang="lisp"><br />
(delq nil my-list)<br />
</syntaxhighlight> <br />
<br />
For example:<br />
<br />
<syntaxhighlight lang="lisp"><br />
(let ((num-list '(1 'a 2 "nil" 3 nil 4)))<br />
(my-filter 'numberp num-list))<br />
==> (1 2 3 4)<br />
</syntaxhighlight> <br />
<br />
Actually the package cl-seq contains the functions `remove-if' and `remove-if-not'. The latter can be used instead of `my-filter'.<br />
<br />
<syntaxhighlight lang="lisp"><br />
(let ((num-list '(1 'a 2 "nil" 3 nil 4)))<br />
(remove-if-not 'numberp num-list))<br />
==> (1 2 3 4)<br />
<br />
(let ((num-list '(1 'a 2 "nil" 3 nil 4)))<br />
(remove-if 'numberp num-list))<br />
==> ((quote a) "nil" nil)<br />
</syntaxhighlight> <br />
<br />
As an example here is the quick sort algorithm:<br />
<br />
<syntaxhighlight lang="lisp"><br />
(defun quicksort (lst)<br />
"Implement the quicksort algorithm."<br />
(if (null lst) nil<br />
(let* ((spl (car lst))<br />
(rst (cdr lst))<br />
(smalp (lambda (x)<br />
(< x spl))))<br />
(append (quicksort (remove-if-not smalp rst))<br />
(list spl)<br />
(quicksort (remove-if smalp rst))))))<br />
<br />
(quicksort '(5 7 1 3 -9 8 7 -4 0))<br />
==> (-9 -4 0 1 3 5 7 7 8)<br />
</syntaxhighlight> <br />
<br />
Tranposing:<br />
<br />
Convert multiple lists into a list <br />
<br />
<syntaxhighlight lang="lisp"><br />
((lambda (&rest args)<br />
(mapcar (lambda (n)<br />
(delq nil (mapcar (lambda (arg) (nth n arg)) args)))<br />
(number-sequence 0 (1- (apply 'max (mapcar 'length args))))))<br />
'(1 2 3) '(a b c) '(A B C))<br />
==> ((1 a A) (2 b B) (3 c C))<br />
</syntaxhighlight> <br />
<br />
A more concise version is possible with the the higher-arity version of mapcar available with the `cl' library.<br />
<br />
<syntaxhighlight lang="lisp"><br />
((lambda (&rest args)<br />
(apply (function mapcar*) (function list) args))<br />
'(1 2 3) '(a b c) '(A B C))<br />
==> ((1 a A) (2 b B) (3 c C))<br />
</syntaxhighlight> <br />
<br />
Searching:<br />
<br />
Simply checking for existence of a value in a list can be done with<br />
`member' or `memq'.<br />
<br />
<syntaxhighlight lang="lisp"><br />
(let ((words '("fight" "foo" "for" "food!")))<br />
(car (member "for" words)))<br />
==> "for"<br />
<br />
(let ((re "\\wo\\b")<br />
(words '("fight" "foo" "for" "food!")))<br />
(consp (memq t<br />
(mapcar (lambda (s) (numberp (string-match re s))) words))))<br />
==> t<br />
</syntaxhighlight> <br />
<br />
In the latter, a more efficient algorithm would use a loop (a non-local exit).<br />
<br />
I don't think so. Normally you will open it up with latest veorisn, then save it in an earlier veorisn, that wat you can retain the 2008 veorisn with all the new options, and then convert it to an earlier. The improvements which are not handled by an earlier veorisn will be prompted when you try to save. You can lose layers or part of layers.<br />
<br />
=== Vectors ===<br />
<br />
Vectors are fixed in size but elements can be accessed in constant time.<br />
<br />
<syntaxhighlight lang="lisp"><br />
(let ((words ["fight" "foo" "for" "food!"]))<br />
(when (string= "foo" (aref words 1))<br />
(aset words 1 "bar"))<br />
words)<br />
==> ["fight" "bar" "for" "food!"]<br />
</syntaxhighlight> <br />
<br />
== Hashes ==<br />
<br />
Hashes map keys to values. In a way they are similar to alists, except<br />
they are more efficient for a large number of keys.<br />
<br />
More info is available on the HashMap page.<br />
<br />
=== Storing and retrieving keys and values ===<br />
<br />
By default, hash tables use `eql' to compare keys. This is not appropriate<br />
for strings: ##(eql "alex" "alex")## ==> nil. Thus, use `equal' in these cases:<br />
<br />
<syntaxhighlight lang="lisp"><br />
(let ((nick-table (make-hash-table :test 'equal)))<br />
(puthash "kensanata" "Alex Schroeder" nick-table)<br />
(gethash "kensanata" nick-table))<br />
==> "Alex Schroeder"<br />
</syntaxhighlight> <br />
<br />
Iterate:<br />
<br />
<syntaxhighlight lang="lisp"><br />
(let ((nick-table (make-hash-table :test 'equal))<br />
nicks)<br />
(puthash "kensanata" "Alex Schroeder" nick-table)<br />
(puthash "e1f" "Luis Fernandes" nick-table)<br />
(puthash "pjb" "Pascal J. Bourguignon" nick-table)<br />
(maphash (lambda (nick real-name)<br />
(setq nicks (cons nick nicks)))<br />
nick-table)<br />
nicks)<br />
==> ("pjb" "e1f" "kensanata")<br />
</syntaxhighlight> <br />
<br />
=== Sorting keys ===<br />
<br />
Use `maphash' to build up a list of keys, sort it, and then loop through<br />
the list:<br />
<br />
<syntaxhighlight lang="lisp"><br />
(let ((nick-table (make-hash-table :test 'equal))<br />
nicks)<br />
(puthash "kensanata" "Alex Schroeder" nick-table)<br />
(puthash "e1f" "Luis Fernandes" nick-table)<br />
(puthash "pjb" "Pascal J. Bourguignon" nick-table)<br />
(maphash (lambda (nick real-name)<br />
(setq nicks (cons nick nicks)))<br />
nick-table)<br />
(mapcar (lambda (nick)<br />
(concat nick " => " (gethash nick nick-table)))<br />
(sort nicks 'string<)))<br />
==> ("e1f => Luis Fernandes"<br />
"kensanata => Alex Schroeder"<br />
"pjb => Pascal J. Bourguignon")<br />
</syntaxhighlight> <br />
<br />
== Files ==<br />
<br />
=== Read ===<br />
<br />
Processing a file is usually done with a temporary buffer:<br />
<br />
<syntaxhighlight lang="lisp"><br />
(defun process-file (file)<br />
"Read the contents of a file into a temp buffer and then do<br />
something there."<br />
(when (file-readable-p file)<br />
(with-temp-buffer<br />
(insert-file-contents file)<br />
(goto-char (point-min))<br />
(while (not (eobp))<br />
;; do something here with buffer content<br />
(forward-line)))))<br />
</syntaxhighlight> <br />
<br />
On the chance that a buffer may already be actively visiting the file,<br />
consider using `find-file-noselect'<br />
<br />
<syntaxhighlight lang="lisp"><br />
(defun file-string (file)<br />
"Read the contents of a file and return as a string."<br />
(with-current-buffer (find-file-noselect file)<br />
(buffer-string)))<br />
</syntaxhighlight> <br />
<br />
=== Write ===<br />
<br />
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.<br />
<br />
<syntaxhighlight lang="lisp"><br />
(defun write-string-to-file (string file)<br />
(interactive "sEnter the string: \nFFile to save to: ")<br />
(with-temp-buffer<br />
(insert string)<br />
(when (file-writable-p file)<br />
(write-region (point-min)<br />
(point-max)<br />
file))))<br />
</syntaxhighlight> <br />
<br />
Maybe you are interested in word-count.el. It's cnirately to much foryour use-case but it is a great tool if you have some target lengthfor a document (e.g. diary entries).What I'm really missing in Emacs is some usage statistics. I canalready get an overview over my keybind habits with keyfreq but Iwould like that to be more comprehensive. Average buffer-length, timespent in different modes, time spent in files that are part of acertain directory, lines added etc. Maybe I'm just addicted to lifestatistics and this is not really useful. Who knows.<br />
<br />
=== Searching ===<br />
<br />
If you don't have grep, then you may need to write some Lisp which can find a match in a file.<br />
<br />
<syntaxhighlight lang="lisp"><br />
;; Visit file unless its already open.<br />
(with-current-buffer (find-file-noselect "~/.emacs")<br />
(save-excursion ;; Don't change location of point.<br />
(goto-char (point-min)) ;; From the beginning...<br />
(if (re-search-forward ".*load-path.*" nil t 1)<br />
(match-string-no-properties 0)<br />
(error "Search failed"))))<br />
==> "(add-to-list 'load-path \"/usr/share/emacs/site-lisp/\")"<br />
</syntaxhighlight> <br />
<br />
=== Filter ===<br />
<br />
=== Locking ===<br />
<br />
=== Stat ===<br />
<br />
An interface to the kernel's stat(2) is provided by the function file-attributes. The way times are represented may be a bit unexpected, though.<br />
<br />
=== Deleting ===<br />
<br />
<syntaxhighlight lang="lisp"><br />
(if (file-exists-p filename)<br />
(delete-file filename))<br />
</syntaxhighlight> <br />
<br />
=== Copy, move and rename ===<br />
<br />
== Directories ==<br />
<br />
=== Traversing ===<br />
<br />
<syntaxhighlight lang="lisp"><br />
(defun walk-path (dir action)<br />
"walk DIR executing ACTION with (dir file)"<br />
(cond ((file-directory-p dir)<br />
(or (char-equal ?/ (aref dir(1- (length dir))))<br />
(setq dir (file-name-as-directory dir)))<br />
(let ((lst (directory-files dir nil nil t))<br />
fullname file)<br />
(while lst<br />
(setq file (car lst))<br />
(setq lst (cdr lst))<br />
(cond ((member file '("." "..")))<br />
(t<br />
(and (funcall action dir file)<br />
(setq fullname (concat dir file))<br />
(file-directory-p fullname)<br />
(walk-path fullname action)))))))<br />
(t<br />
(funcall action<br />
(file-name-directory dir)<br />
(file-name-nondirectory dir)))))<br />
<br />
(defun walk-path-visitor (dir file)<br />
"Called by walk-path for each file found"<br />
(message (concat dir file)))<br />
<br />
(walk-path "~/" 'walk-path-visitor)<br />
</syntaxhighlight> <br />
<br />
=== Path splitting ===<br />
<br />
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.<br />
<br />
<syntaxhighlight lang="lisp"><br />
(split-string default-directory "/")<br />
==> ("" "usr" "share" "emacs" "22.2" "lisp" "")<br />
</syntaxhighlight><br />
<br />
For splitting a path variable, Emacs already has the `parse-colon-path' function.<br />
<br />
<syntaxhighlight lang="lisp"><br />
(parse-colon-path (getenv "PATH"))<br />
==> ("/usr/lib/qt-3.3/bin/" "/usr/kerberos/bin/" "/usr/local/bin/"<br />
"/usr/bin/" "/bin/" "/usr/local/sbin/" "/usr/sbin/" "/sbin/")<br />
</syntaxhighlight><br />
<br />
== Processes ==<br />
<br />
=== Running a program ===<br />
<br />
Run a command without caring about its output.<br />
<br />
<syntaxhighlight lang="lisp"><br />
(async-shell-command "emacs")<br />
</syntaxhighlight> <br />
<br />
Run a command and put its output in the current buffer.<br />
<br />
<syntaxhighlight lang="lisp"><br />
(shell-command "seq 8 12 | sort" t)<br />
10<br />
11<br />
12<br />
8<br />
9<br />
</syntaxhighlight> <br />
<br />
Run a command and put its output in a new buffer.<br />
<br />
<syntaxhighlight lang="lisp"><br />
(shell-command "seq 8 12 | sort"<br />
(get-buffer-create "*Standard output*"))<br />
</syntaxhighlight> <br />
<br />
Run a command return its output as a string.<br />
<br />
<syntaxhighlight lang="lisp"><br />
(shell-command-to-string "seq 8 12 | sort")<br />
</syntaxhighlight> <br />
<br />
XEmacs also comes with `exec-to-string'.<br />
<br />
=== Handling signals ===<br />
<br />
== Sockets ==<br />
<br />
=== Tcp client ===<br />
<br />
=== Tcp server ===<br />
<br />
Perhaps EmacsEchoServer and EmacsDaytimeServer can be useful here.<br />
<br />
== Keyboard events ==<br />
<br />
* Call function bound to key<br />
<br />
<syntaxhighlight lang="lisp"><br />
(funcall (key-binding (kbd "M-TAB")))<br />
</syntaxhighlight> <br />
<br />
or<br />
<br />
<syntaxhighlight lang="lisp"><br />
(call-interactively (key-binding (kbd "M-TAB")))<br />
</syntaxhighlight> <br />
<br />
[[Category:Customization]]<br />
[[Category:Intermediate]]</div>98.248.36.235