help-gnu-emacs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Inserting output from a program into a buffer


From: Pascal J. Bourguignon
Subject: Re: Inserting output from a program into a buffer
Date: Tue, 23 Feb 2010 00:23:58 +0100
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/23.1 (darwin)

Tim Johnson <tim@johnsons-web.com> writes:

> On 2010-02-22, Pascal J. Bourguignon <pjb@informatimago.com> wrote:
> <...>
>> In general, functions don't modify variables.  This would be a bad case
>> of side effect.  In emacs lisp it would be somewhat possible, since all
>>                    var))))
>>
>> (Notice that this effect is a design bug in LISP that was detected in
>> 1960 and corrected in the following years by the introduction of lexical
>> variables.  emacs lisp is somewhat retrograde (or at least conservator)
>> on this point).
>>
>>
>> Anyways, it is a bad idea to try to modify variables from called
>> functions.
>>
>>
>> What you really need is to BIND the RESULT of buffer-string and other
>> functions TO a variable.  This is done with LET:
>>
>> (let ((string (buffer-substring (point-min) (+ 10 (point-min)))))
>>   (string= "Newsgroups" string))
>>
>> --> t
>  Pascal, the total of what you have written is valuable to me in
>  understand programming elisp. I don't fully follow all of what you say,
>  but I hope that it will soak in.
>  I've now written a function that copies a delimited 'form' (sexp or
>  other data structure)
>  I submit it here for your comments. Your comments will no doubt further
>  enlighten me on your insights.
>  ;; code follows
> (defun tj-copy-previous-region()
>   "Grab a symmetrically delimited data structure beginning on the same line
>   as the cursor"
>   (interactive)
>   (let ((boundary(point))found end success (origin (point)))
>   (beginning-of-line-text)
>   (if (member (char-after) '(40 91 123))
>     (progn 
>     (setq found (point)))
>     (progn
>     (setq found(re-search-forward "(\\|\\[\\|{" boundary t))
>     (if found
>       (progn
>       (backward-char 1)
>       (setq found (point)))
>       (message "*** No Opening delimiter found on this line ***"))))
>   (when found
>     (forward-sexp)
>     (setq end (point))
>     (setq success (buffer-substring found end))
>     (message "** RESULT: %s ***" success)
>     (goto-char origin)) 
>   success))
>   ;; needs a little more factoring and I note some redundant bindings...
>> But who I am to say such things, I'm not RMS...
>   :) We all owe RMS a great debt for his contributions and his
>   passionate opinions are well known....
> thanks


You could write it like this:

(defun tj-copy-previous-region ()
  "Save a list surrounding or before the cursor into the kill-ring."
  (interactive)
  (save-excursion
    (let ((boundary (point)))
      (beginning-of-line-text)
      (if (re-search-forward "[([{]" boundary t)
          (let ((start (match-beginning 0)))
            (goto-char (1- start))
            (forward-sexp)
            (kill-ring-save start (point)))
          (error "No Opening delimiter found on this line")))))

aaaa (1 2 3 4 5 6 7 8 9) zzzz
             ^ M-x tj-copy-previous-region RET C-n C-n C-y inserts: 
(1 2 3 4 5 6 7 8 9)

Notice: 

- spaces before opening parentheses not preceded by an opening
  parenthesis.

- indentation done automatically by emacs.

- avoidance of setf or setq.

- do actually what was documented (by the function name), ie. use
  kill-ring-save instead of buffer-substring.

- use of save-excursion to save the excursion

- use of error to deal with exceptional cases instead of just message.
  error will do the right thing depending on the local circumstances
  (ie. it will message the error in interactive use, but enter the
  debugger or have the error otherwise handled if the programmer asks it
  to).


-- 
__Pascal Bourguignon__


reply via email to

[Prev in Thread] Current Thread [Next in Thread]