Pattern Matching: pcase

Haskell allows pattern matching. The following function counts one, two or many objects

simpleCount 1 = "One"
simpleCount 2 = "Two"
simpleCount _ = "Many"

You can use pattern matching to set base cases in recursive functions.

factorial 0 = 1
factorial n = n * factorial (n-1)

Haskell also allows guards. This if statement checks if someone is old enough to drive in the UK

canDrive x = if x<18 then  "Too young to drive" else "Old enough to drive"

Here it is using guards:

canDrive x
          | x<18 = "Too young to drive"       |
          | otherwise = "Old enough to drive" |

pcase

Emacs Lisp offers similar functionality with the pcase macro. It took me some time to understand the documentation, so here are few examples to get you going. They only scratch the surface, make sure you go back and read up properly afterwards.

(defun simple-count (x)
  (pcase x
    (1 "one")
    (2 "two")
    (_ "many")))

(mapcar #'simple-count '(1 2 5))
=> ("one" "two" "many")

Note that _ is used for the don’t care or wildcard case, rather than the more traditional t.

(defun can-drive (x)
  (pcase x
    ((guard (< x 18)) "Too young to drive")
    (_ "Old enough to drive")))

(can-drive 12)
=> "Too young to drive"

The following converts a test mark into a grade. Note the use of and to evaluate (pred stringp). If non nil, it binds x to msg. In other words, pcase can distinguish between marks and teacher comments.

(defun student-grade (x)
  (pcase x
    ((and (pred stringp) msg) msg)
    ((guard (< x 10)) "Fail")
    ((guard (< x 20)) "C")
    ((guard (< x 30)) "B")
    (_ "A")))

(mapcar #'student-grade '("Absent" 23 12 "off roll" 9 35))
=> ("Absent" "B" "C" "off roll" "Fail" "A")

Take a look at this example from the documentation. Again, it uses and to evaluate (pred stringp). If non nil, it binds x to msg.

So, if x is a string, print it; if x is a recognised symbol, print the associated message; otherwise print unknown return code.

(defun my-errors (x)
  (pcase x
    ;; string
    ((and (pred stringp) msg)
     (message "%s" msg))
    ;; symbol
    ('success       (message "Done!"))
    ('would-block   (message "Sorry, can't do it now"))
    ('read-only     (message "The shmliblick is read-only"))
    ('access-denied (message "You do not have the needed rights"))
    ;; default
    (code           (message "Unknown return code %S" code))))

(mapcar #'my-errors '(1 read-only "hello"))
=> ("Unknown return code 1" "The shmliblick is read-only" "hello")

Really Simple Scrivener Mode

Here’s a screenshot of a really simple Scrivener type view for org mode files. I set this up following my simple sidebar set up.

Scriv Sample

I’ve copied the code below (I’ve also joined the 21st Century and started uploading code to GitHub)

The code is actually very simple. To make notes appear in a side window, simply put the letters TR (for top right), BR (for bottom right) or HD (for heading) at the start of a title and then call org-tree-to-indirect-buffer on those headings. I’ve added a key binding to M-s i to make this easy. I like to have certain notes always visible while I’m typing, this system allows me to vary just which notes they are.

And that’s it. Very simple, but I’ve found this very useful when writing.

(defun my-sidebars()
  (setq fit-window-to-buffer-horizontally t)
  (setq window-resize-pixelwise t)

  (setq display-buffer-alist
        `(("\\*Occur\\*" display-buffer-in-side-window
           (side . left) (slot . 0)
           (window-width . fit-window-to-buffer)
           (preserve-size . (t . nil)) 
           (window-parameters . ((no-delete-other-windows . t))))
          (".*\\.org-HD." display-buffer-in-side-window
           (side . top) (slot . 0) 
           (preserve-size . (t . nil)) 
           (window-parameters . ((no-delete-other-windows . t))))
          (".*\\.org-TR." display-buffer-in-side-window
           (side . right) (slot . -1) 
           (preserve-size . (t . nil)) 
           (window-parameters . ((no-delete-other-windows . t))))
          (".*\\.org-BR." display-buffer-in-side-window
           (side . right) (slot . 1) 
           (preserve-size . (t . nil)) 
           (window-parameters . ((no-delete-other-windows . t)))))))

(defun my-indirect-buffer ()
  (interactive)
  (let ((current-prefix-arg 4))                       ;; emulate C-u
    (call-interactively 'org-tree-to-indirect-buffer)))

(defun scriv()
  (interactive)
  (when (require 'wc-mode nil t)
    (wc-mode))
  (toggle-frame-maximized)
  (my-sidebars)
  (global-set-key (kbd "M-s i") 'my-indirect-buffer))

Sidebar for Emacs Org Mode

It would be nice to have a sidebar when using org mode. The sidebar would display the headlines of an org file. When a headline is selected, the subheadings and text would be displayed in another buffer. 

You can currently do this by using C-c C-x b which is bound to (org-tree-to-indirect-buffer). The command opens a subtree in an indirect buffer which is sort of what I’m looking for, but you have to enter the command each time you land on a new headline.

You can make the process automatic by adding a hook as follows:

(add-hook 'post-command-hook #'org-tree-to-indirect-buffer nil :local)

The solution works, but it’s not quite there.

Searching the internet I found a useful suggestion from the delightfully named My Other Soup’s a Borscht:

M-x occur then search for the regexp "*+ " (note the space at the end)

This gives more of the functionality I want and has the advantage of being customizable. One problem: I wanted the sidebar to appear on the left hand side.

So I looked a little further and discovered side windows

My first thought was so what? I can already do that by splitting windows. The advantage of side windows is that you can set them to stay in position and to fix the buffer they display. No more losing your layout when you hit C-x 1.

If the above seems a little confusing (and it did to me at first) there’s an example of what you can do here in the Emacs Manual 

So I combined the two things I’d learned and came up with the following function:

(defun my-sidebar-occur()
 (interactive)
 (setq fit-window-to-buffer-horizontally t)
        (setq window-resize-pixelwise t)

        (setq
       display-buffer-alist
       `(("\\*Occur\\*" display-buffer-in-side-window
          (side . left) (slot . 0) (window-width . fit-window-to-buffer)
          (preserve-size . (t . nil)) 
          (window-parameters . ((no-delete-other-windows . t)))))))

Here’s a video of the process in action.

One last thing. org-sidebar appears to solve my problem, but at the time of writing it’s still a little buggy. It’s nicely done though and could well become the standard in the future. Until then, I’ll use my workaround.

Common Lisp Loops

I can’t think why you wouldn’t use the Common Lisp loop macro in Emacs. Don’t forget to (require ‘cl-lib)

Simple Loops

;; keywords: to, upto, below, downto, above, by
;; keywords: collect, append, nconc, count, sum, maximize, minimize

(cl-loop
    do (princ 1))
=> 111111... infinite loop

(cl-loop repeat 5
     do (princ 1)
     (princ 2))
=> 1212121212

(cl-loop for i from 1 below 10
     maximize i)
=> 9

(cl-loop for x from 9 downto 1
     collect x)
=> (9 8 7 6 5 4 3 2 1)

(cl-loop for i from 10 above 1 by 2
     collect i)
=> (10 8 6 4 2)

Looping over Sets and Arrays

;; keywords: in, on, across, by
;; Remember in for lists
;; across for vectors

(cl-loop for l in '(1 2 3 4 5)
     do (princ l))
=> 12345

(cl-loop for l in '(1 2 3 4 5) by #'cddr
     collect l)
=> (1 3 5)

(cl-loop for l on '(1 2 3 4 5)
     collect l)
=> ((1 2 3 4 5) (2 3 4 5) (3 4 5) (4 5) (5))

(cl-loop for l on '(1 2 3 4 5) by #'cddr
     collect l)
=> ((1 2 3 4 5) (3 4 5) (5))

;; Remember that a string is an array in lisp, so...
;; Add up the digits in 90125
(cl-loop for d across "90125"
    sum (- d 48))
=> 17

Destructuring

(cl-loop for (a nil) in '((1 2) (2 3) (3 4))
     collect a)
=> (1 2 3)

(cl-loop for (a b) in '((1 2) (2 3) (3 4))
     collect (* a b))
=> (2 6 12)

(cl-loop for (a b) on '(1 2 3 4 5) while b
      collect (+ a b))
=> (3 5 7 9)

(cl-loop for (a b) on '(1 2 3 4 5) by #'cddr while b
     collect (+ a b))
=> (3 7)

Hashtables

(cl-loop for key being the hash-keys of myhashtable
        using (hash-value value)
        do (princ value))

Parallel fors

(cl-loop for i from 1 to 5
     for l in '(a b c d)
     collect (list i l))
=> ((1 a) (2 b) (3 c) (4 d))

(cl-loop for i from 1 to 5
     for j from 2 to 10 by 2
     collect (* i j))
=> (2 8 18 32 50)

Nested fors

(cl-loop for i from 1 to 5
     collect (cl-loop for j from 1 to 5
             collect (* i j)))
=> ((1 2 3 4 5) (2 4 6 8 10) (3 6 9 12 15) (4 8 12 16 20) (5 10 15 20 25))

(cl-loop for i from 1 to 5
     append (cl-loop for j from 1 to 5
             collect (* i j)))
=> (1 2 3 4 5 2 4 6 8 10 3 6 ...)

(cl-loop for i from 1 to 5
     collect (cl-loop for j from 1 to 5
             sum (* i j)))
=> (15 30 45 60 75)

(cl-loop for i from 1 to 5
     sum (cl-loop for j from 1 to 5
             sum (* i j)))
=> 225

Selection

;; if, when, unless

(cl-loop for i from 1 to 20
     unless (cl-evenp i) collect i)
=> (1 3 5 7 9 11 13 15 17 19)

(cl-loop for i from 1 to 20
     when (= (% i 3) 0) collect i into fizz
     when (= (% i 5) 0) collect i into buzz
     finally return (list fizz buzz))
=> ((3 6 9 12 15 18) (5 10 15 20))

(cl-loop for i from 1 to 20
     if (and (= (% i 3) 0) (= (% i 5) 0)) collect i into fizzbuzz
     else if (= (% i 3) 0) collect i into fizz
     else if (= (% i 5) 0) collect i into buzz
     finally return (list fizz buzz fizzbuzz))
=> ((3 6 9 12 18) (5 10 20) (15))

(cl-loop for i from 1 to 10
     if (cl-evenp i)
     collect i into evens
     and sum i into evensum
     else
     collect i into odds
     and sum i into oddsum
     finally return (list evens evensum odds oddsum))
=> ((2 4 6 8 10) 30 (1 3 5 7 9) 25)

Find c from comp where diff is never a member of squares
(cl-loop for c in comp
     if  (cl-loop for p in pri
              for diff = (/ (- c p) 2)
              never (member diff squares))
     collect c)

Then Iteration

(cl-loop for i from 1 to 5
     for square = (* i i)
     collect square)

;; Though you'd be better with
(cl-loop for i from 1 to 5
     collect (* i i))

;; However, this leads to Triangle Numbers
(cl-loop for n from 1 to 10
     for triangle = 1 then (+ triangle n)
     collect triangle)
=> (1 3 6 10 15 21 28 36 45 55)

(cl-loop for x = 0 then y
     for y = 1 then (+ x y)
     while (< y 30)
     collect y)
=> (1 2 4 8 16)

;; Fibonacci Sequence (note the and)
(cl-loop for x = 0 then y
     and y = 1 then (+ x y)
     while (< y 30)
     collect y)
=> (1 1 2 3 5 8 13 21)

Termination

;; while, until, always, never, and thereis

while and until are straightforward

(cl-loop for n from 1
for tri = 1 then (+ tri n)
until (> (divs tri) 500)
finally return tri)

never, thereis and always are shorthand for a combination of when-return

(defun isprime(n)
  (cond
   ((< n 2) nil)
   ((= n 2) t)
   ((cl-evenp n) nil)
   (t
    (cl-loop for i from 3 to (sqrt n) by 2
         never (= (% n i) 0)))))

Code is Poetry

Brian Bilston has written a History of Modern Art in Poetry.  I  wondered what it would be like to do something similar in various programming languages.

Here’s the original poem:

Roses are red
Violets are blue
Sugar is sweet
And so are you

Haskell

Here’s the poem constructed using a zip statement in Haskell

Prelude> zip ["roses","violets","sugar","you"]["red","blue","sweet","sweet"]
[("roses","red"),("violets","blue"),("sugar","sweet"),("you","sweet")]

The list produced holds the relationship that sugar is sweet and you are sweet. The comparison between “you” and sugar is not made clear.

Lisp

Here’s the poem stored as an alist in Lisp

(setq poem '(("roses" . "red") ("violets" . "blue") ("sugar" . "sweet")("you" . "sweet")))
(mapcar (lambda (x) (concat (car x) " are " (cdr x))) poem)

I’ve gone one stage further here, using a mapcar function to produce something that looks a little bit more like the original poem, however we’re still missing the connection between “you” and sugar.

("roses are red" "violets are blue" "sugar are sweet" "you are sweet")

Python

Of course, sugar are sweet isn’t right.   Let’s try some Python.

poem = {"roses":"red","violets":"blue","sugar":"sweet","you":"sweet"}

for key, value in poem.items():
    if key == "sugar":
        print(key, "is" ,value)
    else:
        print(key, "are", value)

This output is at least grammatically correct.

roses are red
violets are blue
sugar is sweet
you are sweet

Java

Java can do something similar using a HashMap

Map<String, String> poem = new HashMap<String, String>();

        poem.put("roses", "red");
        poem.put("violets", "blue");
        poem.put("sugar", "sweet");
        poem.put("you", "sweet");

        for (Map.Entry<String, String> entry : poem.entrySet()) {
            if(entry.getKey().equals("sugar")){
                System.out.println(entry.getKey() + " is " + entry.getValue());
            } else{
                System.out.println(entry.getKey() + " are " + entry.getValue());
            }
            
        }

But we’re still no closer to conveying the connection between “you” being sweet, just like sugar is sweet.

Fortunately, Java allows us to use some object oriented design to better convey the meaning of the poem.

In the example below I’ve used an interface to allow sweetness to be applied to both sugar and to the special one to whom the poem refers.  The comparison is at last made clear.  As there can only be one true love, it seemed reasonable to make a singleton class for TheOne, inherited from a regular person.

Run the code and the poem is printed out properly, just like the original.  More importantly though, the concepts to which the poem refers are properly encapsulated and related.

The original poem was only 4 lines long.  My implementation takes 80 lines, but I think you’ll agree I’ve done a rather better job, providing clarity and removing any ambiguity.

public class Love {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        Flower [] rose = new Flower[12]; // 12 roses in a bunch
        Flower [] violet = new Flower[30]; // more violets in bunch
        Sugar sugar = new Sugar();
        TheOne myLove = TheOne.getInstance();  // Singleton class
        // There can only be one true love
        
        rose[0] = new Flower();
        rose[0].setColour("red");  // colour is static so only need
                                    // to instantiate one here
        
        violet[0] = new Flower();
        violet[0].setColour("blue");
        
        System.out.println("Roses are " + rose[0].getColour());
        System.out.println("Violets are " + violet[0].getColour());
        System.out.println(sugar.sweet());
        System.out.println(myLove.sweet());
    }
    
}

class Flower {
    private static String colour;
    
    public void setColour(String colour){
        this.colour = colour;
    }
    
    public String getColour (){
        return colour;
    }
}

class Sugar implements Sweetness {

    @Override
    public String sweet() {
        return "Sugar is sweet";
    }
    
}

class Person {
    public String sweet()
    {
        return "Not sweet";
    }
}

class TheOne extends Person implements Sweetness{
    private static TheOne instance = null;
    
    private TheOne()
    {
        
    }
    
    public static TheOne getInstance()
    {
        if(instance == null)
            instance = new TheOne();
        
        return instance;
    }

    @Override
    public String sweet() {
         return "And so are you";
    }
}

interface Sweetness {
    String sweet();
}

Only One .emacs

I keep my Emacs init files on Dropbox – that way I only have to maintain one set of files no matter how many machines I run Emacs on. My local .emacs file simply loads the init files on Dropbox.

One minor problem is that Dropbox can have a different path according to the operating system.

This is easily resolved using the system-type variable. For my set up, I’m only interested in whether I’m running on a ‘gnu/linux or a ‘windows-nt system.
The following code sets the path of my Dropbox folder and then uses the format function to append the appropriate init files to that location. The individual files are then loaded. I’ve split my .emacs file across several files for tidiness and convenience. Even so, it still manages to degenerate into a mess when I’m not watching it.

1: (if (eq system-type 'windows-nt)
2:     (setq dot-emacs-files "c:/Users/username/Dropbox/emacs")
3:   (setq dot-emacs-files  "~/Dropbox/emacs")
4: )
5: 
6: (load (format "%s/%s" dot-emacs-files "packages-dot-emacs.el"))
7: (load (format "%s/%s" dot-emacs-files "org-dot-emacs.el"))
8: (load (format "%s/%s" dot-emacs-files "common-dot-emacs.el"))
9: (load (format "%s/%s" dot-emacs-files "elisp.el"))

Manipulating Strings: Yodaizer

Let’s make a function that talks like Yoda. It will take a sentence like “This is instructive” and output “Instructive, this is.”

To do this we’ll need to teach Emacs some adjectives:

1: (setq adjectives '("happy" "sad" "fun" "clever" "instructive"))

We’ll split the sentence into a list of words, and we’ll prepare an empty list for the result of the function:

1: let (  (result '())
2:         (words (split-string s))
3:      )

We’ll use a dolist macro to traverse the words, checking for adjectives, and we’ll use the old lisp trick of concatenating the word we’ve found at the front or the back of the result list, as appropriate.

1: (dolist (element words result)
2: (if (member element adjectives) (setq result (concat (capitalize element) ", " result)) (setq result (concat result " " element))  )
3: )

Lastly, we won’t forget to captalize the first word of the sentence and add a comma…

1: (concat (capitalize element) ", " result)

Put it together and we get the finished function:

 1: (defun yodaizer (s)
 2: "Moves adjective to the front of the sentence."
 3: (interactive "sInput a phrase:")
 4: (setq adjectives '("happy" "sad" "fun" "clever" "instructive"))
 5: 
 6: (let (  (result '())
 7:         (words (split-string s))
 8:      )
 9: (dolist (element words result)
10: (if (member element adjectives) (setq result (concat (capitalize element) ", " result)) (setq result (concat result " " element))  )
11: )
12: (message result)))

that was instructive

Instructive, that was

Next: Date and Time

Find and Replace in a Region: Strip Smart Quotes in a Region

These are smart quotes: “ ” ‘ ’

The easiest way to get Emacs to automatically insert smart-quotes is to use smart-quotes mode.

I prefer not to use smart-quotes mode, however. I find it easier when editing to stick to plain quotes (” and ‘) and then to let org-mode export convert to smart quotes.

What makes things awkward is finding text with smart-quotes already included. I wrote the following function to strip those smart-quotes out. It narrows to a region, uses save-restriction to remember how things were before the narrowing and then uses two regex searches to find first double quotes and then single quotes, replacing both with plain quotes.

 1: (defun strip-smart-quotes (rStart rEnd)
 2:   "Replace smart quotes with plain quotes in text"
 3:   (interactive "r")
 4:   (save-restriction
 5:   (narrow-to-region rStart rEnd)
 6:   (goto-char (point-min))
 7:   (while (re-search-forward "[“”]" nil t) (replace-match "\"" nil t))
 8:   (goto-char (point-min))
 9:   (while (re-search-forward "[‘’]" nil t) (replace-match "'" nil t))
10: ))
Before: “You put your smart-quotes in, you take your smart-quotes out… ”
After: "You put your smart-quotes in, you take your smart-quotes out… "

Date and Time

1 Reading Date and Time

This is how elisp stores a time:

(current-time) => (21209 38073 267139)

The first two numbers are the high and low bits of an integer number giving seconds since the epoch (0:00 January 1, 1970 UTC). The last number is microseconds and may be ommitted. There may be a fourth number representing picoseconds.
decode-time puts this into a more user friendly format:

(decode-time (current-time)) => (30 38 20 17 1 2014 5 nil 0)

The individual values are (SEC MINUTE HOUR DAY MONTH YEAR DOW DST ZONE) DOW is DOW of week DST is t if Daylight saving time is in effect ZONE is an integer indicating the number of seconds east of Greenwich.
format-time-string gives a more everyday format:

(format-time-string "%d/%m/%Y %H:%M:%S" (current-time)) => "17/01/2014 20:38:43"

Or, if you’re really in a hurry:

(current-time-string) => "Fri Jan 17 20:38:54 2014"

2 Setting a Date or Time

Set a time using date-to-time

(date-to-time "May 20 2011 19:30:00") => (19926 45864)

Note that the date strings format is dependent on your machine’s locale settings. For example, the following may be necessary. For more about locales, read this post.

(date-to-time "20 May 2011 19:30:00")

Enter a date using parse-time-string

(setq concert (parse-time-string "May 20 2011 19:30:00")) => (0 30 19 20 5 2011 nil nil nil)

Unlike date-to-time, parse-time-string allows you to omit the time value :

(setq birthday (parse-time-string "July 29 1953")) => (nil nil nil 29 7 1953 nil nil nil)

Here are some times:

(setq five-seconds (seconds-to-time 5))
(setq ninety-minutes (seconds-to-time (* 60 90)))
(setq one-day (seconds-to-time (* 60 60 24)))

The last can be more easily entered as:

(setq one-day (days-to-time 1))

Which leads to

(setq one-week (days-to-time 7))

and so on…

3 Converting Time Values

Use encode-time and decode-time to switch between formats

(encode-time 0 30 19 20 5 2011) => (19926 45864)
(decode-time '(19926  45864)) => (0 30 19 20 5 2011 5 t 3600)

4 Calculations on Dates and Times

Use time-add to add two times together.
Here’s the time a concert starts

(setq concert (date-to-time "May 20 2011 19:30:00"))

Suppose the concert lasts two hours (or 2 x 60 x 60 seconds). You can work out the time the concert ends as follows

(time-add concert (seconds-to-time (* 2 60 60)))

Let’s just check that worked

(format-time-string "%d/%m/%Y %H:%M:%S" (time-add concert (seconds-to-time (* 2 60 60)))) => "20/05/2011 21:30:00"

Suppose you know the start and end times of the concert. Use time-subtract to work out the duration:

(setq concert-start (date-to-time "May 20 2011 19:30:00"))
(setq concert-end (date-to-time "May 20 2011 22:25:00"))
(format-time-string "%H:%M:%S"(time-subtract concert-end concert-start)) => "02:55:00"

See Also

3 Interactive Functions that work on Regions

1 Start Point, End Point and Contents of a Region

The following function prints the contents of the selected region, together with its start and end points.

1: (defun region-contents (rStart rEnd)
2:   "Prints region contents of region selected, and the start and end positions of that region"
3:   (interactive "r")
4:   (setq rStr (buffer-substring rStart rEnd))
5:   (message "The string of the selected region is %s.  It starts at  %d and ends at %d"  rStr  rStart rEnd)
6: )

2 Iterate through the words in a region

You might want to iterate through the words in a selected region. The following function gives an example of this, it prints out the words in the region in reverse order.

1: (defun reverse-region-message (rStart rEnd)
2:   "Reverses order of words"
3:   (interactive "r")
4:   (setq myStr (buffer-substring rStart rEnd))
5:   (setq myWords (split-string myStr))
6:   (setq reversed (reverse myWords))
7:   (message (mapconcat 'identity reversed " "))
8: )

Note the use of the following functions:

  • split-string: splits the string into a list of words
  • reverse: reverses a list
  • mapconcat: Convert a list into a string

It’s interesting to compare the mapconcat function with the concat function. Note that concat does not accept lists, as you might expect at first glance. You can get round this using the apply function.

(concat "this" "that" "other") => "thisthatother"
(concat '("this" "that" "other")) => error
(apply 'concat '("this" "that"  "other")) => "thisthatother"
(mapconcat 'identity '("this" "that" "other") " ") => "thisthatother"

Here’s the function, rewritten to delete the selected region and to replace it with the words in reverse order.

1: (defun reverse-region (rStart rEnd)
2:   "Reverses order of words"
3:   (interactive "r")
4:   (setq myStr (buffer-substring rStart rEnd))
5:   (delete-region rStart rEnd)
6:   (setq myWords (split-string myStr))
7:   (setq reversed (reverse myWords))
8:   (insert (mapconcat 'identity reversed " "))
9:  )

3 Iterate through the letters in a region

You can spend a lot of time writing code to solve a problem only to find that Emacs Lisp already provides a function to do what you want.
For example, suppose you want to iterate through the letters in a region to convert SEPARATE to S-E-P-A-R-A-T-E. The easiest way is to use the mapconcat function, as seen in the previous section.

(mapconcat 'string "SEPARATE" "-")

Here’s the separator as a function that operates on the selected region.

1: (defun region-seperator (rStart rEnd)
2:   "Reverses order of words"
3:   (interactive "r")
4:   (setq rStr (buffer-substring rStart rEnd))
5:   (delete-region rStart rEnd)
6:   (insert (mapconcat 'string rStr "-"))
7:  )

3.1 string-to-list, mapcar and apply

The function string-to-list converts a string to characters.

(setq rStr (string-to-list "example")) => (101 120 97 109 112 108 101)

use char-to-string to convert a character code to a string

(char-to-string 101) => "e"

Note the use of apply, as discussed previously.

(apply 'string (reverse (string-to-list "example"))) => "elpmaxe"

Note that apply returns a value. If you want a list of characters, use mapcar

(mapcar 'char-to-string (string-to-list "example")) => ("e" "x" "a" "m" "p" "l" "e")

Remember, mapcar returns a list, apply returns a value. Many of the errors you make when beginning come down to confusing the two return types.
Finally, use a lambda function (discussed later) for complex functions in mapcar

(mapcar 'char-to-string (mapcar '(lambda (x) (+ x 1)) (string-to-list "foo")))

4 Enclose a Region

This tutorial has been written using emacs org mode. The code samples are marked up using the tags

#+BEGIN_SRC emacs-lisp -n
and
#+END_SRC

I wrote the following function to make the markup easier. Now I just select the region and run the function. The appropriate tags are placed at the start and end of the region.

1: (defun myMark-elisp-region (rStart rEnd)
2:   "Mark region as Elisp source code for org mode export."
3:   (interactive "r")
4:   (save-excursion
5:     (goto-char rEnd) (insert "\n#+END_SRC\n")
6:     (goto-char rStart) (insert "#+BEGIN_SRC emacs-lisp -n\n"))
7: )

Note the use of the save-excursion function to return the point to where it was before the function was run. Note also the way the above function is laid out. An interesting exercise is to reverse the order of lines 5 and 6. See if you can figure out why the function doesn’t work as you might expect.

5 Find and Replace in a Region: Strip Smart Quotes in a Region

These are smart quotes: “ ” ‘ ’
For editing purposes I sometimes need to replace these with the plain quotes ” and ‘. I only want this to replacement to occur on a specified region of text, not on the whole buffer.
Here’s a function to do this. It narrows to a region, uses save-restriction to remember how things were before the narrowing and then uses two regex searches to find first double quotes and then single quotes, replacing both with plain quotes.

 1: (defun strip-smart-quotes (rStart rEnd)
 2:   "Replace smart quotes with plain quotes in text"
 3:   (interactive "r")
 4:   (save-restriction
 5:   (narrow-to-region rStart rEnd)
 6:   (goto-char (point-min))
 7:   (while (re-search-forward "[“”]" nil t) (replace-match "\"" nil t))
 8:   (goto-char (point-min))
 9:   (while (re-search-forward "[‘’]" nil t) (replace-match "'" nil t))
10: ))

6 Choosing between Operating on a Region or the Whole Buffer

The previous example only stripped smart quotes from the selected region. This function uses the (when (uses-region-p) …) construction to determine whether or not a region is selected. If no region is selected, the whole buffer is operated upon.

 1: (defun region-or-buffer ()
 2:  "Strip smart quotes from region, or whole buffer if region not set"
 3:  (interactive)
 4:  (save-excursion
 5:    (save-restriction
 6:      (when (use-region-p) (narrow-to-region (region-beginning) (region-end)))
 7:      (goto-char (point-min))
 8:      (while (re-search-forward "[“”]" nil t) (replace-match "\"" nil t))
 9:      (goto-char (point-min))
10:      (while (re-search-forward "[‘’]" nil t) (replace-match "'" nil t))
11: )))

Next: Yodaizer – Manipulating Strings Example