unofficial mirror of help-gnu-emacs@gnu.org
 help / color / mirror / Atom feed
* regexp / replacement for variable
@ 2004-02-21 23:08 Jan Misol
  2004-02-24 13:31 ` Kevin Dziulko
  0 siblings, 1 reply; 8+ messages in thread
From: Jan Misol @ 2004-02-21 23:08 UTC (permalink / raw)


I'm new to elisp but I want my beloved editor
to generate the standard c-header stuff when creating
a new .h/.hpp header.

> c-x c-f test.h

should automatically insert:

   #ifndef _TEST_H_
   #ifndef _TEST_H_


   #endif

depending on the given filename.

I put the following to my .emacs file:

   (defun new-c-header ()
     "Insert c-header skeleton."
     (interactive "")
     (progn
       (setq bname (upcase(buffer-name)))
       (insert
        (message "#ifndef %s\n\#define %s\n\n#endif"
           bname bname))))

Apart from knowing that "message" might not be the right
choice here, I don't know how to modify the value of bname!?
"replace-regexp" doesn't seem to be the what I'm looking for.

(and how could the new-c-header() be invoked by creating a
new .h/.cpp file?)

jan

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

* Re: regexp / replacement for variable
       [not found] <mailman.262.1077404990.340.help-gnu-emacs@gnu.org>
@ 2004-02-22  0:41 ` Kin Cho
  2004-02-22  0:51 ` lawrence mitchell
  2004-02-22 12:14 ` Floyd Davidson
  2 siblings, 0 replies; 8+ messages in thread
From: Kin Cho @ 2004-02-22  0:41 UTC (permalink / raw)


Instead of string matching, it is easier in this case to use
file-name-extension and file-name-sans-extension.

-kin

Jan Misol <misol@liblss.org> writes:

> I'm new to elisp but I want my beloved editor
> to generate the standard c-header stuff when creating
> a new .h/.hpp header.
> 
> > c-x c-f test.h
> 
> should automatically insert:
> 
>    #ifndef _TEST_H_
>    #ifndef _TEST_H_
> 
> 
>    #endif
> 
> depending on the given filename.
> 
> I put the following to my .emacs file:
> 
>    (defun new-c-header ()
>      "Insert c-header skeleton."
>      (interactive "")
>      (progn
>        (setq bname (upcase(buffer-name)))
>        (insert
>         (message "#ifndef %s\n\#define %s\n\n#endif"
>            bname bname))))
> 
> Apart from knowing that "message" might not be the right
> choice here, I don't know how to modify the value of bname!?
> "replace-regexp" doesn't seem to be the what I'm looking for.
> 
> (and how could the new-c-header() be invoked by creating a
> new .h/.cpp file?)
> 
> jan

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

* Re: regexp / replacement for variable
       [not found] <mailman.262.1077404990.340.help-gnu-emacs@gnu.org>
  2004-02-22  0:41 ` Kin Cho
@ 2004-02-22  0:51 ` lawrence mitchell
  2004-02-22 12:18   ` Jan Misol
  2004-02-22 12:14 ` Floyd Davidson
  2 siblings, 1 reply; 8+ messages in thread
From: lawrence mitchell @ 2004-02-22  0:51 UTC (permalink / raw)


Jan Misol wrote:


[...]

>> c-x c-f test.h

> should automatically insert:

>    #ifndef _TEST_H_
>    #ifndef _TEST_H_

>    #endif

[...]

>    (defun new-c-header ()
>      "Insert c-header skeleton."
>      (interactive "")
>      (progn
>        (setq bname (upcase(buffer-name)))
>        (insert
>         (message "#ifndef %s\n\#define %s\n\n#endif"
>            bname bname))))

> Apart from knowing that "message" might not be the right
> choice here, I don't know how to modify the value of bname!?
> "replace-regexp" doesn't seem to be the what I'm looking for.

Well, how about using `file-name-sans-extension' to strip the
trailing .h, and then insert using `format'.

(defun my-new-c-header ()
  (interactive)
  (let ((name (upcase (file-name-sans-extension (buffer-file-name)))))
    ;; Only insert if _name_H isn't already defined.
    (unless (save-excursion
              (goto-char (point-min))
              (search-forward (format "#ifndef _%s_H" name))
      (insert (format "#ifndef _%s_H\n#define _%s_H\n\n#endif"))))))

> (and how could the new-c-header() be invoked by creating a
> new .h/.cpp file?)

You could then either add this as a hook to `c-mode-hook' or
`find-file-hooks'.  In the case of the latter, you'd want to
predicate it on being a header file.  In fact, you'd want to do
the same for the former too.

You could do this by adding an extra test to the `unless' form
in the above function.

say:

(unless (and (string-match "\\.h") (buffer-file-name)
             ...)
  ...)

Slightly orthogonal to all this, you may find reading the Emacs
Lisp Introduction enlightening.

Alternately, instead of trying to roll your own function, it may
well be that Emacs already has the functionality you need
built-in.  See the info node "autotype", in Emacs, you can get
there via C-h i d m Autotype RET.

Hope some of this helps.
-- 
lawrence mitchell <wence@gmx.li>

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

* Re: regexp / replacement for variable
       [not found] <mailman.262.1077404990.340.help-gnu-emacs@gnu.org>
  2004-02-22  0:41 ` Kin Cho
  2004-02-22  0:51 ` lawrence mitchell
@ 2004-02-22 12:14 ` Floyd Davidson
  2 siblings, 0 replies; 8+ messages in thread
From: Floyd Davidson @ 2004-02-22 12:14 UTC (permalink / raw)


Jan Misol <misol@liblss.org> wrote:
>I'm new to elisp but I want my beloved editor
>to generate the standard c-header stuff when creating
>a new .h/.hpp header.
>
>> c-x c-f test.h
>
>should automatically insert:
>
>   #ifndef _TEST_H_
>   #ifndef _TEST_H_
>
>   #endif
>
>depending on the given filename.

We probably want to use more of the filename than just the
base, to allow similar header files in different directories
without name space collisions.

>I put the following to my .emacs file:
>
>   (defun new-c-header ()
>     "Insert c-header skeleton."
>     (interactive "")
>     (progn
>       (setq bname (upcase(buffer-name)))
>       (insert
>        (message "#ifndef %s\n\#define %s\n\n#endif"
>           bname bname))))
>
>Apart from knowing that "message" might not be the right
>choice here, I don't know how to modify the value of bname!?
>"replace-regexp" doesn't seem to be the what I'm looking for.
>
>(and how could the new-c-header() be invoked by creating a
>new .h/.cpp file?)
>
>jan

There are some other considerations too.  It is nice if this is
automatic, but it also must avoid trying to add the #define to
system headers and/or headers from other packages that are just
being looked at.

Below is one way to do that.  It decides that a file is "empty"
if it has fewer than 34 bytes in it, and otherwise will not make
an insertion.  When it does, it will include directories from
the pathname up to a maximum of to 32 characters total (by
default, which can be re-configured on the fly) into the symbol
name used for the #define.

Incidentally, it might be useful to expand on this concept and
make it more general.  Instead of running it from the
c-mode-hook as I've done below, it could be run from the
find-file-hook, and use an alist of regular expressions and
associated boilerplate files.  Similar to the auto-mode-alist,
it would insert user defined boilerplate based on the filename
being edited.  The file to insert could be massaged by a fairly
simple set of macro sustitutions built into the insertion
process to allow using environment variables and Emacs functions
or variables on a per instance basis triggered by macros in the
boilerplate.

Hmmm... sounds like a default "forms" boilerplate; somebody must
have done that already...

;;;
;;;  Insert boilerplate into a new header file
;;;
(defvar fld-header-name-width-max 32)
(defun fld-new-h-header ()
  (interactive)
  (let (
        ;; get file name and extension
        (name (upcase (file-name-sans-extension (buffer-file-name))))
        (extn (upcase (file-name-extension (buffer-file-name)))))

    ;; trim off excessive length
    (when name
      (let ((start 0))
        (while (and (< fld-header-name-width-max (string-width name))
                    (< start (string-width name)))
          (progn
            (when (string= (substring name start (1+ start)) "/")
              (progn
                (setq name (substring name (1+ start) nil))
                (setq start -1)))
            (setq start (1+ start))))))
    ;; to mung, or not to mung...
    (when (or (string= extn "HPP") (string= extn "H"))
      (save-excursion
        (when (< (point-max) 34)
          (progn
            (goto-char (point-min))
            (insert (format "#ifndef _%s.%s_\n#define _%s.%s_\n\n#endif"
                            name extn name extn))))))))

;; add it to c-mode (which assumes the appropriate suffixes are
;; in the auto-mode-alist to enable c-mode for the target files.
(add-hook 'c-mode-hook 'fld-new-h-header)

--
Floyd L. Davidson           <http://web.newsguy.com/floyd_davidson>
Ukpeagvik (Barrow, Alaska)                         floyd@barrow.com

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

* Re: regexp / replacement for variable
  2004-02-22  0:51 ` lawrence mitchell
@ 2004-02-22 12:18   ` Jan Misol
  0 siblings, 0 replies; 8+ messages in thread
From: Jan Misol @ 2004-02-22 12:18 UTC (permalink / raw)


Thanks, this was very helpful ...
(Sorry, the last mail reached you directly ...)

Adding:
   (add-hook 'find-file-hooks 'auto-insert)
to my .emacs does it already!

So I had to upgrade my requirements :)
I found http://www.linuxgazette.com/issue39/marsden.html,
and now it looks like this:

   (define-auto-insert
     (cons "\\.\\([hH].*\\)\\'" "User defined C/C++ header")
     '(nil
       "/*"
       " * Filename: " (buffer-name) "\n"
       " * Author: " (user-full-name) " <" user-mail-address ">\n"
       " * Time-stamp: <>\n"
       " */\n"
       (let* ((prfx (substring buffer-file-name 0 (match-beginning 0)))
            (sffx (substring buffer-file-name (match-beginning 1) (match-end 0)))
            (prfx (file-name-nondirectory prfx))
            (ident (concat "_" (upcase prfx) "_" (upcase sffx) "_")))
         (concat "#ifndef " ident "\n"
                 "#define " ident  "\n\n\n\n"
                 "#endif /* " ident " */\n"))))

   (add-hook 'write-file-hooks 'time-stamp)


Jan

lawrence mitchell wrote:
> Jan Misol wrote:
> 
> 
> [...]
> 
> 
>>>c-x c-f test.h
> 
> 
>>should automatically insert:
> 
> 
>>   #ifndef _TEST_H_
>>   #ifndef _TEST_H_
> 
> 
>>   #endif
> 
> 
> [...]
> 
> 
>>   (defun new-c-header ()
>>     "Insert c-header skeleton."
>>     (interactive "")
>>     (progn
>>       (setq bname (upcase(buffer-name)))
>>       (insert
>>        (message "#ifndef %s\n\#define %s\n\n#endif"
>>           bname bname))))
> 
> 
>>Apart from knowing that "message" might not be the right
>>choice here, I don't know how to modify the value of bname!?
>>"replace-regexp" doesn't seem to be the what I'm looking for.
> 
> 
> Well, how about using `file-name-sans-extension' to strip the
> trailing .h, and then insert using `format'.
> 
> (defun my-new-c-header ()
>   (interactive)
>   (let ((name (upcase (file-name-sans-extension (buffer-file-name)))))
>     ;; Only insert if _name_H isn't already defined.
>     (unless (save-excursion
>               (goto-char (point-min))
>               (search-forward (format "#ifndef _%s_H" name))
>       (insert (format "#ifndef _%s_H\n#define _%s_H\n\n#endif"))))))
> 
> 
>>(and how could the new-c-header() be invoked by creating a
>>new .h/.cpp file?)
> 
> 
> You could then either add this as a hook to `c-mode-hook' or
> `find-file-hooks'.  In the case of the latter, you'd want to
> predicate it on being a header file.  In fact, you'd want to do
> the same for the former too.
> 
> You could do this by adding an extra test to the `unless' form
> in the above function.
> 
> say:
> 
> (unless (and (string-match "\\.h") (buffer-file-name)
>              ...)
>   ...)
> 
> Slightly orthogonal to all this, you may find reading the Emacs
> Lisp Introduction enlightening.
> 
> Alternately, instead of trying to roll your own function, it may
> well be that Emacs already has the functionality you need
> built-in.  See the info node "autotype", in Emacs, you can get
> there via C-h i d m Autotype RET.
> 
> Hope some of this helps.

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

* Re: regexp / replacement for variable
  2004-02-21 23:08 Jan Misol
@ 2004-02-24 13:31 ` Kevin Dziulko
  0 siblings, 0 replies; 8+ messages in thread
From: Kevin Dziulko @ 2004-02-24 13:31 UTC (permalink / raw)



[-- Attachment #1.1: Type: text/plain, Size: 1524 bytes --]

I find file templates easier.  I have this in my .emacs:
 
;; automaticlly start new files with specific templates
(autoload 'auto-insert "autoinsert")
     (add-hook 'find-file-not-found-hooks 'auto-insert)
     (setq auto-insert-query nil)
     (setq auto-insert-directory "myhomedir/.templates/")
     (setq auto-insert-alist
        '(("\\.sh$"       . "template.sh")
          ("\\.pl$"       . "template.pl")))
 
Now all my new *.pl files look like whatever .templates/template.pl looks like.

Jan Misol <misol@liblss.org> wrote:
I'm new to elisp but I want my beloved editor
to generate the standard c-header stuff when creating
a new .h/.hpp header.

> c-x c-f test.h

should automatically insert:

#ifndef _TEST_H_
#ifndef _TEST_H_


#endif

depending on the given filename.

I put the following to my .emacs file:

(defun new-c-header ()
"Insert c-header skeleton."
(interactive "")
(progn
(setq bname (upcase(buffer-name)))
(insert
(message "#ifndef %s\n\#define %s\n\n#endif"
bname bname))))

Apart from knowing that "message" might not be the right
choice here, I don't know how to modify the value of bname!?
"replace-regexp" doesn't seem to be the what I'm looking for.

(and how could the new-c-header() be invoked by creating a
new .h/.cpp file?)

jan


_______________________________________________
Help-gnu-emacs mailing list
Help-gnu-emacs@gnu.org
http://mail.gnu.org/mailman/listinfo/help-gnu-emacs

---------------------------------
Do you Yahoo!?
Yahoo! Mail SpamGuard - Read only the mail you want.

[-- Attachment #1.2: Type: text/html, Size: 2248 bytes --]

[-- Attachment #2: Type: text/plain, Size: 151 bytes --]

_______________________________________________
Help-gnu-emacs mailing list
Help-gnu-emacs@gnu.org
http://mail.gnu.org/mailman/listinfo/help-gnu-emacs

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

* Re: regexp / replacement for variable
       [not found] <mailman.372.1077629684.340.help-gnu-emacs@gnu.org>
@ 2004-02-24 14:03 ` Joakim Hove
  2004-02-24 20:09 ` Floyd Davidson
  1 sibling, 0 replies; 8+ messages in thread
From: Joakim Hove @ 2004-02-24 14:03 UTC (permalink / raw)



Kevin Dziulko <weaselboy1976@yahoo.com> writes:


> depending on the given filename.
>
> I put the following to my .emacs file:
>
> (defun new-c-header ()
> "Insert c-header skeleton."
> (interactive "")
> (progn
> (setq bname (upcase(buffer-name)))
> (insert
> (message "#ifndef %s\n\#define %s\n\n#endif"
> bname bname))))

The (progn  ) construction in your code is superfluous.

Suggestion:

use (let ) to define variables with local scope, in your
implementation the variable bname will be defined and visible for the
complete remaining emacs session.

(let ((bname (upcase (buffer-name)))
      (var2  "value for var2))
   ...
   ...
   ... )

> Apart from knowing that "message" might not be the right
> choice here

That is right - (message ..) prints the contents in the minibuffer. Insert
should do the job:

(insert (format "#ifndef %s\n#define %s\n\n#endif bname bname))


> , I don't know how to modify the value of bname!?  "replace-regexp"
> doesn't seem to be the what I'm looking for.

I don't understand what changes you want to make to bname. Maybe the
(string-match ..) / (match-string ...) functions provide the
functionality you are after?

> (and how could the new-c-header() be invoked by creating a

(add-hook 'c-mode-hook 'new-c-header)

will call new-c-header *every* time you open a .c/.h file, i.e. also
if it is an existing file. Maybe if you start new-c-header like this:

...
(if (= (point-min) (point-max))
   (let ((bname ...
     ...

Warning - there are probably more elegant ways to check whether a file
is new or not.

HTH - Joakim




-- 
  /--------------------------------------------------------------------\
 / Joakim Hove  / hove@bccs.no  /  (55 5) 84076       |                 \
 | Unifob AS, Avdeling for Beregningsvitenskap (BCCS) | Stabburveien 18 |
 | CMU                                                | 5231 Paradis    |
 \ Thormøhlensgt.55, 5020 Bergen.                     | 55 91 28 18     /
  \--------------------------------------------------------------------/

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

* Re: regexp / replacement for variable
       [not found] <mailman.372.1077629684.340.help-gnu-emacs@gnu.org>
  2004-02-24 14:03 ` regexp / replacement for variable Joakim Hove
@ 2004-02-24 20:09 ` Floyd Davidson
  1 sibling, 0 replies; 8+ messages in thread
From: Floyd Davidson @ 2004-02-24 20:09 UTC (permalink / raw)


Kevin Dziulko <weaselboy1976@yahoo.com> wrote:
>I find file templates easier.  I have this in my .emacs:
>
> 
>
>;; automaticlly start new files with specific templates
>
>(autoload 'auto-insert "autoinsert")
>     (add-hook 'find-file-not-found-hooks 'auto-insert)
>     (setq auto-insert-query nil)
>     (setq auto-insert-directory "myhomedir/.templates/")
>
>     (setq auto-insert-alist
>        '(("\\.sh$"       . "template.sh")
>          ("\\.pl$"       . "template.pl")))
>

There is certainly some advantage to using setq to define your
own auto-insert-alist, but it also deletes all of the default
entries too.  To simply add to the auto-insert-alist, or to
replace an existing entry, define-auto-insert could be used to
add the two above entries like this,

   (define-auto-insert "\\.sh$" "template.sh")
   (define-auto-insert "\\.pl$" "template.pl")

You might find some of the default entries useful as is (in
particular the one for HTML is fairly good), or they can also be
used as good examples of what can be done when coding up your
own customized templates.

The defaults are (for GNU Emacs and XEmacs respectively) in files,

   .../lisp/autoinsert.el.
   .../xemacs-packages/lisp/text-modes/autoinsert.el

The builtin defaults for C/C++ headers and programs, eLisp,
HTML, shells, and LaTex don't use a template file, and instead
use code to generate text to be inserted.  For Plain TeX,
BibTeX, Makefiles, and ada it just specifies a template file.

Unfortunately none of the defaults provide an example of using a
template file that is then manipulated by code from the alist
entry.  What I've done is delete all of the defaults by using
setq too, and than also using template files, but all of them
are 1) very similar in form, and 2) all of them are manipulated
by code after being inserted.  Plus (and this idea came from the
HTML default template) a date/time stamp for the file creation
time, and another bit of lisp code that is added to
local-write-file-hooks is used to add and/or update a "Last
update: " time stamp every time the file is modified.

Below is one of the least complex examples.  It is for lisp
programs.  A suitable template file might look like this,

  ;;;;
  ;;;;  **title**
  ;;;;
  ;;;;  **timestamp**
  ;;;;
  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  ;; add the working directory...
  (add-to-list 'load-path "**working_directory**")

though of course it might be (and in reality mine is)
significantly more complex too!  The actual text inserted into
the new file would look like this,

  ;;;;
  ;;;;  foo.el             --
  ;;;;
  ;;;;  Copyright 2004 by Floyd L. Davidson, floyd@barrow.com
  ;;;;  File created:  Tue Feb 24 10:32:57 2004
  ;;;;
  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  ;; add the working directory...
  (add-to-list 'load-path "/home/floyd/lispsrc/")

The cursor is left two spaces past the "--", where in my
case I would then write a short description of what this
file is.  In my case, though the code to make this happen
is not part of the example below, when this file is modified,
if it is written to disk another line will be added below
the one that gives the "File created" date/time, which is
formated the same but says "Last updated:".  That line is
then automatically changed any time that file is edited.

Here is the alist entry to manipulate a template file.

  (("\\.el\\'" "Emacs Lisp Program Template") nil
    ;;
    ;; It is necessary to wrap the following code inside a
    ;; (let ...) function to prevent each command's return
    ;; value from being inserted into the file.  Inside the
    ;; (let ...) function insertions are made the usual way,
    ;; otherwise all strings are inserted by the auto-insert
    ;; package when this executes.
    ;;
    (let ((dummy0 "xxxxx"))
      (goto-char (point-min))
      (insert-file (concat "" auto-insert-directory "lisp-program.inc"))
      (goto-char (point-min))
      (replace-string "**title**"
          (concat (file-name-nondirectory buffer-file-name)
              (when (> 16 (string-width (file-name-nondirectory buffer-file-name)))
                (make-string
                 (- 17 (string-width (file-name-nondirectory buffer-file-name))) ?\ ))
              "  --"))
      (goto-char (point-min))
      (replace-string "**timestamp**" (concat "File created:  " (current-time-string)))
      (beginning-of-line)
      (insert ";;;;  Copyright ")
      (insert (substring (current-time-string) -4 nil) " by ")
      (insert (user-full-name) ", ")
      (insert user-mail-address "\n")
      (goto-char (point-min))
      (replace-string "**working_directory**" (file-name-directory buffer-file-name))
      (goto-char (point-min))
      (replace-regexp "--$" "--  ")
      (message "")))

Note that this /requires/ user-mail-address to return a string.
If it is not defined by set-custom-variables, something should
be put in ~/.emacs to cause it to be defined.  Here is an
example, which does other useful things too,

  ;;
  ;; Can't do this in init.el because custom.el is loaded later.
  ;;
  (add-hook 'select-frame-hook    (lambda ()
  "Set email address correctly before auto-insertion."
  (if (or (not user-mail-address) (> 3 (string-width user-mail-address)))
      (setq user-mail-address
            (concat (user-login-name) "@"
                    (or mail-host-address (system-name)))))
  (when (or (not user-mail-address) (> 3 (string-width user-mail-address)))
    (setq user-mail-address "nobody@home.here"))

  (setq html-helper-address-string
        (concat "<a href=\"mailto:"  user-mail-address
                "\"> Contact by email:  " (user-full-name) "</a>"))))

--
Floyd L. Davidson           <http://web.newsguy.com/floyd_davidson>
Ukpeagvik (Barrow, Alaska)                         floyd@barrow.com

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

end of thread, other threads:[~2004-02-24 20:09 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <mailman.372.1077629684.340.help-gnu-emacs@gnu.org>
2004-02-24 14:03 ` regexp / replacement for variable Joakim Hove
2004-02-24 20:09 ` Floyd Davidson
     [not found] <mailman.262.1077404990.340.help-gnu-emacs@gnu.org>
2004-02-22  0:41 ` Kin Cho
2004-02-22  0:51 ` lawrence mitchell
2004-02-22 12:18   ` Jan Misol
2004-02-22 12:14 ` Floyd Davidson
2004-02-21 23:08 Jan Misol
2004-02-24 13:31 ` Kevin Dziulko

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).