e: a tiny editor plugin for eTcl

Richard Suchenwirth 2006-01-16 - With the eTcl distribution for PocketPC I have taken up doing weekend fun projects again. Here's the fruit of last Sunday, simple, but already very useful:

  • a really compact editor that can be called from the eTcl console with a file or proc name,
  • called without argument, e just brings up the edit window, so one can switch
  • displays the content in a window that leaves room for the virtual keyboard
  • can save the content to file again, or evaluate it (e.g. for modified procs)
  • Most of edit functionality is from text anyway, just need menu items to invoke them

WikiDbImage e2.jpg

Update 2006-02-05: adding 9 lines of code brought coloring for proc and comment lines. Marked as #(1)

The main function builds the UI too, if not already there:

 proc e {{name ""}} {
    if ![winfo exists .t] {
       toplevel .t
       text .t.t -wrap word -yscr ".t.y set" -width 37 -bd 2 -undo 1
       scrollbar .t.y -com ".t.t yview"
       pack .t.t .t.y -side left -fill y
       .t.t tag config red -foreground red   ;#(1)
       .t.t tag config blue -foreground blue ;#(1)
       set m [menu .t.m]
       .t config -menu $m
       m+ $m File Open.. e'open
       m+ $m File Save {e'save $::g(filename)}
       m+ $m File "Save as.." e'save
       m+ $m File ---
       m+ $m File Eval {eval [.t.t get 1.0 end]}
       m+ $m File Clear {.t.t delete 1.0 end}
       m+ $m File ok {console eval {raise .; focus -force .console}}
       foreach i {Cut Copy Paste} {
          m+ $m Edit $i [list event gen .t.t <<$i>>]
       }
       m+ $m Edit ---
       m+ $m Edit Undo {.t.t edit undo}
       m+ $m Edit Redo {.t.t edit redo}
       wm geo .t 240x189+0+25
       set ::g(dir) [pwd]
    }
    if {$name ne ""} {
       .t.t delete 1.0 end
       #.t.t insert end [e'get $name] - now replaced by: #(1)
       foreach line [split [e'get $name] \n] {
          if [regexp {^\s*proc } $line] {
                set tag blue
          } elseif {[regexp {^\s*#} $line]} {
                set tag red
          } else {set tag ""}
          .t.t insert end $line\n $tag
        }
        wm title .t [file tail $name]
    }
    raise .t
    focus -force .t.t
 }

#-- Dispatcher for content types - file or proc

 proc e'get name {
   if [file exists $name] {
      set f [open $name]
      set ::g(filename) $name
      K [read $f] [close $f]
   } else {corp $name}
 }
 proc K {a b} {set a}

#-- reconstruct a proc's full text, with args and defaults (see corp for more)

 proc corp name {
   set argl {}
   foreach a [info args $name] {
      if [info default $name $a def] {
         lappend a $def
      }
      lappend argl $a
   }
   list proc $name $argl [info body $name]
 }

#-- File I/O

 proc e'open {} {
    e [tk_getOpenFile -initialdir $::g(dir)]
 }
 proc e'save {{file ""}} {
   if {$file eq ""} {
      set file [tk_getSaveFile -initialdir $::g(dir)]
   }
   if {$file ne ""} {
      set ::g(dir) [file dir [file join [pwd] $file]]
      set f [open $file w]
      puts $f [.t.t get 1.0 "end - 1c"]
      close $f
   }
 }

#--- Wrapper for simple menu definition

 proc m+ {m head label {cmd ""}} {
   if ![winfo ex $m.m$head] {
      $m add casc -label $head -menu [menu $m.m$head -tearoff 0]
   }
   if {$label ne "---"} {
      $m.m$head add command -label $label -command $cmd
   } else {$m.m$head add separator}
 }

Some more goodies: the following menu items make navigating in larger files very convenient:

      m+ $m Goto Top    {.t.t see 1.0}
      m+ $m Goto Cursor {.t.t see insert}
      m+ $m Goto Bottom {.t.t see end}

And for a feature that most M$ editors, and even emacs don't fully provide: displaying the cursor line and column position. For this I make creative use of the menu, by adding a dummy with the label @. Whenever the mouse is clicked in the text, the label is updated to show the current position:

      $m add casc -label @ -menu [menu $m.dummy]
      bind .t.t <ButtonRelease-1> {.t.m entryconf @* -label @[.t.t index current]; xx}

The xx was a necessary workaround in eTcl at least pl4 (fixed since pl6), to prevent that the menu is repeatedly displayed:

 proc xx {} {
   .t config -menu ""
   .t config -menu .t.m
 }

Little code that does much - that's why I love Tcl !-)

A helpful plug-in for this plug-in is Simple search and replace - it just takes two lines more (provided you have it in auto_index reach):

 m+ $m Edit Search  {searchrep .t.t 0}
 m+ $m Edit Replace {searchrep .t.t}

  [gold] Here is optional convert subroutine to  
 add 4 spaces in front of  text lines,
 used to move over small amounts
 of text in Tcl Wiki preparation. Routine merely inserts
 converted code in front of previous entries.
        proc convert {w} {
        set x [.t.t get 1.0 "end - 1c"]
        set y {}
        #26Apr2007,gold
        foreach l [split $x "\n"] {
        set space "    "        ] {
        set y "$y $space $l\n"
        }
        .t.t insert @0,0 $y
      }
      #suggest following statements to proc e 
      m+ $m Edit convert {convert .t.t}
      m+ $m exit "exit" exit

EF I have repackaged this into a proper package that does (hopefully) the same. The package incorporates all the additions listed above. It is available in e: a packaged tiny editor for eTcl.


MB: After RS and EF work, I extended the possibilities of the editor and released it as an open-source sourceforge project :

http://tclrep.wiki.sourceforge.net/PocketEditor

It is now OO, based on SNIT. The main features are :

 * manage several texts,
 * find/replace dialog as a toolbar (to increase the usability on PDA),
 * file reload, 
 * etc...

This editor inspired another author, who released "ficedit", "un éditeur de texte tout ce qu'il y a de plus simple". :

http://newmagic.progs.googlepages.com/ficedit


See also Sepp.


JM Richard, is the following problem also showing up in this distribution?

Native file selectors allow only to choose files from /My Documents and (only one level?) below. - RS: Yes, but I see this as a (mis)feature of Windows/CE and avoid the selector where I can (calling e from the console, with Tab completion, it is more convenient). Also, as only the tail of directory paths are shown, I'm not sure how the file selector would handle directories ../foo/bar and ../grill/bar on the same device. In iFile 1.1 there's a hierarchic path browser, and I'm planning to isolate that for eTcl, based on LemonTree... soon here :^)

- JM so, at this moment, within this tiny editor,it is not possible to open a file for edition using File>>>Open when that file is not under "My Documents" folder, right? - RS: So it appears, yes - but as the console does filename completion, it's easy to re-call "e" from there (that's why I gave it so short a name :^)

2006-02-14 HE - perhaps Alternative dialogs for pocketPC/etcl can help.