[Mac] Python mode for Alpha editor
Howard Oakley
Howard at quercus.demon.co.uk
Fri Sep 17 15:05:07 EDT 1999
Gentlepersons,
I looked in vain for a Python mode for the wonderful (if Tcl-based!) text
editor, Alpha. I could not find any. Here, below, is an Alpha mode file for
Python, which makes the Alpha text editor much more usable for editing
Python code. Please feel free to post it anywhere that you feel
appropriate. The code works fine here, but is kludgy and largely borrowed
from other Tcl mode files - I could hardly claim any sort of copyright
anyway!
I am also sending it to Pete Keleher, the author of Alpha, and Jack Jansen.
Howard.
--------------cut here-----------------
# (auto-install)
#############################################################################
# pythonMode.tcl
# Howard Oakley, EHN & DIJ Oakley
# howard at quercus.demon.co.uk
#
# Description:
# This auto-installing file implements a simple mode for editing
# Python using Alpha. It has been tested with Alpha version 7.2.
# The features of this mode include:
# syntax colouring - comments in red, strings (some) in green,
# keywords in blue, and colons (a Python particular) in magenta
# easy production of comment boxes etc.
# def and class marking - automatically generated marks (M popup) give
# the function name first, and then the class (if any), whilst class
# definitions give the class name twice; the {} popup takes
# you to class definitions
# automatic indentation - given the importance of this in Python control
# structures, this was an essential, and is accomplished
# using tabs in syntactic context.
# The code below is a cobbling together of code stolen from other sources.
# Whilst the fine code of the original sources is reliable, there are
# all sorts of nasty kludges which I have used to get it to do what
# I needed. Tcl purists who can improve on it are invited to do so:
# please e-mail your corrections to me so that I can maintain this.
# My thanks and apologies to those from whom I have stolen code.
# Version: 1.0 dated 17 Sep 1999 [or if you prefer it, 1999-09-17].
#############################################################################
alpha::mode Pyth 1.0 dummyPyth {*.py} {electricBraces electricTab
electricReturn}
newPref v leftFillColumn {1} Pyth
newPref v wordBreak {\w+} Pyth
newPref f wordWrap {0} Pyth
newPref v funcExpr {^[ \t]*(def|class)[ \t]+([A-Za-z0-9_]+)} Pyth
newPref v parseExpr {^[ \t]*([A-Za-z0-9_]*)} Pyth
newPref v wordBreakPreface {\W} Pyth
newPref f autoMark 0 Pyth
proc dummyPyth {} {}
# I extend the range of keywords a little, to include some type conversions
# and other important items
set pythKeyWords {
access and break class continue def del elif else
except exec finally for from global if import in
is lambda not or pass print raise return self try while
= < > <= >= + * - / != <> % | ^ &
len min max ~ abs int long float complex divmod pow
list map tuple eval string repr assert
}
regModeKeywords -e {#} -s green -c red -i : -I magenta -k blue Pyth
$pythKeyWords
unset pythKeyWords
hook::register saveHook modified "Pyth"
#================================================================================
# for Tcl 8.0 compatibility, hopefully
namespace eval Pyth {}
#================================================================================
proc dummyPyth {} {}
# for easy production of comment boxes etc.
set commentCharacters(Pyth:General) "\#"
set commentCharacters(Pyth:Paragraph) [list "#----" "#----" "#"]
set commentCharacters(Pyth:Box) [list "#" 2 "#" 2 "#" 3]
# the mark routine, which has to append the class name *if* the definition
is
# part of a class definition, but reset the empty class name if it is not,
# i.e. there is no leading whitespace before the 'def'
# - this therefore builds the M popup menu.
proc Pyth::MarkFile {} {
global PythmodeVars
set pos [minPos]
set classnom ""
while {![catch {search -s -f 1 -r 1 -m 0 -i 1 $PythmodeVars(funcExpr)
$pos} res]} {
set start [lindex $res 0]
set end [pos::math [lindex $res 1] + 1]
set text [getText $start $end]
if {[regexp -indices {(class)[ \t]+([a-zA-Z0-9_]+)} $text dummy
dummy0 pname]} {
set i1 [expr [lindex $pname 0] + $start]
set i2 [expr [lindex $pname 1] + $start + 1]
# this is the start of a class definition, so save the class name
set classnom [getText $i1 $i2]
} else {
if {$pos > [minPos]} {
set pp [pos::math $start - 1]
set pq [pos::math $start + 1]
set pr [getText $pp $pq]
if {![regexp {[ \t]+} $pr]} {
# this is a standalone def, therefore reset the class name to an empty
string
set classnom ""
}
}
}
if {[regexp -indices {(def|class)[ \t]+([a-zA-Z0-9_]+)} $text dummy
dummy0 pname]} {
set i1 [expr [lindex $pname 0] + $start]
set i2 [expr [lindex $pname 1] + $start + 1]
set word [getText $i1 $i2]
set tmp [concat $i1 $i2]
# assemble the marker name with the def element first, followed by any
class name
set ol_word [ join [concat $word " " $classnom ""] ]
set inds($ol_word) $tmp
}
set pos $end
}
if {[info exists inds]} {
foreach f [lsort -ignore [array names inds]] {
set res $inds($f)
setNamedMark $f [lineStart [lindex $res 0]] [lindex $res 0] [lindex $res
1]
}
}
}
# this builds the {} menu along similar lines, but this time with just
class definitions
proc Pyth::parseFuncs {} {
global PythmodeVars
set pos [minPos]
while {![catch {search -s -f 1 -r 1 -m 0 -i 1 $PythmodeVars(funcExpr)
$pos} res]} {
set start [lindex $res 0]
set end [pos::math [lindex $res 1] + 1]
set text [getText $start $end]
if {[regexp -indices {(class)[ \t]+([a-zA-Z0-9_]+)} $text dummy
dummy0 pname]} {
set i1 [expr [lindex $pname 0] + $start]
set i2 [expr [lindex $pname 1] + $start + 1]
set word [getText $i1 $i2]
set tmp [concat $i1 $i2]
set inds($word) $tmp
}
set pos $end
}
set rtnRes {}
if {[info exists inds]} {
foreach f [lsort -ignore [array names inds]] {
set next [nextLineStart $inds($f)]
lappend rtnRes $f $next
}
}
return $rtnRes
}
proc Pyth::indentLine {} {
# get details of current line
set beg [lineStart [getPos]]
set text [getText $beg [nextLineStart $beg]]
regexp "^\[ \t\]*" $text white
set len [string length $white]
set epos [pos::math $beg + $len]
# Find last previous non-comment line and get its leading whitespace
set pos $beg
while 1 {
if {[catch {search -s -f 0 -r 1 -i 0 -m 0 "^\[ \t\]*\[^ \t\r\n\]"
[pos::math $pos - 1]} lst]} {
# search failed at top of file
set line "#"
set lwhite 0
break
}
if {![catch {text::inCommentBlock [lindex $lst 0]} res]} {
set pos [lindex $res 0]
} else {
set line [getText [lindex $lst 0] [pos::math [nextLineStart [lindex
$lst 0]] - 1]]
set lwhite [posX [pos::math [lindex $lst 1] - 1]]
break
}
}
# we need (syntactically) to increase the tabs by 1, so first do this using
# spaces, and then convert the spaces to a tab. This is not elegant, but it
works!
if {[regexp ":\[ \t\]*$" $line]} {
getWinInfo a
set ps $a(tabsize)
incr lwhite $ps
}
set lwhite [text::indentOf $lwhite]
if {$white != $lwhite} {
replaceText $beg $epos $lwhite
select $beg [$beg + [string length $lwhite]]
spacesToTabs
}
goto [pos::math $beg + [string length $lwhite]]
}
------------end---------------
More information about the Python-list
mailing list