00001 # TKE - Advanced Programmer's Editor
00002 # Copyright (C) 2014-2019 Trevor Williams (phase1geo@gmail.com)
00003 #
00004 # This program is free software; you can redistribute it and/or modify
00005 # it under the terms of the GNU General Public License as published by
00006 # the Free Software Foundation; either version 2 of the License, or
00007 # (at your option) any later version.
00008 #
00009 # This program is distributed in the hope that it will be useful,
00010 # but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00012 # GNU General Public License for more details.
00013 #
00014 # You should have received a copy of the GNU General Public License along
00015 # with this program; if not, write to the Free Software Foundation, Inc.,
00016 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
00017
00018 ######################################################################
00019 # Name: launcher.tcl
00020 # Author: Trevor Williams (phase1geo@gmail.com)
00021 # Date: 5/11/2013
00022 # Brief: Namespace for the launcher functionality.
00023 ######################################################################
00024
00025 namespace eval launcher {
00026
00027 variable match_commands {}
00028
00029 array set move_info {}
00030 array set read_commands {}
00031 array set commands {}
00032 array set widgets {}
00033 array set options {
00034 -results 10
00035 }
00036 array set command_names {
00037 name 0
00038 validate_cmd 1
00039 temporary 2
00040 }
00041 array set command_values {
00042 description 0
00043 command 1
00044 auto_register 2
00045 count 3
00046 search_str 4
00047 detail_command 5
00048 }
00049
00050 set launcher_file [file join $::tke_home launcher.dat]
00051
00052 ######################################################################
00053 # Saves command launcher information to the session file.
00054 proc save_session {} {
00055
00056 variable move_info
00057
00058 if {[info exists move_info(save_x)]} {
00059 return [list win_posx $move_info(save_x) win_posy $move_info(save_y)]
00060 } else {
00061 return [list]
00062 }
00063
00064 }
00065
00066 ######################################################################
00067 # Loads session information for command launcher.
00068 proc load_session {data} {
00069
00070 variable move_info
00071
00072 array set opts $data
00073
00074 if {[info exists opts(win_posx)]} {
00075 set move_info(save_x) $opts(win_posx)
00076 set move_info(save_y) $opts(win_posy)
00077 }
00078
00079 }
00080
00081 ######################################################################
00082 # Loads the launcher functionality.
00083 proc load {} {
00084
00085 variable read_commands
00086 variable launcher_file
00087
00088 if {![catch { open $launcher_file r } rc]} {
00089 array set read_commands [read $rc]
00090 close $rc
00091 }
00092
00093 # Add preferences traces
00094 trace variable preferences::prefs(Appearance/CommandLauncherEntryFont) w launcher::handle_entry_font
00095 trace variable preferences::prefs(Appearance/CommandLauncherPreviewFont) w launcher::handle_preview_font
00096 trace variable preferences::prefs(Appearance/CommandLauncherRememberLastPosition) w launcher::handle_last_position
00097
00098 }
00099
00100 ######################################################################
00101 # Writes the launcher information to the launcher file.
00102 proc write {} {
00103
00104 variable commands
00105 variable launcher_file
00106
00107 if {![catch { open $launcher_file w } rc]} {
00108 foreach {name value} [array get commands] {
00109 puts $rc "[list $name] [list $value]"
00110 }
00111 close $rc
00112 }
00113
00114 }
00115
00116 ######################################################################
00117 # Launches the command launcher.
00118 proc launch {{mode ""} {show_detail 0}} {
00119
00120 variable widgets
00121 variable move_info
00122
00123 if {![winfo exists .lwin]} {
00124
00125 set widgets(win) .lwin
00126
00127 # Get information from theme
00128 array set theme [theme::get_category_options launcher 1]
00129
00130 frame $widgets(win) -borderwidth 2 -bg $theme(-bordercolor) \
00131 -padx $theme(-borderwidth) -pady $theme(-borderwidth)
00132
00133 set widgets(entry) [entry $widgets(win).entry -bg $theme(-background) -fg $theme(-foreground) \
00134 -width 50 -highlightthickness 0 -relief flat -insertbackground $theme(-foreground) \
00135 -validate key -validatecommand "launcher::lookup %P {$mode} $show_detail" -invalidcommand {bell}]
00136
00137 if {[lsearch [font names] launcher_entry] == -1} {
00138 font create launcher_entry {*}[preferences::get Appearance/CommandLauncherEntryFont]
00139 }
00140
00141 $widgets(entry) configure -font launcher_entry
00142
00143 set widgets(mf) [ttk::frame $widgets(win).mf]
00144 frame $widgets(mf).spcr -height $theme(-spacerheight) -bg $theme(-spacercolor) -borderwidth 0
00145 set widgets(lf) [ttk::frame $widgets(win).mf.lf]
00146 set widgets(lb) [listbox $widgets(lf).lb -exportselection 0 \
00147 -background $theme(-listbackground) -foreground $theme(-listforeground) \
00148 -selectbackground $theme(-selectbackground) -selectforeground $theme(-selectforeground) \
00149 -height 0 -width 35 -borderwidth 0 -highlightthickness 2 \
00150 -highlightcolor $theme(-listbackground) -highlightbackground $theme(-listbackground) \
00151 -yscrollcommand "utils::set_yscrollbar $widgets(lf).vb" -listvariable launcher::match_commands]
00152 scroller::scroller $widgets(lf).vb -orient vertical \
00153 -background $theme(-listbackground) -foreground $theme(-scrollcolor) \
00154 -thickness $theme(-scrollwidth) -command [list $widgets(lb) yview]
00155
00156 grid rowconfigure $widgets(lf) 0 -weight 1
00157 grid columnconfigure $widgets(lf) 0 -weight 1
00158 grid $widgets(lf).lb -row 0 -column 0 -sticky news
00159 grid $widgets(lf).vb -row 0 -column 1 -sticky ns
00160
00161 # Create a special font for the text widget
00162 set widgets(txt) [text $widgets(win).mf.txt -bd 0 \
00163 -highlightthickness 2 -highlightbackground $theme(-listbackground) \
00164 -highlightcolor $theme(-background) \
00165 -width 60 -height 15 -relief flat -wrap word -state disabled \
00166 -fg $theme(-textforeground) -bg $theme(-textbackground)]
00167
00168 if {[lsearch [font names] launcher_preview] == -1} {
00169 font create launcher_preview {*}[preferences::get Appearance/CommandLauncherPreviewFont]
00170 }
00171
00172 $widgets(txt) configure -font launcher_preview
00173
00174 grid rowconfigure $widgets(mf) 1 -weight 1
00175 grid columnconfigure $widgets(mf) 0 -weight 1
00176 grid $widgets(mf).spcr -row 0 -column 0 -sticky ew
00177 grid $widgets(lf) -row 1 -column 0 -sticky news
00178 grid $widgets(txt) -row 2 -column 0 -sticky news
00179
00180 # Hide the text widget
00181 grid remove $widgets(txt)
00182
00183 pack $widgets(entry) -fill x
00184
00185 # Bind the escape key to exit the window
00186 bind $widgets(win) <Destroy> "launcher::handle_win_destroy"
00187 bind $widgets(win) <ButtonPress-1> "launcher::handle_win_press %X %Y"
00188 bind $widgets(win) <B1-Motion> "launcher::handle_win_motion %X %Y"
00189 bind $widgets(win) <ButtonRelease-1> "launcher::handle_win_release %X %Y"
00190 bind $widgets(entry) <Escape> "destroy $widgets(win)"
00191 bind $widgets(entry) <FocusOut> "destroy $widgets(win)"
00192
00193 # Position the window in the center of the main window
00194 if {[info exists move_info(save_x)]} {
00195 place $widgets(win) -x $move_info(save_x) -y $move_info(save_y)
00196 } else {
00197 place $widgets(win) -relx 0.4 -rely 0.25
00198 }
00199
00200 # Get current focus and grab
00201 ::tk::SetFocusGrab $widgets(win) $widgets(entry)
00202
00203 # If we are running in a mode, display the default results
00204 if {$mode ne ""} {
00205 lookup "" $mode $show_detail
00206 }
00207
00208 }
00209
00210 }
00211
00212 ######################################################################
00213 # Allows the themer to configure our look.
00214 proc configure {w args} {
00215
00216 array set opts {
00217 -background "white"
00218 -foreground "black"
00219 -bordercolor "grey90"
00220 -borderwidth 10
00221 -textbackground "black"
00222 -textforeground "white"
00223 }
00224 array set opts $args
00225
00226 }
00227
00228 ######################################################################
00229 # Called when the launcher window is destroyed.
00230 proc handle_win_destroy {} {
00231
00232 variable widgets
00233
00234 # Reset the original focus and grab
00235 ::tk::RestoreFocusGrab $widgets(win) $widgets(entry)
00236
00237 # Destroy temporary registrations
00238 remove_temporary
00239
00240 }
00241
00242 ######################################################################
00243 # Handles a left mouse press event on the frame.
00244 proc handle_win_press {x y} {
00245
00246 variable move_info
00247
00248 set move_info(last_x) $x
00249 set move_info(last_y) $y
00250
00251 }
00252
00253 ######################################################################
00254 # Handles a left-click motion mouse event on the launcher window border.
00255 proc handle_win_motion {x y} {
00256
00257 variable widgets
00258 variable move_info
00259
00260 if {![info exists move_info(last_x)]} {
00261 return
00262 }
00263
00264 set newx [expr [winfo x $widgets(win)] + ($x - $move_info(last_x))]
00265 set newy [expr [winfo y $widgets(win)] + ($y - $move_info(last_y))]
00266
00267 # If the new coordinates are valid, allow the move
00268 if {($newx > 0) && (($newx + [winfo width $widgets(win)]) < [winfo width .]) && \
00269 ($newy > 0) && (($newy + [winfo height $widgets(win)]) < [winfo height .])} {
00270
00271 place configure $widgets(win) -x $newx -y $newy -relx 0.0 -rely 0.0
00272
00273 set move_info(last_x) $x
00274 set move_info(last_y) $y
00275
00276 } else {
00277
00278 array unset move_info
00279
00280 }
00281
00282 }
00283
00284 ######################################################################
00285 # Handles a mouse left-button release event.
00286 proc handle_win_release {x y} {
00287
00288 variable widgets
00289 variable move_info
00290
00291 array unset move_info
00292
00293 # Save the command launcher position if we are supposed to
00294 if {[preferences::get Appearance/CommandLauncherRememberLastPosition]} {
00295 array set opts [place info $widgets(win)]
00296 set move_info(save_x) $opts(-x)
00297 set move_info(save_y) $opts(-y)
00298 }
00299
00300 }
00301
00302 ######################################################################
00303 # Handles any changes to the entry font size preferences variable.
00304 proc handle_entry_font {name1 name2 op} {
00305
00306 if {[lsearch [font names] launcher_entry] != -1} {
00307 font configure launcher_entry {*}[preferences::get Appearance/CommandLauncherEntryFont]
00308 }
00309
00310 }
00311
00312 ######################################################################
00313 # Handles any changes to the preview font size preferences variable.
00314 proc handle_preview_font {name1 name2 op} {
00315
00316 if {[lsearch [font names] launcher_preview] != -1} {
00317 font configure launcher_preview {*}[preferences::get Appearance/CommandLauncherPreviewFont]
00318 }
00319
00320 }
00321
00322 ######################################################################
00323 # Handles a change to the RememberLastPosition preference value.
00324 proc handle_last_position {name1 name2 op} {
00325
00326 variable move_info
00327
00328 if {[preferences::get Appearance/CommandLauncherRememberLastPosition] == 0} {
00329 catch { unset move_info(save_x) }
00330 catch { unset move_info(save_y) }
00331 }
00332
00333 }
00334
00335 ############################################################################
00336 # Moves the currently selected command up by one row.
00337 proc move_up {} {
00338
00339 variable widgets
00340
00341 set selected [$widgets(lb) curselection]
00342
00343 if {$selected > 0} {
00344 select [expr $selected - 1]
00345 }
00346
00347 }
00348
00349 ############################################################################
00350 # Moves the currently selected command down by one row.
00351 proc move_down {} {
00352
00353 variable widgets
00354
00355 set selected [$widgets(lb) curselection]
00356
00357 if {$selected < [expr [$widgets(lb) size] - 1]} {
00358 select [expr $selected + 1]
00359 }
00360
00361 }
00362
00363 ######################################################################
00364 # Handles mouse motion over the listbox.
00365 proc select_motion {w x y} {
00366
00367 select [$w index @$x,$y]
00368
00369 }
00370
00371 ############################################################################
00372 # Selects the current row within the selection table.
00373 proc select {row} {
00374
00375 variable widgets
00376 variable commands
00377 variable command_values
00378 variable matches
00379
00380 # Set the selection
00381 $widgets(lb) selection clear 0 end
00382 $widgets(lb) selection set $row
00383 $widgets(lb) see $row
00384
00385 # If the text widget is shown, clear it and display the current detail information
00386 if {[lsearch [grid slaves $widgets(mf)] $widgets(txt)] != -1} {
00387 $widgets(txt) configure -state normal
00388 $widgets(txt) delete 1.0 end
00389 if {[set detail_command [lindex $commands([lindex $matches $row]) $command_values(detail_command)]] ne ""} {
00390 uplevel #0 "$detail_command $widgets(txt)"
00391 }
00392 $widgets(txt) configure -state disabled
00393 }
00394
00395 }
00396
00397 ######################################################################
00398 # Adds a new command that is registered for use by the widget.
00399 proc register {name command {detail_command ""} {validate_cmd "launcher::okay"} {auto_register 0}} {
00400
00401 variable commands
00402 variable read_commands
00403 variable command_names
00404 variable command_values
00405
00406 # If the read file has not been read, do it now and bind ourselves
00407 if {[array size read_commands] == 0} {
00408 load
00409 }
00410
00411 # Create default values
00412 set count 0
00413 set search_str ""
00414 set command_name [get_command_name $name $validate_cmd 0]
00415
00416 # Update the commands array
00417 if {[llength [array names commands $command_name]] == 0} {
00418 if {[info exists read_commands($command_name)]} {
00419 set count [lindex $read_commands($command_name) $command_values(count)]
00420 set search_str [lindex $read_commands($command_name) $command_values(search_str)]
00421 }
00422 }
00423
00424 # Create the command list
00425 set command_value [lrepeat [array size command_values] ""]
00426 lset command_value $command_values(description) [string trim $name]
00427 lset command_value $command_values(command) $command
00428 lset command_value $command_values(auto_register) $auto_register
00429 lset command_value $command_values(count) $count
00430 lset command_value $command_values(search_str) $search_str
00431 lset command_value $command_values(detail_command) $detail_command
00432
00433 # Populate the command in the lookup table
00434 set commands($command_name) $command_value
00435
00436 }
00437
00438 ############################################################################
00439 # Adds a new command that is registered for use by the widget but will not
00440 # be saved.
00441 proc register_temp {name command description {order 0x7fffffff} {detail_command ""} {validate_cmd "launcher::okay"}} {
00442
00443 variable commands
00444 variable command_names
00445 variable command_values
00446
00447 # Create the command name list
00448 set command_name [get_command_name $name $validate_cmd 1]
00449
00450 # Create the command value list
00451 set command_value [lrepeat [array size command_values] ""]
00452 lset command_value $command_values(description) [string trim $description]
00453 lset command_value $command_values(command) $command
00454 lset command_value $command_values(auto_register) 0
00455 lset command_value $command_values(count) [expr 0x7fffffff - $order]
00456 lset command_value $command_values(search_str) $name
00457 lset command_value $command_values(detail_command) $detail_command
00458
00459 # Populate the command in the lookup table
00460 set commands($command_name) $command_value
00461
00462 return $command_name
00463
00464 }
00465
00466 ######################################################################
00467 # Unregisters launcher commands that match the given pattern.
00468 proc unregister {name_pattern {command_pattern *} {temp_pattern *}} {
00469
00470 variable commands
00471
00472 array unset commands [get_command_name $name_pattern $command_pattern $temp_pattern]
00473
00474 }
00475
00476 ######################################################################
00477 # Removes all of the temporary registrations.
00478 proc remove_temporary {} {
00479
00480 # Unregister all temporary registrations
00481 unregister * * 1
00482
00483 }
00484
00485 ######################################################################
00486 # Returns the command name given the specified values.
00487 proc get_command_name {name validate_cmd temporary} {
00488
00489 variable command_names
00490
00491 # Create the command name list
00492 set command_name [lrepeat [array size command_names] ""]
00493 lset command_name $command_names(name) [string tolower $name]
00494 lset command_name $command_names(validate_cmd) $validate_cmd
00495 lset command_name $command_names(temporary) $temporary
00496
00497 return $command_name
00498
00499 }
00500
00501 ######################################################################
00502 # Default validate command.
00503 proc okay {} {
00504
00505 return 1
00506
00507 }
00508
00509 ######################################################################
00510 # Validate command for calculations.
00511 proc calc_okay {} {
00512
00513 return 1
00514
00515 }
00516
00517 ######################################################################
00518 # Validate command for symbols.
00519 proc symbol_okay {} {
00520
00521 return 1
00522
00523 }
00524
00525 ######################################################################
00526 # Validate command for markers.
00527 proc marker_okay {} {
00528
00529 return 1
00530
00531 }
00532
00533 ######################################################################
00534 # Validate command for clipboard history.
00535 proc clip_okay {} {
00536
00537 return 1
00538
00539 }
00540
00541 ######################################################################
00542 # Validate command for URL launching.
00543 proc url_okay {} {
00544
00545 return 1
00546
00547 }
00548
00549 ######################################################################
00550 # Validate command for snippet insertion.
00551 proc snip_okay {} {
00552
00553 return 1
00554
00555 }
00556
00557 ######################################################################
00558 # Validate command for sidebar file opening.
00559 proc file_okay {} {
00560
00561 return 1
00562
00563 }
00564
00565 ######################################################################
00566 # Called whenever the user enters a value
00567 proc lookup {value mode show_detail} {
00568
00569 variable widgets
00570 variable commands
00571 variable matches
00572 variable options
00573 variable match_commands
00574 variable command_names
00575 variable command_values
00576
00577 if {($value ne "") || ($mode ne "")} {
00578
00579 # Find all of the matches
00580 find_matches $value $mode show_detail
00581
00582 # Get the number of matches
00583 set match_num [llength $matches]
00584
00585 # Only display results if we have some to display
00586 if {$match_num > 0 } {
00587
00588 # Limit the match list to the top
00589 if {$match_num > $options(-results)} {
00590 $widgets(lb) configure -height $options(-results)
00591 } else {
00592 $widgets(lb) configure -height $match_num
00593 }
00594
00595 # If we need to show detail, display the text widget
00596 if {$show_detail} {
00597 grid $widgets(txt)
00598 } else {
00599 grid remove $widgets(txt)
00600 }
00601
00602 # Update the table
00603 set match_commands [list]
00604 for {set i 0} {$i < $match_num} {incr i} {
00605 lappend match_commands [lindex $commands([lindex $matches $i]) $command_values(description)]
00606 }
00607
00608 # Bind up/down and return keys
00609 bind $widgets(entry) <Up> "launcher::move_up; break"
00610 bind $widgets(entry) <Down> "launcher::move_down; break"
00611 bind $widgets(entry) <Return> "launcher::execute"
00612 bind $widgets(entry) <Escape> "destroy $widgets(win)"
00613 bind $widgets(lb) <Motion> "launcher::select_motion %W %x %y"
00614 bind $widgets(lb) <<ListboxSelect>> "launcher::execute"
00615
00616 # Set tablelist selection to the first entry
00617 select 0
00618
00619 # Pack the listbox, if it isn't already
00620 if {[catch "pack info $widgets(mf)"]} {
00621 pack $widgets(mf) -fill both -expand yes
00622 }
00623
00624 } else {
00625
00626 # Remove the results frame
00627 pack forget $widgets(mf)
00628
00629 # Unbind up and down arrows
00630 bind $widgets(entry) <Up> ""
00631 bind $widgets(entry) <Down> ""
00632 bind $widgets(entry) <Return> "destroy $widgets(win)"
00633 bind $widgets(entry) <Escape> "destroy $widgets(win)"
00634
00635 }
00636
00637 } else {
00638
00639 # Remove the results frame
00640 pack forget $widgets(mf)
00641
00642 # Unbind up and down arrows
00643 bind $widgets(entry) <Up> ""
00644 bind $widgets(entry) <Down> ""
00645 bind $widgets(entry) <Return> "destroy $widgets(win)"
00646 bind $widgets(entry) <Escape> "destroy $widgets(win)"
00647
00648 }
00649
00650 return 1
00651
00652 }
00653
00654 ############################################################################
00655 # Updates the contents of the matches array which contains all of the entries
00656 # that match the given user input.
00657 proc find_matches {str mode pshow_detail} {
00658
00659 upvar $pshow_detail show_detail
00660
00661 variable commands
00662 variable command_names
00663 variable command_values
00664 variable matches
00665 variable curr_states
00666 variable last_url
00667
00668 set matches [list]
00669
00670 if {$mode eq ""} {
00671
00672 switch [string index $str 0] {
00673 "@" {
00674 if {[llength [array names commands [get_command_name * launcher::symbol_okay 1]]] == 0} {
00675 unregister * * 1
00676 set i 0
00677 foreach {procedure pos} [gui::get_symbol_list] {
00678 lappend matches [register_temp "@$procedure" [list gui::jump_to $pos] $procedure $i "" launcher::symbol_okay]
00679 incr i
00680 }
00681 }
00682 }
00683 "," {
00684 if {[llength [array names commands [get_command_name * launcher::marker_okay 1]]] == 0} {
00685 unregister * * 1
00686 set i 0
00687 foreach marker [gui::get_marker_list] {
00688 lassign $marker name txt mname
00689 lappend matches [register_temp ",$marker" [list gui::jump_to_marker $txt $mname] $name $i "" launcher::marker_okay]
00690 incr i
00691 }
00692 }
00693 }
00694 "#" {
00695 if {[llength [array names commands [get_command_name * launcher::clip_okay 1]]] == 0} {
00696 unregister * * 1
00697 set i 0
00698 foreach strs [cliphist::get_history] {
00699 lassign $strs name str
00700 lappend matches [register_temp "#$name" [list cliphist::add_to_clipboard $str] $name $i [list cliphist::add_detail $str] launcher::clip_okay]
00701 incr i
00702 }
00703 set show_detail 1
00704 }
00705 }
00706 ";" {
00707 if {[llength [array names commands [get_command_name * launcher::snip_okay 1]]] == 0} {
00708 unregister * * 1
00709 set i 0
00710 foreach snippet [snippets::get_current_snippets] {
00711 lassign $snippet name value
00712 lappend matches [register_temp ";$name" [list snippets::insert_snippet_into_current $value] $name $i [list snippets::add_detail $value] launcher::snip_okay]
00713 incr i
00714 }
00715 set show_detail 1
00716 }
00717 }
00718 ">" {
00719 if {[llength [array names commands [get_command_name * launcher::file_okay 1]]] == 0} {
00720 unregister * * 1
00721 set i 0
00722 foreach finfo [sidebar::get_shown_files] {
00723 lassign $finfo name row
00724 lappend matches [register_temp ">$name" [list sidebar::open_file $row] $name $i "" launcher::file_okay]
00725 }
00726 }
00727 }
00728 default {
00729 unregister * * 1
00730 if {([string first {\[} $str] == -1) && [handle_calculation $str]} {
00731 # Nothing more to do
00732 } elseif {[regexp {^((https?://)?[a-z0-9\-]+\.[a-z0-9\-\.]+(?:/|(?:/[a-zA-Z0-9!#\$%&'\*\+,\-\.:;=\?@\[\]_~]+)*))$} $str -> url]} {
00733 lappend matches [register_temp "" [list launcher::open_url_and_bookmark $url] "Open URL $url" 0 "" launcher::url_okay]
00734 } elseif {[regexp {^[a-zA-Z][a-zA-Z0-9+.-]*:} $str]} {
00735 lappend matches [register_temp "" [list launcher::open_uri_and_bookmark $str] "Open URI $str" 0 "" launcher::url_okay]
00736 }
00737 }
00738 }
00739
00740 }
00741
00742 # Get the precise match (if one exists)
00743 set results [list]
00744 foreach {name value} [array get commands [get_command_name * * *]] {
00745 if {[lindex $value $command_values(search_str)] eq "$mode$str"} {
00746 if {[eval [lindex $name $command_names(validate_cmd)]]} {
00747 lappend results [list $name $value]
00748 }
00749 }
00750 }
00751
00752 # Sort the results by relevance
00753 sort_match_results $results 1
00754
00755 # Make the string regular expression friendly
00756 set tmpstr [string map {{.} {\.} {*} {\*} {+} {\+} {?} {\?} {\[} {\[}} $str]
00757
00758 if {[string index $tmpstr 0] eq ">"} {
00759 set tmpstr ">.*[string range $tmpstr 1 end]"
00760 }
00761
00762 # Get exact matches that match the beginning of the statement
00763 sort_match_results [get_match_results \{?$mode$tmpstr.*] 0
00764
00765 # Get all of the exact matches within the string
00766 sort_match_results [get_match_results \{?$mode.*$tmpstr.*] 0
00767
00768 # Get all of the fuzzy matches
00769 sort_match_results [get_match_results \{?$mode.*[join [string map {{.} {\\\.} {*} {\\\*} {+} {\\\+} {?} {\\\?} {\[} {\\\[}} [split $str {}]] .*].*] 1
00770
00771 }
00772
00773 ############################################################################
00774 # Searches the list of commands that match the top widget and the given search
00775 # pattern.
00776 proc get_match_results {regex_pattern} {
00777
00778 variable commands
00779 variable command_names
00780 variable command_values
00781 variable matches
00782
00783 set results [list]
00784 set pattern [subst [string map {{(} {\(} {)} {\)}} [get_command_name $regex_pattern .* .*]]]
00785
00786 foreach name [array name commands -regexp $pattern] {
00787 set value $commands($name)
00788 if {[lsearch -exact $matches $name] == -1} {
00789 set validate_cmd [lindex $name $command_names(validate_cmd)]
00790 if {[eval $validate_cmd]} {
00791 if {$validate_cmd ne "launcher::okay"} {
00792 lset value $command_values(count) [expr [lindex $value $command_values(count)] + 1000000]
00793 }
00794 lappend results [list $name $value]
00795 }
00796 }
00797 }
00798
00799 return $results
00800
00801 }
00802
00803 ############################################################################
00804 # Sorts the results by last accessed time and appends the sorted results
00805 # to the matches list.
00806 proc sort_match_results {results type} {
00807
00808 variable command_values
00809 variable matches
00810
00811 # Sort the results by relevance
00812 foreach result [lsort -integer -index [list 1 $command_values(count)] -decreasing $results] {
00813 lappend matches [lindex $result 0]
00814 }
00815
00816 }
00817
00818 ############################################################################
00819 # Executes the selected command, saving usage information.
00820 proc execute {} {
00821
00822 variable widgets
00823 variable matches
00824 variable commands
00825 variable command_values
00826 variable widgets
00827 variable last_command
00828
00829 # Get the current selection
00830 set row [$widgets(lb) curselection]
00831
00832 # Retrieve the command name
00833 set command_name [lindex $matches $row]
00834
00835 # Create the command value
00836 set command_value $commands($command_name)
00837 lset command_value $command_values(count) \
00838 [expr [lindex $command_value $command_values(count)] + 1]
00839 lset command_value $command_values(search_str) [$widgets(entry) get]
00840
00841 # Store the relevance by using the new execution count and the entered search string
00842 set commands($command_name) $command_value
00843 set command [lindex $commands($command_name) $command_values(command)]
00844
00845 # Store the last command and type
00846 set last_command $command_name
00847
00848 # Destroy the widget
00849 destroy $widgets(win)
00850
00851 # Execute the associated command
00852 after 1 [list launcher::execute_helper $command]
00853
00854 }
00855
00856 ############################################################################
00857 # Helper procedure for the execute procedure.
00858 proc execute_helper {command} {
00859
00860 # Execute the command
00861 eval "$command"
00862
00863 # Write the launcher information
00864 bgproc::command launcher_write launcher::write -cancelable 1
00865
00866 }
00867
00868 ############################################################################
00869 # Handles a calculation that is presented on the command-line. The calculation
00870 # can be either a Tcl expression or a Verilog expression.
00871 proc handle_calculation {str} {
00872
00873 variable matches
00874
00875 # Check to see if the string is a valid Tcl expression
00876 if {![catch "expr $str" rc]} {
00877
00878 lappend matches [register_temp "" [list launcher::copy_calculation $rc] "Copy $rc to clipboard" 0 "" launcher::calc_okay]
00879
00880 return 1
00881
00882 }
00883
00884 return 0
00885
00886 }
00887
00888 ############################################################################
00889 # Copies the current calculation to the clipboard.
00890 proc copy_calculation {value} {
00891
00892 variable last_command
00893
00894 # Clear the clipboard and add the calculation
00895 clipboard clear
00896 clipboard append $value
00897
00898 # Add the clipboard content to the clipboard history manager
00899 cliphist::add_from_clipboard
00900
00901 # Clear the last command so that we don't have the calculated value stuck in memory
00902 set last_command ""
00903
00904 }
00905
00906 ######################################################################
00907 # Displays the given URL and bookmarks it.
00908 proc open_url_and_bookmark {url} {
00909
00910 # Open the URL in the local browser
00911 if {[open_url $url] == 0} {
00912
00913 # Add the URL to the bookmark list
00914 register "Open bookmarked URL $url" [list launcher::open_url $url]
00915
00916 }
00917
00918 }
00919
00920 ######################################################################
00921 # Shows the given URL and adds it to the URL history if it does not
00922 # exist.
00923 proc open_url {url} {
00924
00925 # If the URL did not contain the http portion, add it so that the external launcher knows
00926 # this is a URL.
00927 if {[string range $url 0 3] ne "http"} {
00928 set url "http:
00929 }
00930
00931 # Displays the URL in the local browser
00932 return [utils::open_file_externally $url]
00933
00934 }
00935
00936 ######################################################################
00937 # Opens the given URI.
00938 proc open_uri_and_bookmark {uri} {
00939
00940 # Display the URI
00941 if {[open_uri $uri] == 0} {
00942
00943 # Add the URI to the bookmark list
00944 register "Open bookmarked URI $uri" [list launcher::open_uri $uri]
00945
00946 }
00947
00948 }
00949
00950 ######################################################################
00951 # Performs the given URI.
00952 proc open_uri {uri} {
00953
00954 return [utils::open_file_externally $uri]
00955
00956 }
00957
00958 ######################################################################
00959 # Returns the list of files in the TKE home directory to copy.
00960 proc get_share_items {dir} {
00961
00962 return [list launcher.dat]
00963
00964 }
00965
00966 ######################################################################
00967 # Called whenever the share directory changes.
00968 proc share_changed {dir} {
00969
00970 variable launcher_file
00971
00972 set launcher_file [file join $dir launcher.dat]
00973
00974 }
00975
00976 }