history.tcl
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:9k
源码类别:

通讯编程

开发平台:

Visual C++

  1. # history.tcl --
  2. #
  3. # Implementation of the history command.
  4. #
  5. # RCS: @(#) $Id: history.tcl,v 1.5.14.1 2005/07/22 21:59:40 dgp Exp $
  6. #
  7. # Copyright (c) 1997 Sun Microsystems, Inc.
  8. #
  9. # See the file "license.terms" for information on usage and redistribution
  10. # of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  11. #
  12. # The tcl::history array holds the history list and
  13. # some additional bookkeeping variables.
  14. #
  15. # nextid the index used for the next history list item.
  16. # keep the max size of the history list
  17. # oldest the index of the oldest item in the history.
  18. namespace eval tcl {
  19.     variable history
  20.     if {![info exists history]} {
  21. array set history {
  22.     nextid 0
  23.     keep 20
  24.     oldest -20
  25. }
  26.     }
  27. }
  28. # history --
  29. #
  30. # This is the main history command.  See the man page for its interface.
  31. # This does argument checking and calls helper procedures in the
  32. # history namespace.
  33. proc history {args} {
  34.     set len [llength $args]
  35.     if {$len == 0} {
  36. return [tcl::HistInfo]
  37.     }
  38.     set key [lindex $args 0]
  39.     set options "add, change, clear, event, info, keep, nextid, or redo"
  40.     switch -glob -- $key {
  41. a* { # history add
  42.     if {$len > 3} {
  43. return -code error "wrong # args: should be "history add event ?exec?""
  44.     }
  45.     if {![string match $key* add]} {
  46. return -code error "bad option "$key": must be $options"
  47.     }
  48.     if {$len == 3} {
  49. set arg [lindex $args 2]
  50. if {! ([string match e* $arg] && [string match $arg* exec])} {
  51.     return -code error "bad argument "$arg": should be "exec""
  52. }
  53.     }
  54.     return [tcl::HistAdd [lindex $args 1] [lindex $args 2]]
  55. }
  56. ch* { # history change
  57.     if {($len > 3) || ($len < 2)} {
  58. return -code error "wrong # args: should be "history change newValue ?event?""
  59.     }
  60.     if {![string match $key* change]} {
  61. return -code error "bad option "$key": must be $options"
  62.     }
  63.     if {$len == 2} {
  64. set event 0
  65.     } else {
  66. set event [lindex $args 2]
  67.     }
  68.     return [tcl::HistChange [lindex $args 1] $event]
  69. }
  70. cl* { # history clear
  71.     if {($len > 1)} {
  72. return -code error "wrong # args: should be "history clear""
  73.     }
  74.     if {![string match $key* clear]} {
  75. return -code error "bad option "$key": must be $options"
  76.     }
  77.     return [tcl::HistClear]
  78. }
  79. e* { # history event
  80.     if {$len > 2} {
  81. return -code error "wrong # args: should be "history event ?event?""
  82.     }
  83.     if {![string match $key* event]} {
  84. return -code error "bad option "$key": must be $options"
  85.     }
  86.     if {$len == 1} {
  87. set event -1
  88.     } else {
  89. set event [lindex $args 1]
  90.     }
  91.     return [tcl::HistEvent $event]
  92. }
  93. i* { # history info
  94.     if {$len > 2} {
  95. return -code error "wrong # args: should be "history info ?count?""
  96.     }
  97.     if {![string match $key* info]} {
  98. return -code error "bad option "$key": must be $options"
  99.     }
  100.     return [tcl::HistInfo [lindex $args 1]]
  101. }
  102. k* { # history keep
  103.     if {$len > 2} {
  104. return -code error "wrong # args: should be "history keep ?count?""
  105.     }
  106.     if {$len == 1} {
  107. return [tcl::HistKeep]
  108.     } else {
  109. set limit [lindex $args 1]
  110. if {[catch {expr {~$limit}}] || ($limit < 0)} {
  111.     return -code error "illegal keep count "$limit""
  112. }
  113. return [tcl::HistKeep $limit]
  114.     }
  115. }
  116. n* { # history nextid
  117.     if {$len > 1} {
  118. return -code error "wrong # args: should be "history nextid""
  119.     }
  120.     if {![string match $key* nextid]} {
  121. return -code error "bad option "$key": must be $options"
  122.     }
  123.     return [expr {$tcl::history(nextid) + 1}]
  124. }
  125. r* { # history redo
  126.     if {$len > 2} {
  127. return -code error "wrong # args: should be "history redo ?event?""
  128.     }
  129.     if {![string match $key* redo]} {
  130. return -code error "bad option "$key": must be $options"
  131.     }
  132.     return [tcl::HistRedo [lindex $args 1]]
  133. }
  134. default {
  135.     return -code error "bad option "$key": must be $options"
  136. }
  137.     }
  138. }
  139. # tcl::HistAdd --
  140. #
  141. # Add an item to the history, and optionally eval it at the global scope
  142. #
  143. # Parameters:
  144. # command the command to add
  145. # exec (optional) a substring of "exec" causes the
  146. # command to be evaled.
  147. # Results:
  148. #  If executing, then the results of the command are returned
  149. #
  150. # Side Effects:
  151. # Adds to the history list
  152.  proc tcl::HistAdd {command {exec {}}} {
  153.     variable history
  154.     # Do not add empty commands to the history
  155.     if {[string trim $command] eq ""} {
  156. return ""
  157.     }
  158.     set i [incr history(nextid)]
  159.     set history($i) $command
  160.     set j [incr history(oldest)]
  161.     unset -nocomplain history($j)
  162.     if {[string match e* $exec]} {
  163. return [uplevel #0 $command]
  164.     } else {
  165. return {}
  166.     }
  167. }
  168. # tcl::HistKeep --
  169. #
  170. # Set or query the limit on the length of the history list
  171. #
  172. # Parameters:
  173. # limit (optional) the length of the history list
  174. #
  175. # Results:
  176. # If no limit is specified, the current limit is returned
  177. #
  178. # Side Effects:
  179. # Updates history(keep) if a limit is specified
  180.  proc tcl::HistKeep {{limit {}}} {
  181.     variable history
  182.     if {$limit eq ""} {
  183. return $history(keep)
  184.     } else {
  185. set oldold $history(oldest)
  186. set history(oldest) [expr {$history(nextid) - $limit}]
  187. for {} {$oldold <= $history(oldest)} {incr oldold} {
  188.     unset -nocomplain history($oldold)
  189. }
  190. set history(keep) $limit
  191.     }
  192. }
  193. # tcl::HistClear --
  194. #
  195. # Erase the history list
  196. #
  197. # Parameters:
  198. # none
  199. #
  200. # Results:
  201. # none
  202. #
  203. # Side Effects:
  204. # Resets the history array, except for the keep limit
  205.  proc tcl::HistClear {} {
  206.     variable history
  207.     set keep $history(keep)
  208.     unset history
  209.     array set history [list 
  210. nextid 0
  211. keep $keep
  212. oldest -$keep
  213.     ]
  214. }
  215. # tcl::HistInfo --
  216. #
  217. # Return a pretty-printed version of the history list
  218. #
  219. # Parameters:
  220. # num (optional) the length of the history list to return
  221. #
  222. # Results:
  223. # A formatted history list
  224.  proc tcl::HistInfo {{num {}}} {
  225.     variable history
  226.     if {$num eq ""} {
  227. set num [expr {$history(keep) + 1}]
  228.     }
  229.     set result {}
  230.     set newline ""
  231.     for {set i [expr {$history(nextid) - $num + 1}]} 
  232.     {$i <= $history(nextid)} {incr i} {
  233. if {![info exists history($i)]} {
  234.     continue
  235. }
  236. set cmd [string map [list n nt] [string trimright $history($i)  n]]
  237. append result $newline[format "%6d  %s" $i $cmd]
  238. set newline n
  239.     }
  240.     return $result
  241. }
  242. # tcl::HistRedo --
  243. #
  244. # Fetch the previous or specified event, execute it, and then
  245. # replace the current history item with that event.
  246. #
  247. # Parameters:
  248. # event (optional) index of history item to redo.  Defaults to -1,
  249. # which means the previous event.
  250. #
  251. # Results:
  252. # Those of the command being redone.
  253. #
  254. # Side Effects:
  255. # Replaces the current history list item with the one being redone.
  256.  proc tcl::HistRedo {{event -1}} {
  257.     variable history
  258.     if {$event eq ""} {
  259. set event -1
  260.     }
  261.     set i [HistIndex $event]
  262.     if {$i == $history(nextid)} {
  263. return -code error "cannot redo the current event"
  264.     }
  265.     set cmd $history($i)
  266.     HistChange $cmd 0
  267.     uplevel #0 $cmd
  268. }
  269. # tcl::HistIndex --
  270. #
  271. # Map from an event specifier to an index in the history list.
  272. #
  273. # Parameters:
  274. # event index of history item to redo.
  275. # If this is a positive number, it is used directly.
  276. # If it is a negative number, then it counts back to a previous
  277. # event, where -1 is the most recent event.
  278. # A string can be matched, either by being the prefix of
  279. # a command or by matching a command with string match.
  280. #
  281. # Results:
  282. # The index into history, or an error if the index didn't match.
  283.  proc tcl::HistIndex {event} {
  284.     variable history
  285.     if {[catch {expr {~$event}}]} {
  286. for {set i [expr {$history(nextid)-1}]} {[info exists history($i)]} 
  287. {incr i -1} {
  288.     if {[string match $event* $history($i)]} {
  289. return $i;
  290.     }
  291.     if {[string match $event $history($i)]} {
  292. return $i;
  293.     }
  294. }
  295. return -code error "no event matches "$event""
  296.     } elseif {$event <= 0} {
  297. set i [expr {$history(nextid) + $event}]
  298.     } else {
  299. set i $event
  300.     }
  301.     if {$i <= $history(oldest)} {
  302. return -code error "event "$event" is too far in the past"
  303.     }
  304.     if {$i > $history(nextid)} {
  305. return -code error "event "$event" hasn't occured yet"
  306.     }
  307.     return $i
  308. }
  309. # tcl::HistEvent --
  310. #
  311. # Map from an event specifier to the value in the history list.
  312. #
  313. # Parameters:
  314. # event index of history item to redo.  See index for a
  315. # description of possible event patterns.
  316. #
  317. # Results:
  318. # The value from the history list.
  319.  proc tcl::HistEvent {event} {
  320.     variable history
  321.     set i [HistIndex $event]
  322.     if {[info exists history($i)]} {
  323. return [string trimright $history($i)  n]
  324.     } else {
  325. return "";
  326.     }
  327. }
  328. # tcl::HistChange --
  329. #
  330. # Replace a value in the history list.
  331. #
  332. # Parameters:
  333. # cmd The new value to put into the history list.
  334. # event (optional) index of history item to redo.  See index for a
  335. # description of possible event patterns.  This defaults
  336. # to 0, which specifies the current event.
  337. #
  338. # Side Effects:
  339. # Changes the history list.
  340.  proc tcl::HistChange {cmd {event 0}} {
  341.     variable history
  342.     set i [HistIndex $event]
  343.     set history($i) $cmd
  344. }