home *** CD-ROM | disk | FTP | other *** search
- # jtextvi.tcl - additional procedures for vi-like Text bindings
- #
- # Copyright 1992-1994 by Jay Sekora. All rights reserved, except
- # that this file may be freely redistributed in whole or in part
- # for non-profit, noncommercial use.
- #
- #
- # Essentially, call
- # j:tb:vi_init Text --- for vi-like Text bindings
- # You can check $j_tb(modified,$WIDGET) to see if a text widget has been
- # modified. (Set it to false when you save the text widget.)
-
- # TO DO:
- # ^L
- # sentence-manipulation stuff
- # case change commands, transposition commands
- # commands to do with mark?
- # word deletion - fix to use buffer
- # generalise movement to copying-to-cutbuffer and deletion
- # IMPROVE ENTRY BINDINGS
- # literal-insert for entry
-
- ######################################################################
- # j:tb:vi_init t - set vi bindings up for widget $t (possibly "Text")
- ######################################################################
-
- proc j:tb:vi_init { {t Text} } {
- global j_teb
- set j_teb(cutbuffer) {}
- set j_teb(dragscroll,txnd) 0
- set j_teb(dragscroll,delay) 50
- set j_teb(scanpaste_time) 0
- set j_teb(scanpaste_paste) 1
-
- set j_teb(keymap,$t) vi-command
-
- # in tk4, we need to make sure tkTextBind is called _before_
- # j:tb:key_bind!
- j:tk4 {tkTextBind Enter}
-
- j:tb:key_bind $t
- j:tb:mouse_bind $t
-
-
- j:tkb:mkmap Text vi-command vi-command {
- {Control-slash j:tb:select_all}
- {Control-backslash j:tb:clear_selection}
-
- {Delete j:tkb:vi:left}
- {BackSpace j:tkb:vi:left}
- {space j:tkb:vi:right}
- {minus j:tkb:vi:minus}
- {plus j:tkb:vi:plus}
- {Return j:tkb:vi:plus}
-
- {Up j:tkb:vi:up}
- {Down j:tkb:vi:down}
- {Left j:tkb:vi:left}
- {Right j:tkb:vi:right}
-
- {Control-p j:tkb:vi:up}
- {Control-n j:tkb:vi:down}
-
- {k j:tkb:vi:up}
- {j j:tkb:vi:down}
- {h j:tkb:vi:left}
- {l j:tkb:vi:right}
-
- {Control-k j:tkb:vi:up}
- {Control-j j:tkb:vi:down}
- {Control-h j:tkb:vi:left}
- {Control-l j:tkb:vi:right}
-
- {Control-b j:tkb:scroll_up}
- {Control-f j:tkb:scroll_down}
-
- {x j:tkb:delete_right}
- {X j:tkb:delete_left}
- {b j:tkb:word_left}
- {B j:tkb:word_left}
- {e j:tkb:vi:word_end}
- {w j:tkb:word_right}
- {W j:tkb:word_right}
- {G j:tkb:eof}
-
- {i j:tkb:vi:insert}
- {I j:tkb:vi:Insert}
- {a j:tkb:vi:append}
- {A j:tkb:vi:Append}
- {o j:tkb:vi:open}
- {O j:tkb:vi:Open}
-
- {d j:tkb:new_mode vi-delete}
- {c j:tkb:new_mode vi-change}
-
- {D j:tkb:vi:d-eol}
- {C j:tkb:vi:c-eol}
-
- {Home j:tkb:bol}
- {End j:tkb:eol}
-
- {asciicircum j:tkb:vi:bol}
- {dollar j:tkb:vi:eol}
-
- {Next j:tkb:scroll_down}
- {Prior j:tkb:scroll_up}
-
- {Escape j:tkb:vi:clear_count}
- {Control-bracketleft j:tkb:vi:clear_count}
-
- {1 j:tkb:continue_number}
- {2 j:tkb:continue_number}
- {3 j:tkb:continue_number}
- {4 j:tkb:continue_number}
- {5 j:tkb:continue_number}
- {6 j:tkb:continue_number}
- {7 j:tkb:continue_number}
- {8 j:tkb:continue_number}
- {9 j:tkb:continue_number}
- {0 j:tkb:continue_number}
-
- {Control-DEFAULT j:tb:beep}
- {DEFAULT j:tb:beep}
- {Shift-DEFAULT j:tb:beep}
- }
-
- j:tkb:mkmap Text vi-insert vi-insert {
- {Delete j:tkb:delete_left}
- {BackSpace j:tkb:delete_left}
- {Return j:tkb:insert_newline}
-
- {Control-i j:tkb:self_insert}
- {Control-j j:tkb:self_insert}
- {Control-h j:tkb:delete_left}
-
- {Control-w j:tkb:delete_left_word}
- {Control-u j:tkb:vi:delete_left_line}
-
- {Escape j:tkb:vi:command}
- {Control-bracketleft j:tkb:vi:command}
-
- {Control-v j:tkb:new_mode vi-literal}
-
- {Control-DEFAULT j:tb:beep}
- {DEFAULT j:tkb:self_insert}
- {Shift-DEFAULT j:tkb:self_insert}
- }
-
- j:tkb:mkmap Text vi-literal vi-insert {
- {DEFAULT j:tkb:self_insert}
- {Shift-DEFAULT j:tkb:self_insert}
- {Control-DEFAULT j:tkb:self_insert}
- {Meta-DEFAULT j:tkb:self_insert}
- }
-
- # The following maps are a hideous kludge until generalised command
- # structure can be implemented:
-
- j:tkb:mkmap Text vi-delete vi-command {
- {d j:tkb:vi:dd}
- {w j:tkb:vi:dw}
- {W j:tkb:vi:dw}
- {dollar j:tkb:vi:d-eol}
-
- {DEFAULT j:tb:beep}
- {Shift-DEFAULT j:tb:beep}
- {Control-DEFAULT j:tb:beep}
- {Meta-DEFAULT j:tb:beep}
- }
-
- j:tkb:mkmap Text vi-change vi-command {
- {c j:tkb:vi:cd}
- {w j:tkb:vi:cw}
- {W j:tkb:vi:cw}
- {dollar j:tkb:vi:c-eol}
-
- {DEFAULT j:tb:beep}
- {Shift-DEFAULT j:tb:beep}
- {Control-DEFAULT j:tb:beep}
- {Meta-DEFAULT j:tb:beep}
- }
- }
-
- ######################################################################
-
-
- proc j:tkb:vi:command { W K A } {
- if { ! [j:tb:is_bol $W]} {
- j:tb:move $W {insert - 1 char}
- }
- j:tkb:new_mode vi-command $W $K $A
- }
-
- proc j:tkb:vi:insert { W K A } {
- j:tkb:new_mode vi-insert $W $K $A
- }
-
- ######################################################################
- # based on procedures from Achim Bohnet <ach@rosat.mpe-garching.mpg.de>
- # TO DO: should beep ONCE if repeating would hit edge
-
- proc j:tkb:vi:left { W K A } {
- if [j:tb:is_bol $W] {
- j:beep $W
- } else {
- j:tkb:repeatable {
- if {![j:tb:is_bol $W]} {j:tb:move $W {insert - 1 char}}
- } $W
- }
- }
-
- proc j:tkb:vi:right { W K A } {
- if [j:tb:is_eol $W] {
- j:beep $W
- } else {
- j:tkb:repeatable {
- if {![j:tb:is_eol $W]} {j:tb:move $W {insert + 1 char}}
- } $W
- }
- }
-
- proc j:tkb:vi:up { W K A } {
- if [j:tb:is_first_line $W] {
- j:beep $W
- } else {
- j:tkb:repeatable {
- if {![j:tb:is_first_line $W]} {j:tb:move $W {insert - 1 line}}
- } $W
- }
- }
-
- proc j:tkb:vi:down { W K A } {
- if [j:tb:is_last_line $W] {
- j:beep $W
- } else {
- j:tkb:repeatable {
- if {![j:tb:is_last_line $W]} {j:tb:move $W {insert + 1 line}}
- } $W
- }
- }
-
- proc j:tkb:vi:word_end { W K A } {
- j:tb:move $W {insert + 1 char}
- j:tkb:repeatable {
- while {[$W compare insert != end] &&
- [string match "\[ \t\n\]" [$W get insert]]} {
- j:tb:move $W {insert + 1 char}
- }
- while {[$W compare insert != end] &&
- ![string match "\[ \t\n\]" [$W get insert]]} {
- j:tb:move $W {insert + 1 char}
- }
- j:tb:move $W {insert - 1 char}
- } $W
- }
-
- proc j:tkb:vi:open { W K A } {
- global j_ed
-
- $W mark set insert "insert lineend "
- $W insert insert "\n"
- set j_ed(vi,$W,insert-begin) [$W index insert] ;# NOT YET USED
- j:tkb:vi:insert $W $K $A
- j:text:mark_dirty $W
- }
-
- proc j:tkb:vi:Open { W K A } {
- global j_ed
-
- $W mark set insert "insert linestart"
- $W insert insert "\n"
- $W mark set insert "insert - 1line"
- set j_ed(vi,$W,insert-begin) [$W index insert] ;# NOT YET USED
- j:tkb:vi:insert $W $K $A
- j:text:mark_dirty $W
- }
-
- ######################################################################
-
- # vi beeps on escape:
- proc j:tkb:vi:clear_count { W K A } {
- j:beep $W
- j:tkb:clear_count $W $K $A
- }
-
- # vi bol is first _printing_ character (non-whitespace):
- proc j:tkb:vi:bol { W K A } {
- j:tkb:bol $W $K $A
- while {[string match "\[ \t\]" [$W get insert]]} {
- j:tb:move $W {insert + 1 char}
- }
- }
-
- # vi eol leaves cursor on last character _before_ newline:
- proc j:tkb:vi:eol { W K A } {
- j:tkb:eol $W $K $A
- if { ! [j:tb:is_bol $W]} {
- j:tb:move $W {insert - 1 char}
- }
- }
-
- proc j:tkb:vi:plus { W K A } {
- global j_teb
- j:tkb:vi:down $W $K $A
- j:tkb:vi:bol $W $K $A
- }
-
- proc j:tkb:vi:minus { W K A } {
- global j_teb
- j:tkb:vi:up $W $K $A
- j:tkb:vi:bol $W $K $A
- }
-
- proc j:tkb:vi:append { W K A } {
- global j_teb
- if { ! [j:tb:is_bol $W]} {
- j:tb:move $W {insert + 1 char}
- }
- j:tkb:vi:insert $W $K $A
- }
-
- proc j:tkb:vi:Insert { W K A } {
- global j_teb
- j:tkb:vi:bol $W $K $A
- j:tkb:vi:insert $W $K $A
- }
-
- proc j:tkb:vi:Append { W K A } {
- global j_teb
- j:tkb:eol $W $K $A
- j:tkb:vi:insert $W $K $A
- }
-
- ######################################################################
- # used for Control-u in insert mode:
-
- proc j:tkb:vi:delete_left_line { W K A } {
- if [$W compare {insert linestart} < insert] {
- global j_teb
- set j_teb(modified,$W) 1
-
- j:text:delete $W [$W index {insert linestart}] [$W index insert]
- }
- }
-
- ######################################################################
- # the following are probably temporary kludges; see jbindtext.tcl:
-
- proc j:tkb:vi:dd { W K A } {
- set start [$W index "insert linestart"]
- j:tkb:vi:down $W $K $A ;# repeatable
- set end [$W index "insert linestart"]
- j:text:delete $W $start $end
- }
-
- proc j:tkb:vi:dw { W K A } {
- set start [$W index insert]
- j:tkb:word_right $W $K $A ;# repeatable
- set end [$W index insert]
- j:text:delete $W $start $end
- if { ! [j:tb:is_bol $W]} {
- j:tb:move $W {insert - 1 char}
- }
- }
-
- proc j:tkb:vi:d-eol { W K A } {
- j:text:delete $W [$W index insert] [$W index "insert lineend"]
- j:tkb:clear_count $W $K $A
- if { ! [j:tb:is_bol $W]} {
- j:tb:move $W {insert - 1 char}
- }
- }
-
- proc j:tkb:vi:cc { W K A } {
- j:tkb:vi:dd $W $K $A ;# repeatable
- j:tkb:vi:insert $W $K $A
- }
-
- proc j:tkb:vi:cw { W K A } {
- j:tkb:vi:dw $W $K $A ;# repeatable
- j:tkb:vi:append $W $K $A
- }
-
- proc j:tkb:vi:c-eol { W K A } {
- j:tkb:vi:d-eol $W $K $A ;# repeatable
- j:tkb:vi:append $W $K $A
- }
-
- ######################################################################
- # deprecated alias for backwards-compatibility:
- ######################################################################
-
- proc j:tb:vi_bind { W } {
- j:tb:vi_init $W
- }
-