unofficial mirror of help-gnu-emacs@gnu.org
 help / color / mirror / Atom feed
* Critique my Code, learning elisp
@ 2006-10-16  8:39 Sam Peterson
  2006-10-16 13:06 ` Passer By
  0 siblings, 1 reply; 2+ messages in thread
From: Sam Peterson @ 2006-10-16  8:39 UTC (permalink / raw)


I'm a long time user of GNU Emacs, but I've only recently dabbled in
Emacs Lisp.  I'm setting some useful functions for some friends of
mine in a C language class I'm taking to make composing C code
easier.  The trouble with learning Emacs Lisp for someone like me is
that I'm a perfectionist and it seems like there's multiple ways to do
just about everything in Emacs Lisp :).  Not only that, but it seems
like when I get an idea for a good elisp function, it turns out such a
thing already exists in Emacs, or somebody else has written a better
version of what I set out to do :(.  Or, something could have been
done much more easily with a Macro.

Take the following code:

(defun sams-c-wrap-if (beg end if-cond)
  "Function that wraps the region in a C language if statement"
  (interactive "r\nsCondition: ")
  (save-excursion
    (save-restriction
      (narrow-to-region beg end)
      (goto-char (point-min))
      (insert (format "if (%s)\n{" if-cond))
      (c-indent-command)
      (newline)
      (c-indent-command)
      (goto-char (point-max))
      (insert (format "} // end if(%s)\n" if-cond))
      (c-indent-command)
      (setq end (point-max)))
    (c-indent-region beg end)))

This works splendidly.  However, I feel like an apprentice without a
mentor and I can't help but feel if what I've done here is sloppy or
poorly realized.  I also began to read up on skeletons.  I started to
realize I could accomplish the same thing via a skeleton like such:

(define-skeleton sams-c-wrap-if
 "Simple skeleton for wrapping c if statements"
 "Condition: " "if (" str ")" > "\n{" > "\n" > _ "}" >)

This works splendidly too.  So, "which is better"?  I realize this is
probably a subjective question, but I'm sure there's at least
contextual concerns to each.  For instance, I've written an "unif"
function to undo an if statement around the region:

(defun sams-c-unif (beg end)
  (interactive "r")
  (save-excursion
    (save-restriction
      (narrow-to-region beg end)
      (goto-char (point-min))
      (if (not (looking-at " *if *(.*?) *$"))
          (error "Region doesn't contain a complete if statement")
        ;; else
        (kill-line 2)
        (setq beg (point))
        (goto-char (point-max))
        (previous-line 1)
        (beginning-of-line)
        (kill-line 1)
        (setq end (point))))
    (c-indent-region beg end)))

How does this compare?  It of course makes many assumptions about the
formatting of the if statement, but I haven't felt this is necessarily
evil as Emacs itself seems to do this about a lot of things, such as
its function movement commands.

The reason I've chosen this code is that it deals with wrapping a
region and there's so many ways to go about this.  In keyboard macros
you can go about it several ways:

* One way is to kill the region as the first command of the macro,
  then type what goes before the region, yank, and type what goes
  after the region.  This makes it so that it doesn't matter if point
  or mark is the furthest part of the region, but it does it at the
  expense of cluttering up the kill ring.

* A work around for this is to insert the region into a register,
  delete-region, type what goes before the region, insert register,
  then type what comes after the region.  This avoids cluttering the
  kill-ring at the expense of being a little more work to define.

* Yet one more way to go about is to simply type what comes after the
  region, exchange point and mark, type what comes before the region
  and exchange point and mark one last time.  This avoids having to
  store and delete text at the expense of requiring point be after
  mark in the region (otherwise the wrong thing ends up before and
  after the region).

There's probably even more ways to go about it but I'll stop there.

Not only can you do these things in elisp, but you can better it by
the fact that being passed the region interactively means that you
always know the beginning and end of the region at the start of your
function.  There's a small problem with just using buffer positions
however.  The insert function changes the buffer, so if you insert
what goes in the beginning of the region first, the end variable no
longer points to the end of the region.  I got around this in my code
above by narrowing to the region and using point-min and point-max.
This solves that problem, but is that overkill?  Is it normally better
to just insert what goes at the end of the region first, goto-char
beg, and insert the beginning of what goes in the region?  Heck, what
about goto-char end, push-mark, goto-char beg, insert, exchange point
and mark, insert end?  Are there performance trade-offs?  What is
"the" way to do this.  Am I stressing out waaaay too much about this?
Should I just do something that works and be secure in the knowledge
that performance concerns are probably not a big deal for something
like this?  Is something like this already built into cc-mode or Emacs
and am I wasting my time trying?  Was I abused as a child with Basic?
Will I ever get my degree?  What is the meaing of life?

-- 
Sam Peterson
skpeterson At no spam ucdavis.edu
The curious little elisp learner.

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: Critique my Code, learning elisp
  2006-10-16  8:39 Critique my Code, learning elisp Sam Peterson
@ 2006-10-16 13:06 ` Passer By
  0 siblings, 0 replies; 2+ messages in thread
From: Passer By @ 2006-10-16 13:06 UTC (permalink / raw)


Sam Peterson <skpeterson@nospam.please.ucdavis.edu> writes:


> Not only that, but it seems like when I get an idea for a good elisp
> function, it turns out such a thing already exists in Emacs, or
> somebody else has written a better version of what I set out to do
> :(.  Or, something could have been done much more easily with a
> Macro.
> 

Ya i hear what you mean, if all the emacs users were as lazy as me
about creating new code, i wouldn't be so lazy.

I will wait for some experts for your code.

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2006-10-16 13:06 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-10-16  8:39 Critique my Code, learning elisp Sam Peterson
2006-10-16 13:06 ` Passer By

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).