cmdr
Check-in [16470ccbc4]
Not logged in
Bounty program for improvements to Tcl and certain Tcl packages.
Tcl 2019 Conference, Houston/TX, US, Nov 4-8
Send your abstracts to [email protected]
or submit via the online form by Sep 9.

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Tweaks to the history mgmt: Documented semantics of limits. Nicer output on changes and current. Allow application to overide initial default limits. Ensure saving of initial limits on first use.
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 16470ccbc4540c91efdc06cec9bca1dae2ace20e
User & Date: andreask 2014-04-15 20:45:12
Context
2014-04-15
21:04
Fixed multi-section help setup of the limit command. check-in: abb1eb8115 user: andreask tags: trunk
20:45
Tweaks to the history mgmt: Documented semantics of limits. Nicer output on changes and current. Allow application to overide initial default limits. Ensure saving of initial limits on first use. check-in: 16470ccbc4 user: andreask tags: trunk
19:56
Cross-reference usage of *prefix* in actors. Extended actor base to allow complete clearance of a common block along a chain of actors up to the root. check-in: 576b7640c7 user: andreask tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to history.tcl.

    13     13   # Meta subject {save history} {load history}
    14     14   # Meta require {Tcl 8.5-}
    15     15   # Meta require fileutil
    16     16   # Meta require debug
    17     17   # Meta require debug::caller
    18     18   # @@ Meta End
    19     19   
           20  +# Limits 'n'
           21  +# < 0 | History on.  Keep everything 
           22  +# = 0 | History off. Keep nothing.
           23  +# > 0 | History on.  Keep last n entries.
           24  +
    20     25   # # ## ### ##### ######## ############# #####################
    21     26   ## Requisites
    22     27   
    23     28   package require Tcl 8.5
    24     29   package require fileutil
    25     30   package require debug
    26     31   package require debug::caller
................................................................................
    30     35   
    31     36   namespace eval ::cmdr {
    32     37       namespace export history
    33     38       namespace ensemble create
    34     39   }
    35     40   
    36     41   namespace eval ::cmdr::history {
    37         -    namespace export attach saveto
           42  +    namespace export attach save-to initial-limit
    38     43       namespace ensemble create
    39     44   
    40     45       # Path to the file the history is stored in.
    41     46       # The default value shown below disables history.
    42     47       variable file {}
    43     48   
    44     49       # State information about the history subsystem.
    45     50       variable loaded  0 ; # Boolean: Has the history file been loaded yet ?
    46         -    variable limit   0 ; # What are the limits on commands to be saved ? (0 = unlimited)
           51  +    variable limit  -1 ; # Limits. Default: active, no limits.
    47     52       variable cache  {} ; # In-memory list of the saved commands for easier limit handling.
    48     53   }
    49     54   
    50     55   # Helper ensemble.
    51     56   namespace eval ::cmdr::history::mgr {
    52     57       namespace ensemble create -map {
    53     58   	initialize ::cmdr::history::Init
................................................................................
    59     64   
    60     65   debug define cmdr/history
    61     66   debug level  cmdr/history
    62     67   debug prefix cmdr/history {[debug caller] | }
    63     68   
    64     69   # # ## ### ##### ######## ############# #####################
    65     70   
    66         -proc ::cmdr::history::saveto {path} {
           71  +proc ::cmdr::history::save-to {path} {
    67     72       debug.cmdr/history {}
    68     73       variable file $path
    69     74       return
    70     75   }
           76  +
           77  +proc ::cmdr::history::initial-limit {new} {
           78  +    debug.cmdr/history {}
           79  +    variable limit $new
           80  +    return
           81  +}
    71     82   
    72     83   proc ::cmdr::history::attach {actor} {
    73     84       debug.cmdr/history {}
    74     85       # cmdr shandler to use.
    75     86       # The actor is the officer to extend.
    76     87   
    77     88       # (***) Detect recursive entry through the extend statements
................................................................................
   138    149   	section Introspection
   139    150   	description {
   140    151   	    Limit the size of the history.
   141    152   	    If no limit is specified the current limit is shown.
   142    153   	}
   143    154   	input n {
   144    155   	    The number of commands to limit the history to.
   145         -	    A value <= 0 disables all limits.
   146         -	    Default is unlimited.
          156  +	    For a value > 0 we keep that many commands in the history.
          157  +	    For a value < 0 we keep all commands, i.e. unlimited history.
          158  +	    For a value = 0 we keep nothing, i.e. no history.
   147    159   	} {
   148    160   	    optional
   149         -	    default 0
          161  +	    default -1
   150    162   	    validate integer
   151    163   	}
   152    164       } ::cmdr::history::Limit
   153    165   
   154    166       return
   155    167   }
   156    168   
................................................................................
   176    188   ## Handler invoked by the main framework to save commands
   177    189   ## just before they are run.
   178    190   
   179    191   proc ::cmdr::history::Add {command} {
   180    192       debug.cmdr/history {}
   181    193       Load
   182    194   
          195  +    # Shortcircuit if we are not keeping any history.
          196  +    variable limit
          197  +    if {$limit == 0} return
          198  +
   183    199       # Extend history
   184    200       variable cache
   185    201       lappend  cache $command
   186    202   
   187    203       # And save it, possibly limiting the number of entries.
   188    204       if {[Restrict]} {
   189    205   	SaveAll
................................................................................
   193    209       return
   194    210   }
   195    211   
   196    212   proc ::cmdr::history::Restrict {} {
   197    213       variable limit
   198    214       debug.cmdr/history {limit = $limit}
   199    215   
   200         -    # No limits, nothing to do.
   201         -    if {$limit <= 0} {
          216  +    # There are no limits set, there is nothing to do.
          217  +    if {$limit < 0} {
   202    218   	debug.cmdr/history {/no limit}
   203    219   	return 0
   204    220       }
   205    221   
   206    222       variable cache
   207    223       debug.cmdr/history {cache len = [llength $cache]}
   208    224   
   209    225       set delta [expr {[llength $cache] - $limit}]
   210    226   
   211    227       debug.cmdr/history {delta = $delta}
   212    228   
   213         -    # Amount of history is still under the imposed limit, nothing to do.
          229  +    # The stored amount of history is still under the imposed limit,
          230  +    # so there is nothing to do.
   214    231       if {$delta < 0} {
   215    232   	debug.cmdr/history {Under limit by [expr {- $delta}]}
   216    233   	return 0
   217    234       }
   218    235   
   219         -    # Throw the <delta> oldest entries out
          236  +    # Throw the <delta> oldest entries out. This may be all.
   220    237       set cache [lrange $cache $delta end]
   221    238   
   222    239       debug.cmdr/history {cache len = [llength $cache]}
   223    240       return 1
   224    241   }
   225    242   
   226    243   proc ::cmdr::history::SaveLast {} {
................................................................................
   242    259       variable cache
   243    260       variable file
   244    261   
   245    262       debug.cmdr/history {file      = $file}
   246    263       debug.cmdr/history {limit     = $limit}
   247    264       debug.cmdr/history {cache len = [llength $cache]}
   248    265   
   249         -    if {$limit > 0} {
   250         -	set prefix "#limit=$limit\n"
   251         -    } else {
   252         -	set prefix ""
          266  +    set contents ""
          267  +
          268  +    if {$limit >= 0} {
          269  +	# We need a marker for limited and disabled history.
          270  +	append contents "#limit=$limit\n"
          271  +    }
          272  +
          273  +    if {[llength $cache]} {
          274  +	append contents "[join $cache \n]\n"
   253    275       }
   254    276   
   255         -    debug.cmdr/history {prefix    = ($prefix)}
   256         -
   257         -    fileutil::writeFile $file "$prefix[join $cache \n]\n"
          277  +    fileutil::writeFile $file $contents
   258    278       return
   259    279   }
   260    280   
   261    281   proc ::cmdr::history::Load {} {
   262    282       CheckActive
   263    283   
   264    284       variable loaded
................................................................................
   267    287   
   268    288       variable file
   269    289       variable limit
   270    290       variable cache
   271    291   
   272    292       if {![file exists $file]} {
   273    293   	# Initial memory defaults for cache and limit are good.
          294  +	# Write the latter to external to keep it properly.
          295  +	SaveAll
   274    296   	return
   275    297       }
   276    298   
   277    299       # We have a saved history, pull it in.
   278    300       set lines [split [string trimright [fileutil::cat $file]] \n]
   279    301   
   280    302       # Detect and strip a leading limit clause from the contents.
   281    303       if {[regexp "#limit=(\\d+)\$" [lindex $lines 0] -> plimit]} {
   282         -	set limit $plimit
   283    304   	set lines [lrange $lines 1 end]
          305  +    } else {
          306  +	set plimit -1
   284    307       }
   285    308   
          309  +    set limit $plimit
   286    310       set cache $lines
          311  +    # Apply the limit clause if the user tried to circumvent it by
          312  +    # manually extending the history. Any changes we had to make are
          313  +    # saved back.
          314  +    if {[Restrict]} SaveAll
   287    315       return
   288    316   }
   289    317   
   290    318   proc ::cmdr::history::CheckActive {} {
   291    319       variable file
   292    320       if {$file ne {}} return
   293    321   
................................................................................
   344    372       debug.cmdr/history {}
   345    373       Load
   346    374   
   347    375       variable limit
   348    376   
   349    377       if {![$config @n set?]} {
   350    378   	# Show current limit
   351         -	puts $limit
          379  +	puts [Describe]
   352    380   	return
   353    381       }
   354    382   
   355    383       # Retrieve the new limit, apply it to the in-memory history, and
   356    384       # at last refresh the external state.
   357    385       debug.cmdr/history {current = $limit}
   358    386       set new [$config @n]
   359         -    if {$new < 0 } { set new 0 }
          387  +    if {$new < 0 } {
          388  +	set new -1
          389  +    }
   360    390   
   361    391       debug.cmdr/history {new     = $new}
   362    392   
   363    393       if {$new == $limit} {
   364    394   	puts {No change}
   365    395   	return
   366    396       }
   367    397   
   368    398       set limit $new
   369    399       Restrict
   370    400       SaveAll
   371    401   
   372         -    puts "Changed limit to $new"
          402  +    puts "Changed limit to: [Describe]"
   373    403       return
   374    404   }
          405  +
          406  +proc ::cmdr::history::Describe {} {
          407  +    variable limit
          408  +    if {$limit < 0} {
          409  +	return "Keep an unlimited history"
          410  +    } elseif {$limit == 0} {
          411  +	return "Keep no history (off)"
          412  +    } elseif {$limit == 1} {
          413  +	return "Keep one entry"
          414  +    } else {
          415  +	return "Keep $limit entries"
          416  +    }
          417  +}
   375    418   
   376    419   # # ## ### ##### ######## ############# #####################
   377    420   ## Ready
   378    421   package provide cmdr::history 0
   379    422   return