Version 5 of emacs package to insert templated code interactively

Updated 2007-11-12 04:09:22 by escargo

Templating system for Tcl in Emacs

Snippet.el from various sources will have you quickly removing the drudgery out of the common chores you have to do when writing Tcl scripts. Let's face it; a lot of things that you write in scripts are repetitive, and this is where a templating system comes in handy.

Features:

  • Typing simple keywords and a space will expand to a template that you specify.
  • You can specify hot spots where you provide information that will change in your template.
  • hot spots can be linked so change in one hotspot will be reflected in all linked hot spots. Imagine filling out the comments at the top of the proc and having the proc arguments, global declaration, namespace and proc name all change as you progress through the template.
  • Easy to create more templates for how you use Tcl.

Installation:

  • Download snippet.el from [L1 ] and put that either in your .emacs.d directory or any directory in your load path. The file is well commented and will inform you on how to create templates. What I include below will get you up and running quickly. You will need to read the comments at the top of this file if you want to add more or edit any more templates.
  • Edit your ~/.emacs initialization file to add the following text to add the abbrev hooks for Tcl and some sample templates.
  • Test by starting up emacs, press M-x tcl-mode (or, if emacs is correctly configured, load a file with .tcl extension and tcl-mode will be set) then type "scriptstart ". Note you must type the space at the end to get the template to appear.
 #!/bin/sh
 # the next line restarts using wish \
 exec /opt/usr/bin/tclsh8.5  "$0" ${1+"$@"}
  • I provide a template that lists the abbrev that are provided. Type "help " and the list will appear. Just do an undo (typically a Ctrl-/ to remove it).

Enjoy. I Bezoar would like to see other emacsen add their own templates and improvements!


 (load-file (expand-file-name "~/.emacs.d/snippet.el" ) ) 
 (custom-set-variables
   ;; custom-set-variables was added by Custom -- don't edit or cut/paste it!
   ;; Your init file should contain only one such instance.
  '(abbrev-mode t)
  '(save-abbrevs t)
  '(snippet-exit-identifier "~.")
  '(snippet-field-identifier "~~"))

 (defun inside-comment-p (&optional on)
   "Is the point inside a comment?
 Optional ON means to also count being on a comment start."
   ;; Note: this only handles single-character commenting, as in lisp.
   (or (and on (looking-at "\\s<"))
       (save-excursion
         (skip-syntax-backward "^><")
         (and (not (bobp))
              (eq (char-syntax (preceding-char)) ?\<)))))

; this is not necessary for snippet but helps keep common misspellings down

 (define-abbrev-table 'text-mode-abbrev-table '(
     ("teh" "the" nil 6)
     ("fo" "of" nil 4)
     ("taht" "that" nil 3)
     ("alos" "also" nil 0)
     ("ign" "ing" nil 2)
     ("adn" "and" nil 1)
     ))
 ; make sure the abrev table exists 
 (define-abbrev-table 'tcl-mode-abbrev-table '(
     ("teh" "the" nil 6)
      ))

 (add-hook 'pre-abbrev-expand-hook
              (lambda ()
                (setq local-abbrev-table
                      (if (inside-comment-p)
                          text-mode-abbrev-table)))
              nil t)

 (snippet-with-abbrev-table 'tcl-mode-abbrev-table
 ("forf" .  "for { set ~~{variable} 0 } { $~~{variable} < ~~{limit} } {incr ~~{variable} } { 
 ~. 
 }")
 ("reqf"  .  "if { [ catch {package require ~~{package} } err ] != 0 } {
 $>puts stderr \"Unable to find package ~~{package} ... adjust your auto_path!\";
 }")
 ("orf"      . "[expr ( ~~{boolean} )  ? ~~{iftrue} : ~~{iffalse} ]" )
 ("ifeqstr"  .  "if { [ string equal ~~{str1} ~~{str2} ] }  { 
   ~.
 }")
 ("whilef"  .  "while { ~~{True} } { 
 $>~.
 }")
 ("iff"  .  "if { ~~{True} } {
 $>~.
 } ")
 ("execf"    . "if { [ catch { exec ~~{program} } ~~{buffer} ] != 0 } {
 $>error \"Unable to execute ~~{program} : $~~{buffer}\"
 } else {
 $>~.
 }")
 ("tryf"    . "try { 
 $>~.  
 } catch {
 $>puts \"$errorResult\\n$errorInfo\"
 }")
 ("scriptstart"  . "#!/bin/sh
  # the next line restarts using wish \\
  exec /opt/usr/bin/tclsh8.5  \"$0\" ${1+\"$@\"}
  ~." )
 ("cmdlinef" . "package require cmdline;
 package require log
 global usage options
 set options {
  $>{~~{flag}          \"~~{flag_description}\"}
  $>{~~{opt}.arg  ~~{defaultValue}  \"~~{option_description}\"}
  $>{ v         \"verbose\" } 
  $>{ vv        \"double verbose\" } 
  $>{ vvv       \"debug level verboseness\" } 
 }
 $> set usage \": $argv0 \\[options\\]  ...\\noptions:\"
 $> array set params [::cmdline::getoptions argv $options $usage]
 foreach level [ log::levels ] {
       log::lvSuppress $level 1 
 }
 if { $params(v)  } {
 $>    foreach level { notice warning error } {
 $>          log::lvSuppress $level 0
 $>    }
 } elseif { $params(vv) } {
 $>    foreach level { notice info  warning error } {
 $>          log::lvSuppress $level 0
 $>    }
 } elseif { $params(vvv) } {
 $>    foreach level { notice info debug warning error } {
 $>          log::lvSuppress $level 0
 $>    }
 } else { 
 $>    foreach level {  warning error } {
 $>          log::lvSuppress $level 0
 $>    }
 }
 log::lvCmdForall logproc ; # provide this function or delete line
 log::lvChannelForall stdout
 # adjust your cmd flags and args here
 $> if {  $params(~~{flag}) } { 
 $>~.
 } ")
 ("procf" . "#-------------------------------------------------------------------------
 # ProcName: ~~{myproc}
 # Description: ~~{description}
 # Arglist :  ~~{arglist} 
 # Globals :  ~~{globals}
 # namespace: ~~{namespace} 
 # returns:   ~~{ 1 on success, 0 on failure}
 #-------------------------------------------------------------------------
 proc ~~{namespace}::~~{myproc} { ~~{arglist} } {
     $>global ~~{globals} ; # delete me if no globals
     $>set retval 1
     ~.
     $>return $retval;
 }" )
 ("streq"  . "[string equals ~~{first} ~~{second} ]")
 ("strfirst"  . " [string first ~~{searchfor} ~~{inthisstring} ]" )
 ("prov"  .  "package provide ~~{package} ~~{version};
   namespace eval ~~{package} {
  $>variable {} (~~{item}) ~~{value} 
  $>proc _get { name } {
  $> variable {}
  $> if { [ info exists ($name) ] } { return $name }
  $> return \"\";
  $>}
  $>proc _set { name value } {
  $>   variable {}
  $>   set ($name) $value 
  $>}
  $>foreach name [ array names {} ] { 
  $> eval \" proc set$name \\{ value \\} \\{
  $>         _set $name \$value
  $>       \\} 
  $>       proc get$name \\{ \\} \\{
  $>         return [_get $name ]
  $>      \\}\"
  $>}
 }")
 ( "help" . "\# ------------------ Emacs snippets for tcl ----- 
 $>\# forf        - forloop with body
 $>\# expectf     - full expect loop 
 $>\# reqf         - package require xxx
 $>\# orf         - expr ? expansion
 $>\# ifeqstr     - if { [ string equal XX YY ] }  
 $>\# iff         - same as if but with complete body
 $>\# whilef      - while { XXX } { }
 $>\# procf       - documentation and proc header line with namespace support
 $>\# scriptstart - Start code for script file 
 $>\# tryf        - Tclx try/catch complete with body
 $>\# strfirst    - [string first XXX YYYY ]
 $>\# streq       - [string equal XX YY ]
 4>\# execf       -  exec with error catching
 $>\# cmdlinef    - create option processing for commandline
 $>\# prov        - package provide .... includes namespace defaults
 \#------------------------------------------------------------" )
 ("expectf" . "set ~~{spawn_id} $spawn_id;
 set bad 0;
 set done 0;
 exp_internal 0; \# set to one for extensive debug
 log_user 0; \# set to one to watch action
 expect {
 $>-i ~~{spawn_id}
 $>-re {~.} {
 $>    exp_continue;
 $>  }
 $>timeout { 
 $>   puts \"timeout\"
 $>   set bad 1
 $>}
 $>fullbuffer {
 $>  puts \" buffer is full\"
 $>  exp_continue;
 $>}
 $>eof {
 $>     puts \"Eof detected \"
 $>     set done 1 ;
 $>}
 }
 if { $bad || $done } { 
 $>set exitstatus [ exp_wait -i ~~{spawn_id} ];
 $>catch { exp_close -i ~~{spawn_id} };
 }")