(how-many 1)
"one"
(how-many 0)
"no"
(how-many 3)
"many"
Combining these two helper functions into a mechanism to report the change count for our fancy command is easy.
(defun report-change-count (count)
(message "Made %s %s." (how-many count) (pluralize "change" count)))
We get results like these:
(report-change-count 0)
"Made no changes."
(report-change-count 1)
"Made one change."
(report-change-count 1329)
"Made many changes."
11.3 Useful Built-in Emacs Functions
Many of the Emacs functions that exist and that you may write involve searching and manipulating the text in a buffer. Such functions are particularly useful in specialized modes, like the programming language modes described in Chapter 9. Many built-in Emacs functions relate to text in strings and buffers; the most interesting ones take advantage of Emacs's regular expression facility, which we introduced in Chapter 3 Chapter 3. Search and Replace The commands we discussed in the first two chapters are enough to get you started, but they're certainly not enough to do any serious editing. If you're using Emacs for anything longer than a few paragraphs, you'll want the support this chapter describes. In this chapter, we cover the various ways that Emacs lets you search for and replace text. Emacs provides the traditional search and replace facilities you would expect in any editor; it also provides several important variants, including incremental searches, regular expression searches, and query-replace. We also cover spell-checking here, because it is a type of replacement (errors are sought and replaced with corrections). Finally, we cover word abbreviation mode; this feature is a type of automatic replacement that can be a real timesaver.
.
We first describe the basic functions relating to buffers and strings that don't use regular expressions. Afterwards, we discuss regular expressions in more depth than was the case in Chapter 3 Chapter 3. Search and Replace The commands we discussed in the first two chapters are enough to get you started, but they're certainly not enough to do any serious editing. If you're using Emacs for anything longer than a few paragraphs, you'll want the support this chapter describes. In this chapter, we cover the various ways that Emacs lets you search for and replace text. Emacs provides the traditional search and replace facilities you would expect in any editor; it also provides several important variants, including incremental searches, regular expression searches, and query-replace. We also cover spell-checking here, because it is a type of replacement (errors are sought and replaced with corrections). Finally, we cover word abbreviation mode; this feature is a type of automatic replacement that can be a real timesaver.
, concentrating on the features that are most useful to Lisp programmers, and we describe the functions that Emacs makes available for dealing with regular expressions.
11.3.1 Buffers, Text, and Regions
Table 11-4shows some basic Emacs functions relating to buffers, text, and strings that are only useful to Lisp programmers and thus aren't bound to keystrokes. We already saw a couple of them in the count-words-bufferexample. Notice that some of these are predicates, and their names reflect this.
Table 11-4. Buffer and text functions
Function |
Value or action |
point |
Character position of point. |
mark |
Character position of mark. |
point-min |
Minimum character position (usually 1). |
point-max |
Maximum character position (usually size of buffer). |
bolp |
Whether point is at the beginning of the line ( t or nil ). |
eolp |
Whether point is at the end of the line. |
bobp |
Whether point is at the beginning of the buffer. |
eobp |
Whether point is at the end of the buffer. |
insert |
Insert any number of arguments (strings or characters) into the buffer after point. |
number-to-string |
Convert a numerical argument to a string. |
string-to-number |
Convert a string argument to a number (integer or floating point). |
char-to-string |
Convert a character argument to a string. |
substring |
Given a string and two integer indices start and end , return the substring starting after start and ending before end . Indices start at 0. For example, (substring "appropriate" 2 5) returns " pro ". |
aref |
Array indexing function that can be used to return individual characters from strings; takes an integer argument and returns the character as an integer, using the ASCII code (on most machines). For example, (aref "appropriate" 3) returns 114, the ASCII code for r . |
Many functions not included in the previous table deal with buffers and text, including some that you should be familiar with as user commands. Several commonly used Emacs functions use regions , which are areas of text within a buffer. When you are using Emacs, you delineate regions by setting the mark and moving the cursor. However, region-oriented functions (such as kill-region, indent-region, and shell-command-on-region—really, any function with region in its name) are actually more flexible when used within Emacs Lisp code. They typically take two integer arguments that are used as the character positions of the boundaries for the region on which they operate. These arguments default to the values of point and mark when the functions are called interactively.
Obviously, allowing point and mark as interactive defaults is a more general (and thus more desirable) approach than one in which only point and mark can be used to delineate regions. The roption to the interactivefunction makes it possible. For example, if we wanted to write the function translate-region-into-German, here is how we would start:
(defun translate-region-into-German (start end)
(interactive "r")
...
The roption to interactivefills in the two arguments startand endwhen the function is called interactively, but if it is called from other Lisp code, both arguments must be supplied. The usual way to do this is like this:
(translate-region-into-German (point) (mark))
But you need not call it in this way. If you wanted to use this function to write another function called translate-buffer-into-German, you would only need to write the following as a "wrapper":
(defun translate-buffer-into-German ( )
(translate-region-into-German (point-min) (point-max)))
In fact, it is best to avoid using point and mark within Lisp code unless doing so is really necessary; use local variables instead. Try not to write Lisp functions as lists of commands a user would invoke; that sort of behavior is better suited to macros (see Chapter 6).
Читать дальше