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

7 GTD: Doing

  • If you’re not totally sure what your job is it will always feel overwhelmed
  • Lack of time is not the major issue. Things rarely get stuck because of lack of time, they get stuck because the doing of them has not been defined
  • You can’t do a project, you can only do the action steps it involves

It’s very easy to get caught up in your GTD system and to forget about the actual doing part.

Decide what to do according to the following four criteria:
– Context
– Time Available
– Energy Available
– Priority

If you’ve tagged your tasks properly you’ll have, for example:

Context: a list of phone calls to make when you’re on the phone, or emails to browse whilst sitting on a train

Time Available: A list of quick jobs to do when you have the odd five minutes

Energy Available: A list of jobs requiring little mental or creative horsepower

Priority: A calendar telling you what you must do today

I find it especially useful to tag the five minute jobs and the low energy jobs. I usually do the five minute jobs when I’ve got a little spare time before teaching a class, the low energy jobs can be fun things to read or enjoy.

Related Links

6 GTD: Reviewing

Now that you’ve got yourself organised, you need to remind yourself what the jobs are that you need to do.

Review appropriate lists at appropriate times. For example

  • Check Calendar at the start of the day
  • Look at General Tasks to be done
  • When on the phone, look for tasks marked phone
  • When in a meeting, look at the tasks for that meeting

Review your whole system once a week.

  • Check Calendar for forthcoming events
  • Check projects have a Next Action
  • Check Next Actions are being performed
  • Check Wait list to see if anything needs chasing
  • Check Maybe list to see if anything is ready to proceed
  • Pause or drop projects that aren’t going ahead

If you’re not up to date at the weekly review you won’t be able to convince yourself that your system is remembering for you. You’ll go back to worrying that you’ve forgotten something.

Related Links

5 GTD: Organize

One mistake I made at the beginning was to try and process and organize as I collected. What I mean by this is I’d try and write jobs under different headings in my GTD file as I was collecting them. This is a mistake. One of the key principles of GTD is you only do one thing at a time. If you’re collecting, you shouldn’t be organizing.  Collecting is dealt with in a previous post.  Let’s assume you’ve collected, now it’s time to organize.

Organizing involves putting the jobs into the appropriate categories: writing them under the appropriate heading, if you like.

Here are example headings I use for my general GTD file:

  • General Tasks
  • Dated (Scheduled) Tasks
  • Waiting Tasks
  • Meeting with Julie
  • Meeting with Links
  • Meeting with Craig
  • Maybe
  • View, Watch, Read
  • Long Term

The Dated Tasks should go in your calendar.

The Waiting Tasks are those for which I’m awaiting a response. For example, a reply to an email or an answer to a query.

Note how I have separate headings for regular meetings with different people.

The View, Watch, Read heading is for books, video clips, articles I would like to read if I had more time. I look at the things here when I have the odd ten minutes.

The Maybe heading is for things I don’t have time to do at the moment. I review this occasionally, and may get round to them someday.

Long Term tasks are mainly reminders of things that will happen in at least a year’s time: reminders of contract renewals etc.

I also have a reference file and a projects file. These two have a section all to themselves, later on in this tutorial.

Organising is important. It might seem from the above that all you’ve done is simply moved your todo list around, but what you’ve really done is separated out your “inbox”. You’ve separated the reference from the actions, and eliminated the chaff. This is the secret of GTD. It’s simple but effective.

Related Links

4 GTD: Process

Processing means going through the jobs you’ve collected and getting them into a suitable format. If the job is one which would be quicker to do right away than to process, then do it.

Rules for Processing

  • Go through your list of unprocessed tasks
  • Process the top item first
  • Process one item at a time
  • Never put anything back into “in”

The key question when processing is to think what’s the Next Action? Too many jobs don’t get done because people aren’t clear about what the Next Action is. For example, you might want to tidy your office. What’s stopping you doing that? Perhaps you’ve nowhere to put the rubbish. In that case the Next Action is “Get Bin Bags”

Perhaps you need to arrange a meeting. “Arrange a meeting” is not a suitable Next Action. To arrange a meeting you need to find out when people are free. A more suitable Next Action would be “Phone Steve”

Taking a moment to decide the Next Action removes one cause of stress. If you have a job that’s preying on your mind it’s usually because you haven’t decided what the Next Action is.

Related Links

2 Functions in Elisp

Here’s how to define a simple LISP function

1: (defun pi ()
2:   "A sample non-interactive function"
3:   3.1415
4: )

The above is a non-interactive function that simply returns 3.1415. Evaluate it (C-x C-e, remember?) and you will see the word pi appear in the echo area. Try M-x pi, though, and Emacs won’t find the function. If you want to be able to call a function using M-x, you have to make it interactive, as follows.

1: (defun print-pi()
2:     "Insert an approximation to pi"
3:     (interactive)
4:     (insert "3.1415")
5: )

So why would you want a non-interactive function? Perhaps because you want it to be called from another function, as follows:

1: (defun circumference-of-circle()
2:     (interactive)
3:     (message "The circumference of a circle diameter 3 is %f" (* pi 3))
4: )

Before evaluating the above function, make sure that you have evaluated the non-interactive function pi.

There are lots of different types of interactive functions. The next interactive function is more useful in that it prompts for the diameter to be input (the n at the start of “nInput diameter of circle:” is what tells Emacs to prompt for a number)

1: (defun circumference-of-circle(diameter)
2:     "Calculate the circumference of a circle given the diameter"
3:     (interactive "nInput diameter of circle:")
4:     (message "The circumference of a circle diameter %d is %f" diameter (* 3.1415 diameter))
5: )

Here’s the same function but this time set up to receive the parameter from the universal argument. That is to say, in the form C-u 4 M-x circumference-of-circle.

1: (defun circumference-of-circle(diameter)
2: (interactive "p")
3: (message "The circumference of a circle diameter %d is %f" diameter (* 3.1415 diameter))
4: )

Here’s an example of a function that reads strings and tests your knowledge of capital cities.

1: (defun capital-of-france(answer)
2:     "Simple quiz example."
3:     (interactive "sWhat's the Capital of France?")
4:     (if (string= answer "paris") (message "Correct!") (message "Wrong!"))
5: )

Argument codes for interactive functions can be found here http://www.gnu.org/software/emacs/manual/html_node/elisp/Interactive-Codes.html#Interactive-Codes

Next: Interactive Functions that work on Regions

1 Beginning Emacs Lisp

LISP is derived from the term LISt Processing.

A list in LISP looks like this:

(Knife Fork Spoon)

or like these two examples
(set-background-color "yellow")    <- C-x C-e
(set-background-color "white")    <- C-x C-e

If the first item in the list is a function you can evaluate the list by placing the cursor just after the bracket at the end of the list and pressing C-x C-e. Try it with the two lists above. Copy them into Emacs and then C-x C-e where indicated to turn the Emacs background yellow and then to set it white again.

If you try to evaluate the (Knife Fork Spoon) list you’ll get an error telling you that Knife is a void function.

Try evaluating the following lists in Emacs by typing C-x C-e after the closing bracket:
(linum-mode)
(message "This is the echo area")
(* 2 3)
(+ 4 5)

The last three will output their results in the echo area, the area at the bottom of Emacs.

You can also evaluate a function by typing M-x (function name). So M-x visual-line-mode will turn word wrap on and off.

Emacs supports TAB completion, so typing M-x visu and pressing TAB is enough to fill in the function name.

You set a variable as follows:

(set 'name 'John) C-x C-e to set the variable

name C-x C-e to see the contents of the variable “name”

If you press C-x C-e after (name)you’ll get an error. Remember, name is a variable, (name) is a function, and you haven’t defined a function called name.
It’s a nuisance typing in ‘ all the time, so the following is often used
(setq animal 'cat)

Evaluate the above and then evaluate animal …

C-u C-x C-e will insert any output directly in the text area, rather than in the echo area.

Here is a list of cheeses called cheese:
(setq cheese '(Stilton Wensleydale Cheddar Cheshire))

Evaluate the list.

The first item in a list is called the car, the remaining items are called the cdr (pronounced could-er) The Emacs Lisp tutorial will tell you why. Evaluate the following:

(car cheese)
(cdr cheese)

… and there you are

Next: Functions in Elisp

3 GTD: Collect

  • You can’t organize what’s incoming, you can only collect it and process it.
  • You don’t manage priorities, you have them

Collection is the key to the whole process of GTD.

Collection means writing down everything you have to do, and this means everything.

If you have a good memory, and I do, the temptation is not to bother, but this means that you’re not trusting the system. If the system doesn’t have everything you need to do in it, then you won’t trust it and you’ll go back to worrying that you’re not doing all your tasks.

You also won’t be able to plan properly.

I’m getting more and more in the habit of capturing things I need to do, even jobs I know I’ll do in a short time.

Here are some jobs I’ve captured

  • Email Harold about Films
  • Watch Epilepsy Video
  • Write UCAS reports
  • Buy birthday card
  • Organise VLE training for September
  • Investigate Trello software

I use Emacs org-mode capture to capture my tasks, but that’s just my preference. Evernote is good, but the system works perfectly adequately using pen and paper.

Related Links

2 GTD: Overview

There are five parts to GTD

  • Collect
  • Process
  • Organize
  • Reviewing
  • Do
You should only ever be doing one of these things at any one time: 95% of your time should be spent doing.

The basic principles of GTD are just common sense.

First, collect all the things you have to do and write them down.  If your tasks are all recorded you know that they won’t be forgotten. If you know you’re not going to forget things you’ve just removed one cause of stress.

Next, organize your work so that jobs get done at the right time.  This stops the feeling that you’re drowning in trivial jobs when should be doing something more important.

Having done that, do the work. If you have all your tasks organized properly you can look up a couple of five minute tasks when you have ten minutes spare, when you have a longer stretch of time you can get down to a more challenging task.

Review your system every so often.  Priorities will change, you’ll need to reorganize your work to take this into account.

GTD involves writing down all your jobs.  It doesn’t matter whether you do it on paper or use an IT solution such as Evernote or my preferred solution, Emacs.  Everything you have to do – making a phone call; sending a birthday card; starting a big project;  buying a book to read… write it down.

Related Links

Ubuntu Emacs Org-Mode Setup

Emacs works straight out of the box on Ubuntu however, at the time of writing, Ubuntu 12.04 still only comes with org-version 6.33.  It’s worth installing the latest version.  The installation instructions are on the org-mode site http://orgmode.org/manual/Installation.html, but they’re not quite complete.

 Install the latest version of Org-Mode

  1. Download the org-mode files and copy to a suitable location (I put them in the Ubuntu One folder so they’re easily shared between PCs)
  2. sudo apt-get install texinfo.  This is the missing step that ensures the next part works correctly
  3. Navigate to the org-8.x folder and sudo make autoloads and then sudo make install
  4. Finally, add (add-to-list ‘load-path “/usr/share/emacs/site-lisp/org”) to your .emacs file

Unity Keybindings

Some of the Unity keybindings overwrite those of standard org-mode.  I get particularly frustrated not being able to use S-M-<UP> to sort lines.  The following sorts this out:

  1. sudo apt-get install compizconfig-settings-manager
  2. Launch compiz-config-settings-manager
  3. Dash Home -> CompizConfig Settings Manager-> Scale(icon) under Windows Management Category -> Bindings(tab) -> Initiate Windows Picker -> change to <Shift><Super>Up or similar

Alt and Alt Gr

I don’t make use of the way Ubuntu distinguishes between these two keys, and I prefer to set the Alt Gr key to act just like the Alt.  For one thing, it makes it easier on the hands to type M-f and M-b when moving forward and backwards through words (something I do a lot when editing) .  Making this change on Ubuntu 12.04 is easy

  • Open Keyboard Layout from the dash.  Choose Options, Alt/Win Key behaviour and select Alt and Meta are on Alt Keys

Note you you can also swap the Ctrl and Caps lock this way if you prefer.
For older versions of Ubuntu, the Keyboard Layout preferences are found on a tab in Keyboard in System Settings

Related Posts