1
2
3
4
5
6
7
8
9
10
|
1
2
3
4
5
6
7
8
9
10
|
-
+
|
#!/usr/locanl/bin/tclsh
# FILE: "/home/joze/src/tclreadline/tclreadlineCompleter.tcl"
# LAST MODIFICATION: "Mon Sep 13 02:21:21 1999 (joze)"
# LAST MODIFICATION: "Tue Sep 14 01:55:17 1999 (joze)"
# (C) 1998, 1999 by Johannes Zellner, <johannes@zellner.org>
# $Id$
# ---
#
# tclreadline -- gnu readline for tcl
# Copyright (C) 1999 Johannes Zellner
#
|
︙ | | |
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
|
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
|
+
+
+
+
-
+
|
}
}
#**
# build a list hosts from the /etc/hosts file.
# this is only done once. This is sort of a
# dirty hack, /etc/hosts is hardcoded ...
# But on the other side, if the user supplies
# a valid host table in tclreadline::hosts
# before entering the event loop, this proc
# will return this list.
#
proc HostList {} {
# read the host table only once.
#
variable hosts
if {![info exists hosts]} {
catch {
set id [open /etc/hosts r]
set hosts ""
set id [open /etc/hosts r]
if {0 != ${id}} {
while {-1 != [gets ${id} line]} {
regsub {#.*} ${line} {} line
if {[llength ${line}] >= 2} {
lappend hosts [lindex ${line} 1]
}
}
|
︙ | | |
203
204
205
206
207
208
209
210
211
212
213
214
215
216
|
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
|
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
|
foreach word $lst {
if {[string match ${text}* ${word}]} {
lappend result ${word}
}
}
return [string trim $result]
}
#**
# invoke cmd with a (hopefully) invalid string and
# parse the error message to get an option list.
#
# @param cmd
# @return list of options for cmd
# @date Sep-14-1999
#
proc TrySubCmds {cmd} {
set trystring ____
set result ""
if [catch {set result [${cmd} ${trystring}]} msg] {
if {[regexp {bad *option.*____.*: *must *be( .*$)} ${msg} all raw]} {
regsub -all -- , ${raw} { } raw
set len [llength ${raw}]
set len_2 [expr ${len} - 2]
for {set i 0} {${i} < ${len}} {incr i} {
set word [lindex ${raw} ${i}]
if {"or" != ${word} && ${i} != ${len_2}} {
lappend result ${word}
}
}
} else {
# check, if it's a blt error msg ...
#
set msglst [split ${msg} \n]
foreach line ${msglst} {
if {[regexp "${cmd}\[ \t\]\+\(\[^ \t\]*\)\[^:\]*$" \
${line} all sub]} {
lappend result [list ${sub}]
}
}
}
}
return ${result}
}
proc FirstNonOption {line} {
set expr_pos 1
foreach word [lrange ${line} 1 end] {; # 0 is the command itself
if {"-" != [string index ${word} 0]} {
break
} else {
|
︙ | | |
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
|
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
|
-
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
|
return [CommandCompletion ${cmd} procs]
}
proc CommandsOnlyCompletion {cmd} {
return [CommandCompletion ${cmd} commands]
}
proc CommandCompletion {cmd {action both} {spc ::} {pre UNDEFINED}} {
proc CommandCompletion {cmd {action both} {spc ::}} {
# get the leading colons in `cmd'.
regexp {^:*} ${cmd} pre
return [CommandCompletionWithPre $cmd $action $spc $pre]
}
proc CommandCompletionWithPre {cmd action spc pre} {
# puts stderr "(CommandCompletion) cmd=|$cmd|"
# puts stderr "(CommandCompletion) action=|$action|"
# puts stderr "(CommandCompletion) spc=|$spc|"
# get the leading colons in `cmd'.
if {"UNDEFINED" == $pre} {
regexp {^:*} ${cmd} pre
}
# puts stderr \npre=|$pre|
set cmd [StripPrefix ${cmd}]
set quali [namespace qualifiers ${cmd}]
if {[string length ${quali}]} {
# puts stderr \nquali=|$quali|
set matches [CommandCompletion \
set matches [CommandCompletionWithPre \
[namespace tail ${cmd}] ${action} ${spc}${quali} ${pre}]
# puts stderr \nmatches1=|$matches|
return $matches
}
set cmd [string trim ${cmd}]*
# puts stderr \ncmd=|$cmd|\n
if {"procs" != ${action}} {
|
︙ | | |
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
|
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
|
-
-
-
+
+
+
-
+
|
set commands ""
}
if {"commands" != ${action}} {
set all_procs [namespace eval $spc [list info procs ${cmd}]]
# puts stderr procs=|$procs|
set procs ""
foreach proc $all_procs {
if {[namespace eval $spc [list namespace origin $command]] == \
[namespace eval $spc [list namespace which $command]]} {
lappend procs $command
if {[namespace eval $spc [list namespace origin $proc]] == \
[namespace eval $spc [list namespace which $proc]]} {
lappend procs $proc
}
}
} else {
set procs ""
}
set matches [namespace eval $spc concat ${commands} ${procs}]
set namespaces [namespace children $spc ${cmd}]
if {![llength ${matches}] && 1 == [llength ${namespaces}]} {
set matches [CommandCompletion {} ${action} ${namespaces} ${pre}]
set matches [CommandCompletionWithPre {} ${action} ${namespaces} ${pre}]
# puts stderr \nmatches=|$matches|
return $matches
}
# make `namespaces' having exactly
# the same number of colons as `cmd'.
#
|
︙ | | |
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
|
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
|
+
+
+
+
|
# [SplitLine] --> {1 " put $b"} == sub
# new_start = [lindex $sub 0] == 1
# new_end = [expr $end - ($start - $new_start)] == 4
# new_part == $part == put
# new_line = [lindex $sub 1] == " put $b"
#
} elseif {"" != [set sub [SplitLine $start $line]]} {
set new_start [lindex $sub 0]
set new_end [expr $end - ($start - $new_start)]
set new_line [lindex $sub 1]
# puts stderr "(SplitLine) $new_start $new_end $new_line"
return [ScriptCompleter $part $new_start $new_end $new_line]
} elseif {0 == [set pos [PartPosition part start end line]]} {
# puts stderr "(PartPosition) $part $start $end $line"
set all [CommandCompletion ${part}]
# puts stderr "(ScriptCompleter) all=$all"
#puts \nmatches=$matches\n
# return [Format $all $part]
return [TryFromList $part $all]
} else {
# try to use $pos further ...
# puts stderr |$line|
#
if {"." == [string index [string trim ${line}] 0]} {
set alias WIDGET
|
︙ | | |
905
906
907
908
909
910
911
912
913
914
915
916
917
918
|
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
|
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
|
error [list error during evaluation of `complete(${cmd})']
}
# puts stderr \nscript_result=|${script_result}|
return ${script_result}
}
# set namespc ""; # no qualifiers for tclreadline_complete_unknown
}
# as we've reached here no valid specific completer
# was found. Check, if it's a proc and return the
# arguments.
#
if {[string length [uplevel [info level] info proc $alias]]} {
set args [uplevel [info level] info args $alias]
set arg [lindex $args [expr $pos - 1]]
if {"" != $arg} {
if {[uplevel [info level] info default $alias $arg junk]} {
return [DisplayHints ?$arg?]
} else {
return [DisplayHints <$arg>]
}
}
}
# Ok, also no proc. Try to do the same as for widgets now:
# try to get at least the first option from an error output.
#
switch -- $pos {
1 {
set cmds [TrySubCmds ${alias}]
if {[llength ${cmds}]} {
return [TryFromList ${part} ${cmds}]
}
}
}
# no specific command completer found.
return ""
}
error "{NOTREACHED (this is probably an error)}"
}
|
︙ | | |
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
|
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
|
-
-
+
+
+
|
switch -- $pos {
1 { return [DisplayHints <script>] }
2 { return [DisplayHints ?varName?] }
}
return ""
}
# proc complete(cd) {text start end line pos mod} {
# }
proc complete(cd) {text start end line pos mod} {
return ""
}
proc complete(clock) {text start end line pos mod} {
set cmd [Lindex $line 1]
switch -- $pos {
1 {
return [CompleteFromList $text {clicks format scan seconds}]
}
|
︙ | | |
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
|
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
|
+
+
+
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
|
names {}
unknown { return [DisplayHints ?command?] }
vcompare -
vsatisfies { return [DisplayHints <version1>] }
}
}
3 {
set versions ""
catch [list set versions [package versions [Lindex $line 2]]]
switch -- $cmd {
forget {}
ifneeded {
if {"" != $versions} {
return [CompleteFromList ${text} $versions]
} else {
ifneeded { return [DisplayHints <version>] }
provide { return [DisplayHints ?version?] }
return [DisplayHints <version>]
}
}
provide {
if {"" != $versions} {
return [CompleteFromList ${text} $versions]
} else {
return [DisplayHints ?version?]
}
}
versions {}
present -
require {
if {"-exact" == [PreviousWord ${start} ${line}]} {
return [CompleteFromList ${mod} [package names]]
} else {
if {"" != $versions} {
return [CompleteFromList ${text} $versions]
} else {
return [DisplayHints ?version?]
return [DisplayHints ?version?]
}
}
}
names {}
unknown {}
vcompare -
vsatisfies { return [DisplayHints <version2>] }
}
|
︙ | | |
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
|
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
|
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
|
}
}
}
}
return ""
}
# --- TCLREADLINE PACKAGE ---
# create a tclreadline namespace inside
# tclreadline and import some commands.
#
namespace eval tclreadline {
catch {
namespace import \
::tclreadline::DisplayHints \
::tclreadline::CompleteFromList \
::tclreadline::Lindex
}
}
proc tclreadline::complete(readline) {text start end line pos mod} {
set cmd [Lindex $line 1]
switch -- $pos {
1 { return [CompleteFromList ${text} {
read initialize write add complete
customcompleter builtincompleter eofchar}]
}
2 {
switch -- $cmd {
read {}
initialize {}
write {}
add { return [DisplayHints <completerLine>] }
completer { return [DisplayHints <line>] }
customcompleter { return [DisplayHints ?scriptCompleter?] }
builtincompleter { return [DisplayHints ?boolean?] }
eofchar { return [DisplayHints ?script?] }
}
}
}
return ""
}
# --- END OF TCLREADLINE PACKAGE ---
proc complete(tell) {text start end line pos mod} {
switch -- $pos {
1 { return [ChannelId ${mod}] }
1 { return [ChannelId ${text}] }
}
return ""
}
proc complete(time) {text start end line pos mod} {
switch -- $pos {
1 { return [DisplayHints <script>] }
|
︙ | | |
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
|
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
|
-
+
-
+
-
-
-
-
-
-
+
+
-
-
-
-
-
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
|
return ""
}
# -------------------------------------
# TK
# -------------------------------------
# generic widget configuration
# GENERIC WIDGET CONFIGURATION
proc TrySubCmds {cmd} {
proc WidgetChildren {pattern} {
set trystring ____
set result ""
if [catch {set result [${cmd} ${trystring}]} msg] {
if {[regexp {bad *option.*____.*: *must *be( .*$)} ${msg} all raw]} {
regsub -all -- , ${raw} { } raw
set len [llength ${raw}]
regsub {^([^\.])} ${pattern} {\.\1} pattern
if {![string length ${pattern}]} {
set len_2 [expr ${len} - 2]
for {set i 0} {${i} < ${len}} {incr i} {
set word [lindex ${raw} ${i}]
if {"or" != ${word} && ${i} != ${len_2}} {
lappend result ${word}
}
}
set pattern .
}
} else {
# check, if it's a blt error msg ...
#
set msglst [split ${msg} \n]
foreach line ${msglst} {
if {[regexp "${cmd}\[ \t\]\+\(\[^ \t\]*\)\[^:\]*$" \
${line} all sub]} {
lappend result [list ${sub}]
}
}
}
}
return ${result}
}
proc WidgetList {pattern} {
regsub {^([^\.])} ${pattern} {\.\1} pattern
if {[winfo exists ${pattern}]} {
return [winfo children ${pattern}]
} else {
regsub {.[^.]*$} $pattern {} pattern
if {[winfo exists ${pattern}]} {
return [winfo children ${pattern}]
} else {
return ""
}
}
}
proc WidgetDescendants {pattern} {
set tree [WidgetChildren ${pattern}]
foreach widget $tree {
append tree " [WidgetDescendants $widget]"
}
return $tree
}
proc complete(WIDGET) {text start end line pos mod} {
set widget [lindex ${line} 0]
set cmd [lindex ${line} 1]
# first we build an option table
#
if {[catch [list set option_table [${widget} configure]] msg]} {
return ""
}
foreach optline ${option_table} {
if {5 != [llength ${optline}]} continue else {
lappend options(switches) [lindex ${optline} 0]
lappend options(value) [lindex ${optline} 4]
}
}
switch -- $pos {
if {1 >= ${pos}} {
set cmds [TrySubCmds ${widget}]
if {[llength ${cmds}]} {
return [TryFromList ${mod} ${cmds}]
}
} elseif {2 <= ${pos} &&
([string match ${cmd}* cget] || \
[string match ${cmd}* configure])} {
set prev [PreviousWord ${start} ${line}]
#puts \nprev=|$prev|
#puts switches=|$options(switches)|
#puts found=[lsearch -exact ${prev} $options(switches)]
if {-1 != [set found [lsearch -exact $options(switches) ${prev}]]} {
if {![llength ${mod}]} {
return [list "[lindex $options(value) ${found}]"]
}
} else {
return [TryFromList ${mod} $options(switches)]
}
}
1 {
set cmds [TrySubCmds ${widget}]
if {[llength ${cmds}]} {
return [TryFromList ${mod} ${cmds}]
}
}
2 {
if {([string match ${cmd}* cget] || \
[string match ${cmd}* configure])
} {
set prev [PreviousWord ${start} ${line}]
#puts \nprev=|$prev|
#puts switches=|$options(switches)|
#puts found=[lsearch -exact ${prev} $options(switches)]
if {-1 != [set found \
[lsearch -exact $options(switches) ${prev}]]
} {
if {![llength ${mod}]} {
return [list "[lindex $options(value) ${found}]"]
}
} else {
return [TryFromList ${mod} $options(switches)]
}
}
}
}
return ""
}
# SPECIFIC TK COMMAND COMPLETERS
proc complete(bell) {text start end line pos mod} {
switch -- $pos {
1 { return [CompleteFromList ${text} -displayof] }
2 {
if {"-displayof" == [PreviousWord ${start} ${line}]} {
return [CompleteFromList ${text} [WidgetDescendants ${text}]]
}
}
}
}
proc complete(winfo) {text start end line pos mod} {
set cmd [lindex ${line} 1]
switch -- $pos {
if {1 >= ${pos}} {
set cmds [TrySubCmds winfo]
if {[llength ${cmds}]} {
return [TryFromList ${mod} ${cmds}]
}
} elseif {2 == ${pos}} {
return [TryFromList ${mod} [WidgetList ${mod}]]
1 {
set cmds [TrySubCmds winfo]
if {[llength ${cmds}]} {
return [TryFromList ${text} ${cmds}]
}
}
2 {
return [TryFromList ${text} [WidgetChildren ${text}]]
}
}
return ""
}
}; # namespace tclreadline
|