The editor functions described in this section can be combined and provided with arguments to create new commands.
Existing editor commands can also be used in the creation of new commands. Every editor command documented in this manual is named by a string command which can be used to invoke the command interactively, but there is also associated with this a standard Lisp function (the "command function") named by a symbol exported from the editor package. You can use this symbol to call the command programmatically. For example, the editor command Forward Character is referred to by
The first argument of any command function is the prefix argument p, and this must therefore be included in any programmatic call, even if the prefix argument is ignored. Some commands have additional optional arguments. For example to insert 42 #\! characters, you would call
(editor:self-insert-command 42 #\!)
Details of these optional arguments are provided in the command descriptions throughout this manual.
See editor:defcommand for the details of how to create new commands.
Note: code which modifies the contents of a
capi:editor-pane (for example a displayed editor buffer) must be run only in the interface process of that pane.
The following sections describe editor functions that are not interactive editor commands.
All editor commands and some other editor functions expect to be called within a dynamic context that includes settings for the current buffer and current window. This happens automatically when using the editor interactively.
editor:process-character char window
defcommand name lambda-list command-doc function-doc &body forms => command-function
Defines a new editor command. name is a usually string naming the new editor command which can invoked in the editor via Extended Command, and command-function is a symbol naming the new command function which can be called programmatically. The command-function symbol is interned in the current package.
The name of the command must be a string, while the name of the associated command function must be a symbol. There are two ways in which name can be supplied. Most simply, name is given as a string, and the string is taken to be the name of the editor command. The symbol naming the command function is computed from that string: spaces are replaced with hyphens and alphabetic characters are uppercased, but otherwise the symbol name contains the same characters as the string with
If a specific function name, different to the one
defcommand derives itself, is required, then this can be supplied explicitly. To do this, name should be a list: its first element is the string used as the name of the command, while its second and last element is the symbol used to name the Lisp command function.
If you anticipate frequent interactive use of
Uppercase Buffer you will want to bind it to a key. You can do this interactively for the current session using Bind Key. Also you can put something like this in your initialization file to establish the key binding for each new session:
(editor:bind-key "Uppercase Buffer" #("Control-x" "Meta-u"))
Each buffer that you manipulate interactively using editor commands is an object of type
editor:buffer that can be used directly when programming the editor. Buffers contain an arbitrary number of
editor:point objects, which are used when examining or modifying the text in a buffer (see Points).
Each buffer contains a lock that is used to prevent more than one thread from modifying the text, text properties or points within the buffer simultaneously. All of the exported editor functions (editor:insert-string, editor:move-point etc) claim this lock implicitly and are therefore atomic with respect to other such functions.
In situations where you want to make several changes as one atomic operation, use one of the macros editor:with-buffer-locked or editor:with-point-locked to lock the buffer for the duration of the operation. For example, if you want to delete the next character and replace it by a space:
In addition, you sometimes want to examine the text in a buffer without changing it, but ensure that no other thread can modify it in the meantime. This can be achieved by locking the buffer using editor:with-buffer-locked or editor:with-point-locked and passing the for-modification argument as
nil. For example, if you are computing the beginning and end of some portion of the text in a buffer and then performing some operation on that text, you may want to lock the buffer to ensure that no other threads can modify the text while your are processing it.
editor:with-buffer-locked (buffer &key for-modification check-file-modification block-interrupts ) &body body => values
If for-modification is non-nil (the default), the contents of buffer can be modified by body. If for-modification is
nil, the contents of buffer cannot be modified until body returns and trying to do so from within body will signal an error. If the buffer is read-only and for-modification is non-nil, then an
editor:editor-error is signalled. The status of the lock can be changed to for-modification (see editor:change-buffer-lock-for-modification). If the buffer is read-only, an editor:editor-error occurs if for-modification is
editor:with-buffer-locked can be used recursively, but if the outermost use passed
nil as the value of for-modification, then inner uses cannot pass non-nil as the value of for-modification, unless editor:change-buffer-lock-for-modification is used to change the lock status.
If check-file-modification is non-nil (the default) and the buffer is associated with a file and has not already been modified, then the modification time of the file is compared to the time that the file was last read. If the file is newer than the buffer, then the user is asked if they want to re-read the file into the buffer, and if they do then the file is re-read and the operations aborts. Otherwise, there is no check for the file being newer than the buffer.
If block-interrupts is non-nil, the body is evaluated with interrupts blocked. This is useful if the buffer may be modified by an interrupt function, or some interrupt function may end up waiting for another thread that may wait for the buffer lock, which would cause a deadlock. The default is not to block interrupts.
Note that using a non-nil value for block-interrupts is not the same as using the
without-preemption macros. It just stops the current thread from calling interrupt functions, so other threads might run while the body is being evaluated.
editor:with-point-locked (point &key for-modification check-file-modification block-interrupts errorp ) &body body => values
Evaluates body while holding the lock in the buffer that is associated with point. In addition, the macro checks that point is valid and this check is atomic with respect to calls to the function editor:delete-point. The values of for-modification, check-file-modification and block-interrupts have the same meanings as for editor:with-buffer-locked.
The value of errorp determines the behavior when point is not valid. If errorp is non-nil, an error is signaled, otherwise
nil is returned without evaluating body. The point may be invalid because it does not reference any buffer (that is, it has been deleted), or because its buffer was changed by another thread while the current thread was attempting to lock the buffer.
editor:change-buffer-lock-for-modification buffer &key check-file-modification force-modification => result
Changes the status of the lock in the buffer buffer to allow modification of the text. buffer must already be locked for non-modification by the current thread (that is, it must be dynamically within a editor:with-buffer-locked or editor:with-point-locked form with for-modification
An editor buffer.
If check-file-modification is non-nil, the same test as described for editor:with-buffer-locked is performed, and if the file has been modified then
:buffer-out-of-date is returned without changing anything (it does not prompt the user to re-read the file).
force-modification controls what happens if the buffer is read-only. If force-modification is
nil, the function returns
:buffer-not-writable and does nothing. If it is non-nil, the status is changed. The buffer remains read-only.
nil if the status of the locking was changed to for-modification, or if the status of the buffer lock was already for-modification. Otherwise, result is a keyword indicating why the status could not be changed. When result is non-nil, the status of the locking remains unchanged.
editor:use-buffer buffer &body forms
make-buffer name &key modes contents temporary base-name name-pattern
modes should be a list of strings naming modes. The first mode must be a major mode, and the rest minor modes. The default value of modes is the value of default-modes.
When name is non-nil, it is the name of the buffer. If there is already a buffer with this name which is not temporary and the temporary argument is
make-buffer returns that buffer. Before doing so, it sets its contents to contents unless contents is
t. When contents is
nil, the buffer is made empty.
If name is
nil or temporary is non-nil or a buffer with the name cannot be found, then a new buffer is made and returned. The buffer's contents is set to contents if contents is a string, and otherwise the buffer is made empty. The name of the buffer is set to name if name is non-nil.
If temporary is
nil, the buffer is added to the internal tables of the editor. If name is non-nil, it is used. Otherwise
make-buffer tries to use base-name. If there is already a buffer with this name, it constructs another name by
(format nil name-pattern base-name n)
If temporary is non-nil, the buffer is not added to the internal tables. It is also marked as temporary, which mainly means that it does not have auto-save and backup files, and avoids calling general hooks when it is modified.
:temporary t gives you a buffer that is 'yours', that is the editor does not do anything with it except in response to explicit calls from your code. Except when actually editing files, this is the most useful way of using buffers in most cases.
(make-buffer ... :temporary t)
editor:goto-buffer buffer in-same-window
Makes buffer the current buffer. If buffer is currently being shown in a window then the cursor is moved there. If buffer is not currently in a window and in-same-window is non-nil then it is shown in the current window, otherwise a new window is created for it.
Locations within a buffer are recorded as
editor:point objects. Each point remembers a character position within the buffer and all of the editor functions that manipulate the text of a buffer locate the text using one or more point objects (sometimes the current point).
:temporary points are for cases where you need read-only access to the buffer. They are like GNU Emacs "points". They have a lower overhead than the other kinds of point and do not need to be explicitly deleted, but do not use them in cases where you make a point, insert or delete text and then use the point again, since they do not move when the text is changed. Also, do not use them in cases where more than one thread can modify their buffer without locking the buffer first (see Buffer locking)
:after-insert points are for cases where you need to make a point, insert or delete text and still use the point afterwards. They are like GNU Emacs "markers". The difference between these two kinds is what happens when text is inserted. For a point at position n from the start of the buffer, inserting len characters will leave the point at either position n or n+len according to the following table.
When text is deleted,
:after-insert points are treated the same: points <= the start of the deletion remain unchanged, points >= the end of the deletion are moved with the text and points within the deleted region are automatically deleted and cannot be used again.
All points with kind other than
:temporary are stored within the data structures of the editor buffer so they can be updated when the text changes. A point can be removed from the buffer by editor:delete-point, and point objects are also destroyed if their buffer is killed.
Returns the current point. See also editor:buffer-point.
editor:current-mark &optional pop-p no-error-p
Returns the current mark. If pop-p is
t, the mark ring is rotated so that the previous mark becomes the current mark. If no mark is set and no-error-p is
nil is returned; otherwise an error is signalled. The default for both of these optional arguments is
editor:point< point1 point2
editor:point<= point1 point2
editor:point> point1 point2
editor:point>= point1 point2
editor:copy-point point &optional kind new-point
editor:move-point point new-position
editor:same-line-p point1 point2
editor:save-excursion &rest body
editor:with-point point-bindings &rest body
point-bindings is a list of bindings, each of the form
]). Each variable var is bound to a new point which is a copy of the point point though possibly with a different kind, if kind is supplied. If kind is not supplied, then the new point has kind
The forms of body are evaluated within the scope of the point bindings, and then the points in each variable var are deleted, as if by editor:delete-point. Each point var is deleted even if there was an error when evaluating body.
regular-expression-search point pattern &key forwardp prompt limit to-end brackets-limits => match-len, brackets-limits-vector
point must be an
editor:point object or
nil, meaning the result of calling editor:current-point.
regular-expression-search performs a search starting from point for the pattern, in the direction specified by forwardp, up to to limit if specified, or the buffer's end (when forwardp is non-nil) or the buffer's start (when forwardp is
nil). If it succeeds, it then moves the point, either to the end of that match when both forwardp and to-end are non-nil (the default), or to the beginning of the match.
When pattern is non-nil it must be either a string or a precompiled pattern created with
lw:precompile-regexp. If pattern is a string,
regular-expression-search "precompiles" it before searching, so using a precompiled pattern is more efficient when using the same pattern repeatedly.
Return values: If
regular-expression-search is successful, it returns the length of the string that it matched, and if brackets-limits is non-nil, a second value which is a vector of the limits of the matches of each
\) pair in the pattern. The meaning of the vector is described in the manual entry for
lw:find-regexp-in-string in the
LispWorks User Guide and Reference Manual
lw:precompile-regexp in the
LispWorks User Guide and Reference Manual
Regular expression syntax
editor:message string &rest args
A message is printed in the Echo Area. The argument string must be a string, which may contain formatting characters to be interpreted by
format. The argument args consists of arguments to be printed within the string.
editor:clear-echo-area &optional string force
Clears the Echo Area. The argument string is then printed in the Echo Area. If force is non-nil, the Echo Area is cleared immediately, with no delay. Otherwise, there may be a delay for the user to read any existing message.
In many cases, the user will not want the operation to abort completely if one of the editor commands it uses is not successful. For example, the operation may involve a search, but some aspects of the operation should continue even if the search is not successful. To achieve this, the user can catch the
editor:editor-error using a macro such as
For example, one part of an application might involve moving forward 5 forms. If the current point cannot be moved forward five forms, generally the Editor would signal an error. However, this error can be caught. The following trivial example shows how a new message could be printed in this situation, replacing the system message.
"Tries to move the current point forward five forms, printing out an appropriate message on failure."
editor:editor-error string &rest args
By default this prints a message in the Echo Area, sounds a beep, and exits to the top level of LispWorks, aborting the current operation. The argument string must be a string, which is interpreted as a control string by
format. As with editor:message, args can consist of arguments to be processed within the control string.
The behavior is affected by break-on-editor-error.
editor:find-file-buffer pathname &optional check-function
Returns a buffer associated with the file pathname, reading the file into a new buffer if necessary. The second value returned is
T if a new buffer is created, and
nil otherwise. If the file already exists in a buffer, its consistency is first checked by means of check-function. If no value is supplied for check-function, editor:check-disk-version-consistent is used.
editor:fast-save-all-buffers &optional ask
Saves all modified buffers which are associated with a file. If ask is non-nil then confirmation is asked for before saving each buffer. If ask is not set, all buffers are saved without further prompting.
Unlike the editor command Save All Files this function can be run without any window interaction. It is thus suitable for use in code which does not intend to allow the user to leave any buffers unsaved, and from the console if it is necessary to save buffers without re-entering the full window system.
editor:check-disk-version-consistent pathname buffer
Checks that the date of the file pathname is not more recent than the last time buffer was saved. If pathname is more recent, the user is prompted on how to proceed. Returns
t if there is no need to read the file from disk and
nil if it should be read from disk.
(setf (editor:buffer-external-format buffer) ef-spec)
See Unicode and other file encodings for a full description of the editor's file encodings interface.
editor:insert-string point string &optional start end
Inserts string at point in the current buffer. The arguments start and end specify the indices within string of the substring to be inserted. The default values for start and end are 0 and
editor:kill-ring-string &optional index
editor:points-to-string start end
A true value for editor:*indent-with-tabs* causes the indentation commands to insert
#\Tab characters according to the value of spaces-for-tab and then pad with
#\Space characters as needed.
The first element controls the positioning of the definition: when
t, show it at the top of the editor window; when a non-negative fixnum, position it that many lines from the top; and when
nil, position it at the center of the window.
editor:character-offset point n
editor:word-offset point n
editor:line-offset point n &optional to-offset
Moves point n lines forward, to a location to-offset characters into the line. If n is negative, point moves back n lines. If to-offset is
nil (its default value), an attempt is made to retain the current offset. An error is signalled if there are not n further lines in the buffer.
editor:form-offset point n &optional form depth
Moves point forward n Lisp forms. If n is negative, point moves back n forms. If form is
t (its default value) then atoms are counted as forms, otherwise they are ignored. Before point is moved forward n forms, it first jumps out depth levels. The default value for depth is 0.
Specifies whether the value that is input by the user must be an existing value or not. If
:must-exist is non-nil, the user is prompted again if a non-existent value is input.
Defines the default value that is selected if an empty string is input.
Specifies the string that may be edited by the user (with Insert Parse Default).
Defines the prompt that is written in the Echo Area. Most prompting functions have a default prompt that is used if no value is supplied for
Provides a help message that is printed if the user types "
editor:prompt-for-file &key direction must-exist create-directories default default-string prompt help
You can specify direction :input (when expecting to read the file) or direction :output (when expecting to write the file). This controls the default value of must-exist, which is false for direction :output and true otherwise.
editor:prompt-for-buffer &key prompt must-exist default default-string help
editor:prompt-for-integer &key prompt must-exist default help
editor:prompt-for-string &key prompt default default-string clear-echo-area help
Prompts for a string. No checking is done on the input. The keyword clear-echo-area controls whether or not the echo area is cleared (that is, whether the text being replaced is visible or not). The default for this keyword is
t. See above for an explanation of the remaining keywords.
editor:prompt-for-variable &key must-exist prompt default default-string help
editor:complete-in-place complete-func &key extract-func skip-func insert-func
complete-func string &optional user-arg => result
string should be a string to complete. user-arg is the second return value of extract-func, if this is not
nil. result should be a list of items to be displayed in the list panel of the non-focus window.
extract-func point => string, user-arg
point should be a Point object
extract-func needs to move point to the beginning of the text that will be replaced if the user confirms. It should return two values: string is the string to complete, and user-arg can be any Lisp object. string is passed to the function complete-func, and if user-arg is non-nil it is also passed.
The default value of extract-func is a function which searches backwards until it finds a non-alphanumeric character, or the beginning of the buffer. It then moves its point argument forward to the next character. The function returns its first value string the string between this and the original location of the point, and it returns
nil as the second value user-arg.
point should be a Point object
point will be used as the end of the region to replace by the completion. At the call to skip-func, the point is located at the same place as the point that was passed to extract-func (after it moved). skip-func needs to move point forward to the end of the text that should be replaced when the user wants to do the completion. If skip-func is not supplied, the end point is set to the current point.
insert-func result string user-arg => string-to-use
result is the item selected by the user, string is the original string that was returned by extract-func, and user-arg is the second value returned by extract-func (regardless of whether this value is
nil). It must return a string, string-to-use, which is inserted as the the completion.
editor:complete-in-place is called, it makes a copy of the current point and passes it to extract-func. It then copies this point and positions it either using skip-func or the current point. These two points define the text to be replaced.
editor:complete-in-place then calls complete-func, and use the result to raise a non-focus window next to the current point. The interaction of this window is as described in
CAPI User Guide and Reference Manual
editor:define-editor-variable name value &optional documentation
Symbol naming the variable.
The value to assign to the variable.
A string naming a mode.
A documentation string.
editor:define-editor-variable gives a readable value of defining a variable, and is recognized by the LispWorks source code location system. However variables can also be defined dynamically by calling
(setf editor:variable-value). Variable values may be accessed by editor:variable-value.
A variable has only one string of documentation associated with it. editor:variable-value overwrites the existing documentation string, if there is any. You can see the documentation by the command Describe Editor Variable. It can can be accessed programmatically by editor:editor-variable-documentation.
Note: for backwards compatibility name can also be a string, which is converted to a symbol by uppercasing, replacing
#\-, and interning in the EDITOR package. This may lead to clashes and so you should use a symbol for name, not a string.
editor:define-editor-mode-variable name mode value &optional documentation
A string naming a mode.
As for editor:define-editor-variable.
As for editor:define-editor-variable, except that
editor:define-editor-mode-variable installs the documentation only if the editor variable does not already have any documentation.
editor:define-editor-mode-variable gives a readable value of defining a variable in a mode, and is recognized by the LispWorks source code location system. However mode variables can also be defined dynamically by calling
(setf editor:variable-value). Mode variable values may be accessed by editor:variable-value.
Note: For backwards compatibility a string editor-variable-name is also accepted, as described for editor:define-editor-variable.
editor:variable-value name &optional kind where
Returns the value of the editor variable name, where name is a symbol. An error is signalled if the variable is undefined. The argument kind can take the value
:mode. The default value of kind is
When kind is
:current the argument where should be
nil (the default, meaning the current buffer) or an editor buffer object or the name of a buffer. The variable value for the specified buffer is returned or (if there is no current buffer) then the global variable value is returned.
editor:variable-value-if-bound name &optional kind where
Returns the value of the variable name. If the variable is not bound,
nil is returned. The arguments are as for editor:variable-value.
editor:buffer-value buffer name &optional errorp
editor:redisplay will update a modified editor buffer only when that buffer is the editor:current-buffer. Take care to call
editor:redisplay in an appropriate context.
LispWorks Editor User Guide (Windows version) - 9 Dec 2014