2 # Tcl ignores the next line -*- tcl -*- \
5 # Copyright (C) 2006 Shawn Pearce, Paul Mackerras. All rights reserved.
6 # This program is free software; it may be used, copied, modified
7 # and distributed under the terms of the GNU General Public Licence,
8 # either version 2, or (at your option) any later version.
10 set appname
[lindex
[file split $argv0] end
]
13 ######################################################################
17 proc load_repo_config
{} {
19 global cfg_trust_mtime
21 array
unset repo_config
23 set fd_rc
[open
"| git repo-config --list" r
]
24 while {[gets
$fd_rc line
] >= 0} {
25 if {[regexp
{^
([^
=]+)=(.
*)$
} $line line name value
]} {
26 lappend repo_config
($name) $value
32 if {[catch
{set cfg_trust_mtime \
33 [lindex
$repo_config(gui.trustmtime
) 0]
35 set cfg_trust_mtime false
39 proc save_my_config
{} {
41 global cfg_trust_mtime
44 if {[catch
{set rc_trustMTime
$repo_config(gui.trustmtime
)}]} {
45 set rc_trustMTime
[list false
]
47 if {$cfg_trust_mtime != [lindex
$rc_trustMTime 0]} {
48 exec git repo-config gui.trustMTime
$cfg_trust_mtime
49 set repo_config
(gui.trustmtime
) [list
$cfg_trust_mtime]
52 if {[catch
{set rc_fontdiff
$repo_config(gui.fontdiff
)}]} {
53 set rc_fontdiff
[list
{Courier
10}]
55 if {$font_diff != [lindex
$rc_fontdiff 0]} {
56 exec git repo-config
--global gui.fontDiff
$font_diff
57 set repo_config
(gui.fontdiff
) [list
$font_diff]
60 set cfg_geometry
[wm geometry .
]
61 append cfg_geometry
" [lindex [.vpane sash coord 0] 1]"
62 append cfg_geometry
" [lindex [.vpane.files sash coord 0] 0]"
63 if {[catch
{set rc_geometry
$repo_config(gui.geometry
)}]} {
64 set rc_geometry
[list
[list
]]
66 if {$cfg_geometry != [lindex
$rc_geometry 0]} {
67 exec git repo-config gui.geometry
$cfg_geometry
68 set repo_config
(gui.geometry
) [list
$cfg_geometry]
72 proc error_popup
{msg
} {
78 append title
[lindex \
79 [file split [file normalize
[file dirname $gitdir]]] \
87 -title "$title: error" \
91 ######################################################################
95 if { [catch
{set cdup
[exec git rev-parse
--show-cdup]} err
]
96 ||
[catch
{set gitdir
[exec git rev-parse
--git-dir]} err
]} {
98 error_popup
"Cannot find the git directory:\n\n$err"
106 if {$appname == {git-citool
}} {
112 ######################################################################
121 set update_index_fd
{}
123 set disable_on_lock
[list
]
124 set index_lock_type none
130 proc lock_index
{type} {
131 global index_lock_type disable_on_lock
133 if {$index_lock_type == {none
}} {
134 set index_lock_type
$type
135 foreach w
$disable_on_lock {
136 uplevel
#0 $w disabled
139 } elseif
{$index_lock_type == {begin-update
} && $type == {update
}} {
140 set index_lock_type
$type
146 proc unlock_index
{} {
147 global index_lock_type disable_on_lock
149 set index_lock_type none
150 foreach w
$disable_on_lock {
155 ######################################################################
159 proc repository_state
{hdvar ctvar
} {
161 upvar
$hdvar hd
$ctvar ct
163 if {[catch
{set hd
[exec git rev-parse
--verify HEAD
]}]} {
165 } elseif
{[file exists
[file join $gitdir MERGE_HEAD
]]} {
172 proc update_status
{{final Ready.
}} {
173 global HEAD PARENT commit_type
174 global ui_index ui_other ui_status_value ui_comm
175 global status_active file_states
176 global cfg_trust_mtime
178 if {$status_active ||
![lock_index
read]} return
180 repository_state new_HEAD new_type
181 if {$commit_type == {amend
}
182 && $new_type == {normal
}
183 && $new_HEAD == $HEAD} {
187 set commit_type
$new_type
190 array
unset file_states
192 if {![$ui_comm edit modified
]
193 ||
[string trim
[$ui_comm get
0.0 end
]] == {}} {
194 if {[load_message GITGUI_MSG
]} {
195 } elseif
{[load_message MERGE_MSG
]} {
196 } elseif
{[load_message SQUASH_MSG
]} {
198 $ui_comm edit modified false
202 if {$cfg_trust_mtime == {true
}} {
203 update_status_stage2
{} $final
206 set ui_status_value
{Refreshing
file status...
}
207 set fd_rf
[open
"| git update-index -q --unmerged --refresh" r
]
208 fconfigure
$fd_rf -blocking 0 -translation binary
209 fileevent
$fd_rf readable \
210 [list update_status_stage2
$fd_rf $final]
214 proc update_status_stage2
{fd final
} {
215 global gitdir PARENT commit_type
216 global ui_index ui_other ui_status_value ui_comm
218 global buf_rdi buf_rdf buf_rlo
222 if {![eof
$fd]} return
226 set ls_others
[list | git ls-files
--others -z \
227 --exclude-per-directory=.gitignore
]
228 set info_exclude
[file join $gitdir info exclude
]
229 if {[file readable
$info_exclude]} {
230 lappend ls_others
"--exclude-from=$info_exclude"
238 set ui_status_value
{Scanning
for modified files ...
}
239 set fd_di
[open
"| git diff-index --cached -z $PARENT" r
]
240 set fd_df
[open
"| git diff-files -z" r
]
241 set fd_lo
[open
$ls_others r
]
243 fconfigure
$fd_di -blocking 0 -translation binary
244 fconfigure
$fd_df -blocking 0 -translation binary
245 fconfigure
$fd_lo -blocking 0 -translation binary
246 fileevent
$fd_di readable
[list read_diff_index
$fd_di $final]
247 fileevent
$fd_df readable
[list read_diff_files
$fd_df $final]
248 fileevent
$fd_lo readable
[list read_ls_others
$fd_lo $final]
251 proc load_message
{file} {
252 global gitdir ui_comm
254 set f
[file join $gitdir $file]
255 if {[file isfile
$f]} {
256 if {[catch
{set fd
[open
$f r
]}]} {
259 set content
[string trim
[read $fd]]
261 $ui_comm delete
0.0 end
262 $ui_comm insert end
$content
268 proc read_diff_index
{fd final
} {
271 append buf_rdi
[read $fd]
273 set n
[string length
$buf_rdi]
275 set z1
[string first
"\0" $buf_rdi $c]
278 set z2
[string first
"\0" $buf_rdi $z1]
284 [string range
$buf_rdi $z1 $z2] \
285 [string index
$buf_rdi [expr $z1 - 2]]_
289 set buf_rdi
[string range
$buf_rdi $c end
]
294 status_eof
$fd buf_rdi
$final
297 proc read_diff_files
{fd final
} {
300 append buf_rdf
[read $fd]
302 set n
[string length
$buf_rdf]
304 set z1
[string first
"\0" $buf_rdf $c]
307 set z2
[string first
"\0" $buf_rdf $z1]
313 [string range
$buf_rdf $z1 $z2] \
314 _
[string index
$buf_rdf [expr $z1 - 2]]
318 set buf_rdf
[string range
$buf_rdf $c end
]
323 status_eof
$fd buf_rdf
$final
326 proc read_ls_others
{fd final
} {
329 append buf_rlo
[read $fd]
330 set pck
[split $buf_rlo "\0"]
331 set buf_rlo
[lindex
$pck end
]
332 foreach p
[lrange
$pck 0 end-1
] {
335 status_eof
$fd buf_rlo
$final
338 proc status_eof
{fd buf final
} {
339 global status_active ui_status_value
346 if {[incr status_active
-1] == 0} {
350 set ui_status_value
$final
355 ######################################################################
360 global ui_diff ui_fname_value ui_fstatus_value ui_index ui_other
362 $ui_diff conf
-state normal
363 $ui_diff delete
0.0 end
364 $ui_diff conf
-state disabled
366 set ui_fname_value
{}
367 set ui_fstatus_value
{}
369 $ui_index tag remove in_diff
0.0 end
370 $ui_other tag remove in_diff
0.0 end
373 proc reshow_diff
{} {
374 global ui_fname_value ui_status_value file_states
376 if {$ui_fname_value == {}
377 ||
[catch
{set s
$file_states($ui_fname_value)}]} {
380 show_diff
$ui_fname_value
384 proc show_diff
{path
{w
{}} {lno
{}}} {
385 global file_states file_lists
386 global PARENT diff_3way diff_active
387 global ui_diff ui_fname_value ui_fstatus_value ui_status_value
389 if {$diff_active ||
![lock_index
read]} return
392 if {$w == {} ||
$lno == {}} {
393 foreach w
[array names file_lists
] {
394 set lno
[lsearch
-sorted $file_lists($w) $path]
401 if {$w != {} && $lno >= 1} {
402 $w tag add in_diff
$lno.0 [expr $lno + 1].0
405 set s
$file_states($path)
409 set ui_fname_value
[escape_path
$path]
410 set ui_fstatus_value
[mapdesc
$m $path]
411 set ui_status_value
"Loading diff of [escape_path $path]..."
413 set cmd
[list | git diff-index
-p $PARENT -- $path]
416 set cmd
[list | git diff-index
-p -c $PARENT $path]
420 set fd
[open
$path r
]
421 set content
[read $fd]
426 set ui_status_value
"Unable to display [escape_path $path]"
427 error_popup
"Error loading file:\n\n$err"
430 $ui_diff conf
-state normal
431 $ui_diff insert end
$content
432 $ui_diff conf
-state disabled
435 set ui_status_value
{Ready.
}
440 if {[catch
{set fd
[open
$cmd r
]} err
]} {
443 set ui_status_value
"Unable to display [escape_path $path]"
444 error_popup
"Error loading diff:\n\n$err"
448 fconfigure
$fd -blocking 0 -translation auto
449 fileevent
$fd readable
[list read_diff
$fd]
452 proc read_diff
{fd
} {
453 global ui_diff ui_status_value diff_3way diff_active
455 while {[gets
$fd line
] >= 0} {
456 if {[string match
{diff --git *} $line]} continue
457 if {[string match
{diff --combined *} $line]} continue
458 if {[string match
{--- *} $line]} continue
459 if {[string match
{+++ *} $line]} continue
460 if {[string match index
* $line]} {
461 if {[string first
, $line] >= 0} {
466 $ui_diff conf
-state normal
468 set x
[string index
$line 0]
473 default
{set tags
{}}
476 set x
[string range
$line 0 1]
478 default
{set tags
{}}
480 "++" {set tags dp
; set x
" +"}
481 " +" {set tags
{di bold
}; set x
"++"}
482 "+ " {set tags dni
; set x
"-+"}
483 "--" {set tags dm
; set x
" -"}
484 " -" {set tags
{dm bold
}; set x
"--"}
485 "- " {set tags di
; set x
"+-"}
486 default
{set tags
{}}
488 set line
[string replace
$line 0 1 $x]
490 $ui_diff insert end
$line $tags
491 $ui_diff insert end
"\n"
492 $ui_diff conf
-state disabled
499 set ui_status_value
{Ready.
}
503 ######################################################################
507 proc load_last_commit
{} {
508 global HEAD PARENT commit_type ui_comm
510 if {$commit_type == {amend
}} return
511 if {$commit_type != {normal
}} {
512 error_popup
"Can't amend a $commit_type commit."
520 set fd
[open
"| git cat-file commit $HEAD" r
]
521 while {[gets
$fd line
] > 0} {
522 if {[string match
{parent
*} $line]} {
523 set parent
[string range
$line 7 end
]
527 set msg
[string trim
[read $fd]]
530 error_popup
"Error loading commit data for amend:\n\n$err"
534 if {$parent_count == 0} {
535 set commit_type amend
539 } elseif
{$parent_count == 1} {
540 set commit_type amend
542 $ui_comm delete
0.0 end
543 $ui_comm insert end
$msg
544 $ui_comm edit modified false
548 error_popup
{You can
't amend a merge commit.}
553 proc commit_tree {} {
554 global tcl_platform HEAD gitdir commit_type file_states
555 global commit_active ui_status_value
558 if {$commit_active || ![lock_index update]} return
560 # -- Our in memory state should match the repository.
562 repository_state curHEAD cur_type
563 if {$commit_type == {amend}
564 && $cur_type == {normal}
565 && $curHEAD == $HEAD} {
566 } elseif {$commit_type != $cur_type || $HEAD != $curHEAD} {
567 error_popup {Last scanned state does not match repository state.
569 Its highly likely that another Git program modified the
570 repository since our last scan. A rescan is required
578 # -- At least one file should differ in the index.
581 foreach path [array names file_states] {
582 set s $file_states($path)
583 switch -glob -- [lindex $s 0] {
587 M? {set files_ready 1; break}
589 error_popup "Unmerged files cannot be committed.
591 File [escape_path $path] has merge conflicts.
592 You must resolve them and include the file before committing.
598 error_popup "Unknown file state [lindex $s 0] detected.
600 File [escape_path $path] cannot be committed by this program.
606 error_popup {No included files to commit.
608 You must include at least 1 file before you can commit.
614 # -- A message is required.
616 set msg [string trim [$ui_comm get 1.0 end]]
618 error_popup {Please supply a commit message.
620 A good commit message has the following format:
622 - First line: Describe in one sentance what you did.
624 - Remaining lines: Describe why this change is good.
630 # -- Ask the pre-commit hook for the go-ahead.
632 set pchook [file join $gitdir hooks pre-commit]
633 if {$tcl_platform(platform) == {windows} && [file isfile $pchook]} {
634 set pchook [list sh -c \
635 "if test -x \"$pchook\"; then exec \"$pchook\"; fi"]
636 } elseif {[file executable $pchook]} {
637 set pchook [list $pchook]
641 if {$pchook != {} && [catch {eval exec $pchook} err]} {
642 hook_failed_popup pre-commit $err
647 # -- Write the tree in the background.
650 set ui_status_value {Committing changes...}
652 set fd_wt [open "| git write-tree" r]
653 fileevent $fd_wt readable [list commit_stage2 $fd_wt $curHEAD $msg]
656 proc commit_stage2 {fd_wt curHEAD msg} {
657 global single_commit gitdir HEAD PARENT commit_type
658 global commit_active ui_status_value ui_comm
662 if {$tree_id == {} || [catch {close $fd_wt} err]} {
663 error_popup "write-tree failed:\n\n$err"
665 set ui_status_value {Commit failed.}
670 # -- Create the commit.
672 set cmd [list git commit-tree $tree_id]
674 lappend cmd -p $PARENT
676 if {$commit_type == {merge}} {
678 set fd_mh [open [file join $gitdir MERGE_HEAD] r]
679 while {[gets $fd_mh merge_head] >= 0} {
680 lappend cmd -p $merge_head
684 error_popup "Loading MERGE_HEAD failed:\n\n$err"
686 set ui_status_value {Commit failed.}
692 # git commit-tree writes to stderr during initial commit.
693 lappend cmd 2>/dev/null
696 if {[catch {set cmt_id [eval exec $cmd]} err]} {
697 error_popup "commit-tree failed:\n\n$err"
699 set ui_status_value {Commit failed.}
704 # -- Update the HEAD ref.
707 if {$commit_type != {normal}} {
708 append reflogm " ($commit_type)"
710 set i [string first "\n" $msg]
712 append reflogm {: } [string range $msg 0 [expr $i - 1]]
714 append reflogm {: } $msg
716 set cmd [list git update-ref -m $reflogm HEAD $cmt_id $curHEAD]
717 if {[catch {eval exec $cmd} err]} {
718 error_popup "update-ref failed:\n\n$err"
720 set ui_status_value {Commit failed.}
725 # -- Cleanup after ourselves.
727 catch {file delete [file join $gitdir MERGE_HEAD]}
728 catch {file delete [file join $gitdir MERGE_MSG]}
729 catch {file delete [file join $gitdir SQUASH_MSG]}
730 catch {file delete [file join $gitdir GITGUI_MSG]}
732 # -- Let rerere do its thing.
734 if {[file isdirectory [file join $gitdir rr-cache]]} {
735 catch {exec git rerere}
738 $ui_comm delete 0.0 end
739 $ui_comm edit modified false
742 if {$single_commit} do_quit
744 # -- Update status without invoking any git commands.
747 set commit_type normal
751 foreach path [array names file_states] {
752 set s $file_states($path)
757 D? {set m _[string index $m 1]}
761 unset file_states($path)
763 lset file_states($path) 0 $m
770 set ui_status_value \
771 "Changes committed as [string range $cmt_id 0 7]."
774 ######################################################################
778 proc fetch_from {remote} {
779 set w [new_console "fetch $remote" \
780 "Fetching new changes from $remote"]
781 set cmd [list git fetch]
786 proc pull_remote {remote branch} {
787 global HEAD commit_type
790 if {![lock_index update]} return
792 # -- Our in memory state should match the repository.
794 repository_state curHEAD cur_type
795 if {$commit_type != $cur_type || $HEAD != $curHEAD} {
796 error_popup {Last scanned state does not match repository state.
798 Its highly likely that another Git program modified the
799 repository since our last scan. A rescan is required
800 before a pull can be started.
807 # -- No differences should exist before a pull.
809 if {[array size file_states] != 0} {
810 error_popup {Uncommitted but modified files are present.
812 You should not perform a pull with unmodified files in your working
813 directory as Git would be unable to recover from an incorrect merge.
815 Commit or throw away all changes before starting a pull operation.
821 set w [new_console "pull $remote $branch" \
822 "Pulling new changes from branch $branch in $remote"]
823 set cmd [list git pull]
826 console_exec $w $cmd [list post_pull_remote $remote $branch]
829 proc post_pull_remote {remote branch success} {
830 global HEAD PARENT commit_type
831 global ui_status_value
835 repository_state HEAD commit_type
837 set $ui_status_value {Ready.}
840 "Conflicts detected while pulling $branch from $remote."
844 proc push_to {remote} {
845 set w [new_console "push $remote" \
846 "Pushing changes to $remote"]
847 set cmd [list git push]
852 ######################################################################
856 proc mapcol {state path} {
857 global all_cols ui_other
859 if {[catch {set r $all_cols($state)}]} {
860 puts "error: no column for state={$state} $path"
866 proc mapicon {state path} {
869 if {[catch {set r $all_icons($state)}]} {
870 puts "error: no icon for state={$state} $path"
876 proc mapdesc {state path} {
879 if {[catch {set r $all_descs($state)}]} {
880 puts "error: no desc for state={$state} $path"
886 proc escape_path {path} {
887 regsub -all "\n" $path "\\n" path
893 proc merge_state {path new_state} {
894 global file_states next_icon_id
896 set s0 [string index $new_state 0]
897 set s1 [string index $new_state 1]
899 if {[catch {set info $file_states($path)}]} {
901 set icon n[incr next_icon_id]
903 set state [lindex $info 0]
904 set icon [lindex $info 1]
908 set s0 [string index $state 0]
909 } elseif {$s0 == {*}} {
914 set s1 [string index $state 1]
915 } elseif {$s1 == {*}} {
919 set file_states($path) [list $s0$s1 $icon]
923 proc display_file {path state} {
924 global ui_index ui_other
925 global file_states file_lists status_active
927 set old_m [merge_state $path $state]
928 if {$status_active} return
930 set s $file_states($path)
931 set new_m [lindex $s 0]
932 set new_w [mapcol $new_m $path]
933 set old_w [mapcol $old_m $path]
934 set new_icon [mapicon $new_m $path]
936 if {$new_w != $old_w} {
937 set lno [lsearch -sorted $file_lists($old_w) $path]
940 $old_w conf -state normal
941 $old_w delete $lno.0 [expr $lno + 1].0
942 $old_w conf -state disabled
945 lappend file_lists($new_w) $path
946 set file_lists($new_w) [lsort $file_lists($new_w)]
947 set lno [lsearch -sorted $file_lists($new_w) $path]
949 $new_w conf -state normal
950 $new_w image create $lno.0 \
951 -align center -padx 5 -pady 1 \
952 -name [lindex $s 1] \
954 $new_w insert $lno.1 "[escape_path $path]\n"
955 $new_w conf -state disabled
956 } elseif {$new_icon != [mapicon $old_m $path]} {
957 $new_w conf -state normal
958 $new_w image conf [lindex $s 1] -image $new_icon
959 $new_w conf -state disabled
963 proc display_all_files {} {
964 global ui_index ui_other file_states file_lists
966 $ui_index conf -state normal
967 $ui_other conf -state normal
969 $ui_index delete 0.0 end
970 $ui_other delete 0.0 end
972 set file_lists($ui_index) [list]
973 set file_lists($ui_other) [list]
975 foreach path [lsort [array names file_states]] {
976 set s $file_states($path)
978 set w [mapcol $m $path]
979 lappend file_lists($w) $path
980 $w image create end \
981 -align center -padx 5 -pady 1 \
982 -name [lindex $s 1] \
983 -image [mapicon $m $path]
984 $w insert end "[escape_path $path]\n"
987 $ui_index conf -state disabled
988 $ui_other conf -state disabled
991 proc with_update_index {body} {
992 global update_index_fd
994 if {$update_index_fd == {}} {
995 if {![lock_index update]} return
996 set update_index_fd [open \
997 "| git update-index --add --remove -z --stdin" \
999 fconfigure $update_index_fd -translation binary
1001 close $update_index_fd
1002 set update_index_fd {}
1009 proc update_index {path} {
1010 global update_index_fd
1012 if {$update_index_fd == {}} {
1013 error {not in with_update_index}
1015 puts -nonewline $update_index_fd "$path\0"
1019 proc toggle_mode {path} {
1020 global file_states ui_fname_value
1022 set s $file_states($path)
1035 with_update_index {update_index $path}
1036 display_file $path $new
1037 if {$ui_fname_value == $path} {
1042 ######################################################################
1044 ## remote management
1046 proc load_all_remotes {} {
1047 global gitdir all_remotes repo_config
1049 set all_remotes [list]
1050 set rm_dir [file join $gitdir remotes]
1051 if {[file isdirectory $rm_dir]} {
1052 set all_remotes [concat $all_remotes [glob \
1056 -directory $rm_dir *]]
1059 foreach line [array names repo_config remote.*.url] {
1060 if {[regexp ^remote\.(.*)\.url\$ $line line name]} {
1061 lappend all_remotes $name
1065 set all_remotes [lsort -unique $all_remotes]
1068 proc populate_remote_menu {m pfx op} {
1069 global all_remotes font_ui
1071 foreach remote $all_remotes {
1072 $m add command -label "$pfx $remote..." \
1073 -command [list $op $remote] \
1078 proc populate_pull_menu {m} {
1079 global gitdir repo_config all_remotes font_ui disable_on_lock
1081 foreach remote $all_remotes {
1083 if {[array get repo_config remote.$remote.url] != {}} {
1084 if {[array get repo_config remote.$remote.fetch] != {}} {
1085 regexp {^([^:]+):} \
1086 [lindex $repo_config(remote.$remote.fetch) 0] \
1091 set fd [open [file join $gitdir remotes $remote] r]
1092 while {[gets $fd line] >= 0} {
1093 if {[regexp {^Pull:[ \t]*([^:]+):} $line line rb]} {
1102 regsub ^refs/heads/ $rb {} rb_short
1103 if {$rb_short != {}} {
1105 -label "Branch $rb_short from $remote..." \
1106 -command [list pull_remote $remote $rb] \
1108 lappend disable_on_lock \
1109 [list $m entryconf [$m index last] -state]
1114 ######################################################################
1119 #define mask_width 14
1120 #define mask_height 15
1121 static unsigned char mask_bits[] = {
1122 0xfe, 0x1f, 0xfe, 0x1f, 0xfe, 0x1f, 0xfe, 0x1f, 0xfe, 0x1f, 0xfe, 0x1f,
1123 0xfe, 0x1f, 0xfe, 0x1f, 0xfe, 0x1f, 0xfe, 0x1f, 0xfe, 0x1f, 0xfe, 0x1f,
1124 0xfe, 0x1f, 0xfe, 0x1f, 0xfe, 0x1f};
1127 image create bitmap file_plain -background white -foreground black -data {
1128 #define plain_width 14
1129 #define plain_height 15
1130 static unsigned char plain_bits[] = {
1131 0xfe, 0x01, 0x02, 0x03, 0x02, 0x05, 0x02, 0x09, 0x02, 0x1f, 0x02, 0x10,
1132 0x02, 0x10, 0x02, 0x10, 0x02, 0x10, 0x02, 0x10, 0x02, 0x10, 0x02, 0x10,
1133 0x02, 0x10, 0x02, 0x10, 0xfe, 0x1f};
1134 } -maskdata $filemask
1136 image create bitmap file_mod -background white -foreground blue -data {
1137 #define mod_width 14
1138 #define mod_height 15
1139 static unsigned char mod_bits[] = {
1140 0xfe, 0x01, 0x02, 0x03, 0x7a, 0x05, 0x02, 0x09, 0x7a, 0x1f, 0x02, 0x10,
1141 0xfa, 0x17, 0x02, 0x10, 0xfa, 0x17, 0x02, 0x10, 0xfa, 0x17, 0x02, 0x10,
1142 0xfa, 0x17, 0x02, 0x10, 0xfe, 0x1f};
1143 } -maskdata $filemask
1145 image create bitmap file_fulltick -background white -foreground "#007000" -data {
1146 #define file_fulltick_width 14
1147 #define file_fulltick_height 15
1148 static unsigned char file_fulltick_bits[] = {
1149 0xfe, 0x01, 0x02, 0x1a, 0x02, 0x0c, 0x02, 0x0c, 0x02, 0x16, 0x02, 0x16,
1150 0x02, 0x13, 0x00, 0x13, 0x86, 0x11, 0x8c, 0x11, 0xd8, 0x10, 0xf2, 0x10,
1151 0x62, 0x10, 0x02, 0x10, 0xfe, 0x1f};
1152 } -maskdata $filemask
1154 image create bitmap file_parttick -background white -foreground "#005050" -data {
1155 #define parttick_width 14
1156 #define parttick_height 15
1157 static unsigned char parttick_bits[] = {
1158 0xfe, 0x01, 0x02, 0x03, 0x7a, 0x05, 0x02, 0x09, 0x7a, 0x1f, 0x02, 0x10,
1159 0x7a, 0x14, 0x02, 0x16, 0x02, 0x13, 0x8a, 0x11, 0xda, 0x10, 0x72, 0x10,
1160 0x22, 0x10, 0x02, 0x10, 0xfe, 0x1f};
1161 } -maskdata $filemask
1163 image create bitmap file_question -background white -foreground black -data {
1164 #define file_question_width 14
1165 #define file_question_height 15
1166 static unsigned char file_question_bits[] = {
1167 0xfe, 0x01, 0x02, 0x02, 0xe2, 0x04, 0xf2, 0x09, 0x1a, 0x1b, 0x0a, 0x13,
1168 0x82, 0x11, 0xc2, 0x10, 0x62, 0x10, 0x62, 0x10, 0x02, 0x10, 0x62, 0x10,
1169 0x62, 0x10, 0x02, 0x10, 0xfe, 0x1f};
1170 } -maskdata $filemask
1172 image create bitmap file_removed -background white -foreground red -data {
1173 #define file_removed_width 14
1174 #define file_removed_height 15
1175 static unsigned char file_removed_bits[] = {
1176 0xfe, 0x01, 0x02, 0x03, 0x02, 0x05, 0x02, 0x09, 0x02, 0x1f, 0x02, 0x10,
1177 0x1a, 0x16, 0x32, 0x13, 0xe2, 0x11, 0xc2, 0x10, 0xe2, 0x11, 0x32, 0x13,
1178 0x1a, 0x16, 0x02, 0x10, 0xfe, 0x1f};
1179 } -maskdata $filemask
1181 image create bitmap file_merge -background white -foreground blue -data {
1182 #define file_merge_width 14
1183 #define file_merge_height 15
1184 static unsigned char file_merge_bits[] = {
1185 0xfe, 0x01, 0x02, 0x03, 0x62, 0x05, 0x62, 0x09, 0x62, 0x1f, 0x62, 0x10,
1186 0xfa, 0x11, 0xf2, 0x10, 0x62, 0x10, 0x02, 0x10, 0xfa, 0x17, 0x02, 0x10,
1187 0xfa, 0x17, 0x02, 0x10, 0xfe, 0x1f};
1188 } -maskdata $filemask
1190 set ui_index .vpane.files.index.list
1191 set ui_other .vpane.files.other.list
1192 set max_status_desc 0
1194 {__ i plain "Unmodified"}
1195 {_M i mod "Modified"}
1196 {M_ i fulltick "Checked in"}
1197 {MM i parttick "Partially included"}
1199 {_O o plain "Untracked"}
1200 {A_ o fulltick "Added"}
1201 {AM o parttick "Partially added"}
1202 {AD o question "Added (but now gone)"}
1204 {_D i question "Missing"}
1205 {D_ i removed "Removed"}
1206 {DD i removed "Removed"}
1207 {DO i removed "Removed (still exists)"}
1209 {UM i merge "Merge conflicts"}
1210 {U_ i merge "Merge conflicts"}
1212 if {$max_status_desc < [string length [lindex $i 3]]} {
1213 set max_status_desc [string length [lindex $i 3]]
1215 if {[lindex $i 1] == {i}} {
1216 set all_cols([lindex $i 0]) $ui_index
1218 set all_cols([lindex $i 0]) $ui_other
1220 set all_icons([lindex $i 0]) file_[lindex $i 2]
1221 set all_descs([lindex $i 0]) [lindex $i 3]
1225 ######################################################################
1229 proc hook_failed_popup {hook msg} {
1230 global gitdir font_ui font_diff appname
1237 label $w.m.l1 -text "$hook hook failed:" \
1240 -font [concat $font_ui bold]
1242 -background white -borderwidth 1 \
1244 -width 80 -height 10 \
1246 -yscrollcommand [list $w.m.sby set]
1248 -text {You must correct the above errors before committing.} \
1251 -font [concat $font_ui bold]
1252 scrollbar $w.m.sby -command [list $w.m.t yview]
1253 pack $w.m.l1 -side top -fill x
1254 pack $w.m.l2 -side bottom -fill x
1255 pack $w.m.sby -side right -fill y
1256 pack $w.m.t -side left -fill both -expand 1
1257 pack $w.m -side top -fill both -expand 1 -padx 5 -pady 10
1259 $w.m.t insert 1.0 $msg
1260 $w.m.t conf -state disabled
1262 button $w.ok -text OK \
1265 -command "destroy $w"
1266 pack $w.ok -side bottom
1268 bind $w <Visibility> "grab $w; focus $w"
1269 bind $w <Key-Return> "destroy $w"
1270 wm title $w "$appname ([lindex [file split \
1271 [file normalize [file dirname $gitdir]]] \
1276 set next_console_id 0
1278 proc new_console {short_title long_title} {
1279 global next_console_id console_data
1280 set w .console[incr next_console_id]
1281 set console_data($w) [list $short_title $long_title]
1282 return [console_init $w]
1285 proc console_init {w} {
1286 global console_cr console_data
1287 global gitdir appname font_ui font_diff M1B
1289 set console_cr($w) 1.0
1292 label $w.m.l1 -text "[lindex $console_data($w) 1]:" \
1295 -font [concat $font_ui bold]
1297 -background white -borderwidth 1 \
1299 -width 80 -height 10 \
1302 -yscrollcommand [list $w.m.sby set]
1303 label $w.m.s -anchor w \
1305 -font [concat $font_ui bold]
1306 scrollbar $w.m.sby -command [list $w.m.t yview]
1307 pack $w.m.l1 -side top -fill x
1308 pack $w.m.s -side bottom -fill x
1309 pack $w.m.sby -side right -fill y
1310 pack $w.m.t -side left -fill both -expand 1
1311 pack $w.m -side top -fill both -expand 1 -padx 5 -pady 10
1313 menu $w.ctxm -tearoff 0
1314 $w.ctxm add command -label "Copy" \
1316 -command "tk_textCopy $w.m.t"
1317 $w.ctxm add command -label "Select All" \
1319 -command "$w.m.t tag add sel 0.0 end"
1320 $w.ctxm add command -label "Copy All" \
1323 $w.m.t tag add sel 0.0 end
1325 $w.m.t tag remove sel 0.0 end
1328 button $w.ok -text {Running...} \
1332 -command "destroy $w"
1333 pack $w.ok -side bottom
1335 bind $w.m.t <Any-Button-3> "tk_popup $w.ctxm %X %Y"
1336 bind $w.m.t <$M1B-Key-a> "$w.m.t tag add sel 0.0 end;break"
1337 bind $w.m.t <$M1B-Key-A> "$w.m.t tag add sel 0.0 end;break"
1338 bind $w <Visibility> "focus $w"
1339 wm title $w "$appname ([lindex [file split \
1340 [file normalize [file dirname $gitdir]]] \
1341 end]): [lindex $console_data($w) 0]"
1345 proc console_exec {w cmd {after {}}} {
1348 # -- Windows tosses the enviroment when we exec our child.
1349 # But most users need that so we have to relogin. :-(
1351 if {$tcl_platform(platform) == {windows}} {
1352 set cmd [list sh --login -c "cd \"[pwd]\" && [join $cmd { }]"]
1355 # -- Tcl won't
let us redirect both stdout and stderr to
1356 # the same pipe. So pass it through cat...
1358 set cmd
[concat |
$cmd |
& cat]
1360 set fd_f
[open
$cmd r
]
1361 fconfigure
$fd_f -blocking 0 -translation binary
1362 fileevent
$fd_f readable
[list console_read
$w $fd_f $after]
1365 proc console_read
{w fd after
} {
1366 global console_cr console_data
1370 if {![winfo exists
$w]} {console_init
$w}
1371 $w.m.t conf
-state normal
1373 set n
[string length
$buf]
1375 set cr
[string first
"\r" $buf $c]
1376 set lf
[string first
"\n" $buf $c]
1377 if {$cr < 0} {set cr
[expr $n + 1]}
1378 if {$lf < 0} {set lf
[expr $n + 1]}
1381 $w.m.t insert end
[string range
$buf $c $lf]
1382 set console_cr
($w) [$w.m.t index
{end
-1c}]
1386 $w.m.t delete
$console_cr($w) end
1387 $w.m.t insert end
"\n"
1388 $w.m.t insert end
[string range
$buf $c $cr]
1393 $w.m.t conf
-state disabled
1397 fconfigure
$fd -blocking 1
1399 if {[catch
{close
$fd}]} {
1400 if {![winfo exists
$w]} {console_init
$w}
1401 $w.m.s conf
-background red
-text {Error
: Command Failed
}
1402 $w.ok conf
-text Close
1403 $w.ok conf
-state normal
1405 } elseif
{[winfo exists
$w]} {
1406 $w.m.s conf
-background green
-text {Success
}
1407 $w.ok conf
-text Close
1408 $w.ok conf
-state normal
1411 array
unset console_cr
$w
1412 array
unset console_data
$w
1414 uplevel
#0 $after $ok
1418 fconfigure
$fd -blocking 0
1421 ######################################################################
1425 set starting_gitk_msg
{Please
wait... Starting gitk...
}
1428 global tcl_platform ui_status_value starting_gitk_msg
1430 set ui_status_value
$starting_gitk_msg
1432 if {$ui_status_value == $starting_gitk_msg} {
1433 set ui_status_value
{Ready.
}
1437 if {$tcl_platform(platform
) == {windows
}} {
1445 set w
[new_console
"repack" "Repacking the object database"]
1446 set cmd
[list git repack
]
1449 console_exec
$w $cmd
1455 global gitdir ui_comm quitting
1457 if {$quitting} return
1460 set save
[file join $gitdir GITGUI_MSG
]
1461 set msg
[string trim
[$ui_comm get
0.0 end
]]
1462 if {[$ui_comm edit modified
] && $msg != {}} {
1464 set fd
[open
$save w
]
1465 puts
$fd [string trim
[$ui_comm get
0.0 end
]]
1468 } elseif
{$msg == {} && [file exists
$save]} {
1480 proc do_include_all
{} {
1481 global update_active ui_status_value
1483 if {$update_active ||
![lock_index begin-update
]} return
1486 set ui_status_value
{Including all modified files...
}
1489 foreach path
[array names file_states
] {
1490 set s
$file_states($path)
1496 _D
{toggle_mode
$path}
1501 set ui_status_value
{Ready.
}
1505 set GIT_COMMITTER_IDENT
{}
1507 proc do_signoff
{} {
1508 global ui_comm GIT_COMMITTER_IDENT
1510 if {$GIT_COMMITTER_IDENT == {}} {
1511 if {[catch
{set me
[exec git var GIT_COMMITTER_IDENT
]} err
]} {
1512 error_popup
"Unable to obtain your identity:\n\n$err"
1515 if {![regexp
{^
(.
*) [0-9]+ [-+0-9]+$
} \
1516 $me me GIT_COMMITTER_IDENT
]} {
1517 error_popup
"Invalid GIT_COMMITTER_IDENT:\n\n$me"
1522 set sob
"Signed-off-by: $GIT_COMMITTER_IDENT"
1523 set last
[$ui_comm get
{end
-1c linestart
} {end
-1c}]
1524 if {$last != $sob} {
1525 $ui_comm edit separator
1527 && ![regexp
{^
[A-Z
][A-Za-z
]*-[A-Za-z-
]+: *} $last]} {
1528 $ui_comm insert end
"\n"
1530 $ui_comm insert end
"\n$sob"
1531 $ui_comm edit separator
1536 proc do_amend_last
{} {
1544 # shift == 1: left click
1546 proc click
{w x y
shift wx wy
} {
1547 global ui_index ui_other file_lists
1549 set pos
[split [$w index @
$x,$y] .
]
1550 set lno
[lindex
$pos 0]
1551 set col [lindex
$pos 1]
1552 set path
[lindex
$file_lists($w) [expr $lno - 1]]
1553 if {$path == {}} return
1555 if {$col > 0 && $shift == 1} {
1556 show_diff
$path $w $lno
1560 proc unclick
{w x y
} {
1563 set pos
[split [$w index @
$x,$y] .
]
1564 set lno
[lindex
$pos 0]
1565 set col [lindex
$pos 1]
1566 set path
[lindex
$file_lists($w) [expr $lno - 1]]
1567 if {$path == {}} return
1574 ######################################################################
1581 menu .mbar
-tearoff 0
1582 catch
{set font_ui
[lindex
$repo_config(gui.fontui
) 0]}
1583 catch
{set font_diff
[lindex
$repo_config(gui.fontdiff
) 0]}
1584 if {$font_ui == {}} {catch
{set font_ui
[.mbar cget
-font]}}
1585 if {$font_ui == {}} {set font_ui
{Helvetica
10}}
1586 if {$font_diff == {}} {set font_diff
{Courier
10}}
1587 if {$cursor_ptr == {}} {set cursor_ptr left_ptr
}
1589 switch
-glob -- "$tcl_platform(platform),$tcl_platform(os)" {
1590 windows
,* {set M1B Control
; set M1T Ctrl
}
1591 unix
,Darwin
{set M1B M1
; set M1T Cmd
}
1592 * {set M1B M1
; set M1T M1
}
1596 .mbar add cascade
-label Project
-menu .mbar.project
1597 .mbar add cascade
-label Edit
-menu .mbar.edit
1598 .mbar add cascade
-label Commit
-menu .mbar.commit
1599 .mbar add cascade
-label Fetch
-menu .mbar.fetch
1600 .mbar add cascade
-label Pull
-menu .mbar.pull
1601 .mbar add cascade
-label Push
-menu .mbar.push
1602 .mbar add cascade
-label Options
-menu .mbar.options
1603 . configure
-menu .mbar
1607 .mbar.project add
command -label Visualize \
1610 .mbar.project add
command -label {Repack Database
} \
1611 -command do_repack \
1613 .mbar.project add
command -label Quit \
1615 -accelerator $M1T-Q \
1621 .mbar.edit add
command -label Undo \
1622 -command {catch
{[focus
] edit undo
}} \
1623 -accelerator $M1T-Z \
1625 .mbar.edit add
command -label Redo \
1626 -command {catch
{[focus
] edit redo
}} \
1627 -accelerator $M1T-Y \
1629 .mbar.edit add separator
1630 .mbar.edit add
command -label Cut \
1631 -command {catch
{tk_textCut
[focus
]}} \
1632 -accelerator $M1T-X \
1634 .mbar.edit add
command -label Copy \
1635 -command {catch
{tk_textCopy
[focus
]}} \
1636 -accelerator $M1T-C \
1638 .mbar.edit add
command -label Paste \
1639 -command {catch
{tk_textPaste
[focus
]; [focus
] see insert
}} \
1640 -accelerator $M1T-V \
1642 .mbar.edit add
command -label Delete \
1643 -command {catch
{[focus
] delete sel.first sel.last
}} \
1646 .mbar.edit add separator
1647 .mbar.edit add
command -label {Select All
} \
1648 -command {catch
{[focus
] tag add sel
0.0 end
}} \
1649 -accelerator $M1T-A \
1654 .mbar.commit add
command -label Rescan \
1655 -command do_rescan \
1658 lappend disable_on_lock \
1659 [list .mbar.commit entryconf
[.mbar.commit index last
] -state]
1660 .mbar.commit add
command -label {Amend Last Commit
} \
1661 -command do_amend_last \
1663 lappend disable_on_lock \
1664 [list .mbar.commit entryconf
[.mbar.commit index last
] -state]
1665 .mbar.commit add
command -label {Include All Files
} \
1666 -command do_include_all \
1667 -accelerator $M1T-I \
1669 lappend disable_on_lock \
1670 [list .mbar.commit entryconf
[.mbar.commit index last
] -state]
1671 .mbar.commit add
command -label {Sign Off
} \
1672 -command do_signoff \
1673 -accelerator $M1T-S \
1675 .mbar.commit add
command -label Commit \
1676 -command do_commit \
1677 -accelerator $M1T-Return \
1679 lappend disable_on_lock \
1680 [list .mbar.commit entryconf
[.mbar.commit index last
] -state]
1693 .mbar.options add checkbutton \
1694 -label {Trust File Modification Timestamps
} \
1698 -variable cfg_trust_mtime
1700 # -- Main Window Layout
1701 panedwindow .vpane
-orient vertical
1702 panedwindow .vpane.files
-orient horizontal
1703 .vpane add .vpane.files
-sticky nsew
-height 100 -width 400
1704 pack .vpane
-anchor n
-side top
-fill both
-expand 1
1706 # -- Index File List
1707 frame .vpane.files.index
-height 100 -width 400
1708 label .vpane.files.index.title
-text {Modified Files
} \
1711 text
$ui_index -background white
-borderwidth 0 \
1712 -width 40 -height 10 \
1714 -cursor $cursor_ptr \
1715 -yscrollcommand {.vpane.files.index.sb
set} \
1717 scrollbar .vpane.files.index.sb
-command [list
$ui_index yview
]
1718 pack .vpane.files.index.title
-side top
-fill x
1719 pack .vpane.files.index.sb
-side right
-fill y
1720 pack
$ui_index -side left
-fill both
-expand 1
1721 .vpane.files add .vpane.files.index
-sticky nsew
1723 # -- Other (Add) File List
1724 frame .vpane.files.other
-height 100 -width 100
1725 label .vpane.files.other.title
-text {Untracked Files
} \
1728 text
$ui_other -background white
-borderwidth 0 \
1729 -width 40 -height 10 \
1731 -cursor $cursor_ptr \
1732 -yscrollcommand {.vpane.files.other.sb
set} \
1734 scrollbar .vpane.files.other.sb
-command [list
$ui_other yview
]
1735 pack .vpane.files.other.title
-side top
-fill x
1736 pack .vpane.files.other.sb
-side right
-fill y
1737 pack
$ui_other -side left
-fill both
-expand 1
1738 .vpane.files add .vpane.files.other
-sticky nsew
1740 $ui_index tag conf in_diff
-font [concat
$font_ui bold
]
1741 $ui_other tag conf in_diff
-font [concat
$font_ui bold
]
1743 # -- Diff and Commit Area
1744 frame .vpane.lower
-height 400 -width 400
1745 frame .vpane.lower.commarea
1746 frame .vpane.lower.
diff -relief sunken
-borderwidth 1
1747 pack .vpane.lower.commarea
-side top
-fill x
1748 pack .vpane.lower.
diff -side bottom
-fill both
-expand 1
1749 .vpane add .vpane.lower
-stick nsew
1751 # -- Commit Area Buttons
1752 frame .vpane.lower.commarea.buttons
1753 label .vpane.lower.commarea.buttons.l
-text {} \
1757 pack .vpane.lower.commarea.buttons.l
-side top
-fill x
1758 pack .vpane.lower.commarea.buttons
-side left
-fill y
1760 button .vpane.lower.commarea.buttons.rescan
-text {Rescan
} \
1761 -command do_rescan \
1763 pack .vpane.lower.commarea.buttons.rescan
-side top
-fill x
1764 lappend disable_on_lock \
1765 {.vpane.lower.commarea.buttons.rescan conf
-state}
1767 button .vpane.lower.commarea.buttons.amend
-text {Amend Last
} \
1768 -command do_amend_last \
1770 pack .vpane.lower.commarea.buttons.amend
-side top
-fill x
1771 lappend disable_on_lock \
1772 {.vpane.lower.commarea.buttons.amend conf
-state}
1774 button .vpane.lower.commarea.buttons.incall
-text {Include All
} \
1775 -command do_include_all \
1777 pack .vpane.lower.commarea.buttons.incall
-side top
-fill x
1778 lappend disable_on_lock \
1779 {.vpane.lower.commarea.buttons.incall conf
-state}
1781 button .vpane.lower.commarea.buttons.signoff
-text {Sign Off
} \
1782 -command do_signoff \
1784 pack .vpane.lower.commarea.buttons.signoff
-side top
-fill x
1786 button .vpane.lower.commarea.buttons.commit
-text {Commit
} \
1787 -command do_commit \
1789 pack .vpane.lower.commarea.buttons.commit
-side top
-fill x
1790 lappend disable_on_lock \
1791 {.vpane.lower.commarea.buttons.commit conf
-state}
1793 # -- Commit Message Buffer
1794 frame .vpane.lower.commarea.buffer
1795 set ui_comm .vpane.lower.commarea.buffer.t
1796 set ui_coml .vpane.lower.commarea.buffer.l
1797 label
$ui_coml -text {Commit Message
:} \
1801 trace add variable commit_type
write {uplevel
#0 {
1802 switch
-glob $commit_type \
1803 initial
{$ui_coml conf
-text {Initial Commit Message
:}} \
1804 amend
{$ui_coml conf
-text {Amended Commit Message
:}} \
1805 merge
{$ui_coml conf
-text {Merge Commit Message
:}} \
1806 * {$ui_coml conf
-text {Commit Message
:}}
1808 text
$ui_comm -background white
-borderwidth 1 \
1811 -autoseparators true \
1813 -width 75 -height 9 -wrap none \
1815 -yscrollcommand {.vpane.lower.commarea.buffer.sby
set}
1816 scrollbar .vpane.lower.commarea.buffer.sby \
1817 -command [list
$ui_comm yview
]
1818 pack
$ui_coml -side top
-fill x
1819 pack .vpane.lower.commarea.buffer.sby
-side right
-fill y
1820 pack
$ui_comm -side left
-fill y
1821 pack .vpane.lower.commarea.buffer
-side left
-fill y
1823 # -- Commit Message Buffer Context Menu
1825 menu
$ui_comm.ctxm
-tearoff 0
1826 $ui_comm.ctxm add
command -label "Cut" \
1828 -command "tk_textCut $ui_comm"
1829 $ui_comm.ctxm add
command -label "Copy" \
1831 -command "tk_textCopy $ui_comm"
1832 $ui_comm.ctxm add
command -label "Paste" \
1834 -command "tk_textPaste $ui_comm"
1835 $ui_comm.ctxm add
command -label "Delete" \
1837 -command "$ui_comm delete sel.first sel.last"
1838 $ui_comm.ctxm add separator
1839 $ui_comm.ctxm add
command -label "Select All" \
1841 -command "$ui_comm tag add sel 0.0 end"
1842 $ui_comm.ctxm add
command -label "Copy All" \
1845 $ui_comm tag add sel 0.0 end
1846 tk_textCopy $ui_comm
1847 $ui_comm tag remove sel 0.0 end
1849 $ui_comm.ctxm add separator
1850 $ui_comm.ctxm add
command -label "Sign Off" \
1853 bind $ui_comm <Any-Button-3
> "tk_popup $ui_comm.ctxm %X %Y"
1856 set ui_fname_value
{}
1857 set ui_fstatus_value
{}
1858 frame .vpane.lower.
diff.header
-background orange
1859 label .vpane.lower.
diff.header.l1
-text {File
:} \
1860 -background orange \
1862 label .vpane.lower.
diff.header.l2
-textvariable ui_fname_value \
1863 -background orange \
1867 label .vpane.lower.
diff.header.l3
-text {Status
:} \
1868 -background orange \
1870 label .vpane.lower.
diff.header.l4
-textvariable ui_fstatus_value \
1871 -background orange \
1872 -width $max_status_desc \
1876 pack .vpane.lower.
diff.header.l1
-side left
1877 pack .vpane.lower.
diff.header.l2
-side left
-fill x
1878 pack .vpane.lower.
diff.header.l4
-side right
1879 pack .vpane.lower.
diff.header.l3
-side right
1882 frame .vpane.lower.
diff.body
1883 set ui_diff .vpane.lower.
diff.body.t
1884 text
$ui_diff -background white
-borderwidth 0 \
1885 -width 80 -height 15 -wrap none \
1887 -xscrollcommand {.vpane.lower.
diff.body.sbx
set} \
1888 -yscrollcommand {.vpane.lower.
diff.body.sby
set} \
1890 scrollbar .vpane.lower.
diff.body.sbx
-orient horizontal \
1891 -command [list
$ui_diff xview
]
1892 scrollbar .vpane.lower.
diff.body.sby
-orient vertical \
1893 -command [list
$ui_diff yview
]
1894 pack .vpane.lower.
diff.body.sbx
-side bottom
-fill x
1895 pack .vpane.lower.
diff.body.sby
-side right
-fill y
1896 pack
$ui_diff -side left
-fill both
-expand 1
1897 pack .vpane.lower.
diff.header
-side top
-fill x
1898 pack .vpane.lower.
diff.body
-side bottom
-fill both
-expand 1
1900 $ui_diff tag conf dm
-foreground red
1901 $ui_diff tag conf dp
-foreground blue
1902 $ui_diff tag conf di
-foreground "#00a000"
1903 $ui_diff tag conf dni
-foreground "#a000a0"
1904 $ui_diff tag conf da
-font [concat
$font_diff bold
]
1905 $ui_diff tag conf bold
-font [concat
$font_diff bold
]
1907 # -- Diff Body Context Menu
1909 menu
$ui_diff.ctxm
-tearoff 0
1910 $ui_diff.ctxm add
command -label "Copy" \
1912 -command "tk_textCopy $ui_diff"
1913 $ui_diff.ctxm add
command -label "Select All" \
1915 -command "$ui_diff tag add sel 0.0 end"
1916 $ui_diff.ctxm add
command -label "Copy All" \
1919 $ui_diff tag add sel 0.0 end
1920 tk_textCopy $ui_diff
1921 $ui_diff tag remove sel 0.0 end
1923 $ui_diff.ctxm add separator
1924 $ui_diff.ctxm add
command -label "Decrease Font Size" \
1927 lset font_diff
1 [expr [lindex
$font_diff 1] - 1]
1928 $ui_diff configure
-font $font_diff
1929 $ui_diff tag conf da
-font [concat
$font_diff bold
]
1930 $ui_diff tag conf bold
-font [concat
$font_diff bold
]
1932 $ui_diff.ctxm add
command -label "Increase Font Size" \
1935 lset font_diff
1 [expr [lindex
$font_diff 1] + 1]
1936 $ui_diff configure
-font $font_diff
1937 $ui_diff tag conf da
-font [concat
$font_diff bold
]
1938 $ui_diff tag conf bold
-font [concat
$font_diff bold
]
1940 bind $ui_diff <Any-Button-3
> "tk_popup $ui_diff.ctxm %X %Y"
1943 set ui_status_value
{Initializing...
}
1944 label .status
-textvariable ui_status_value \
1950 pack .status
-anchor w
-side bottom
-fill x
1954 set gm
[lindex
$repo_config(gui.geometry
) 0]
1955 wm geometry .
[lindex
$gm 0]
1956 .vpane sash place
0 \
1957 [lindex
[.vpane sash coord
0] 0] \
1959 .vpane.files sash place
0 \
1961 [lindex
[.vpane.files sash coord
0] 1]
1966 bind $ui_comm <$M1B-Key-Return> {do_commit
;break}
1967 bind $ui_comm <$M1B-Key-i> {do_include_all
;break}
1968 bind $ui_comm <$M1B-Key-I> {do_include_all
;break}
1969 bind $ui_comm <$M1B-Key-x> {tk_textCut
%W
;break}
1970 bind $ui_comm <$M1B-Key-X> {tk_textCut
%W
;break}
1971 bind $ui_comm <$M1B-Key-c> {tk_textCopy
%W
;break}
1972 bind $ui_comm <$M1B-Key-C> {tk_textCopy
%W
;break}
1973 bind $ui_comm <$M1B-Key-v> {tk_textPaste
%W
; %W see insert
; break}
1974 bind $ui_comm <$M1B-Key-V> {tk_textPaste
%W
; %W see insert
; break}
1975 bind $ui_comm <$M1B-Key-a> {%W tag add sel
0.0 end
;break}
1976 bind $ui_comm <$M1B-Key-A> {%W tag add sel
0.0 end
;break}
1978 bind $ui_diff <$M1B-Key-x> {tk_textCopy
%W
;break}
1979 bind $ui_diff <$M1B-Key-X> {tk_textCopy
%W
;break}
1980 bind $ui_diff <$M1B-Key-c> {tk_textCopy
%W
;break}
1981 bind $ui_diff <$M1B-Key-C> {tk_textCopy
%W
;break}
1982 bind $ui_diff <$M1B-Key-v> {break}
1983 bind $ui_diff <$M1B-Key-V> {break}
1984 bind $ui_diff <$M1B-Key-a> {%W tag add sel
0.0 end
;break}
1985 bind $ui_diff <$M1B-Key-A> {%W tag add sel
0.0 end
;break}
1986 bind $ui_diff <Key-Up
> {catch
{%W yview scroll
-1 units
};break}
1987 bind $ui_diff <Key-Down
> {catch
{%W yview scroll
1 units
};break}
1988 bind $ui_diff <Key-Left
> {catch
{%W xview scroll
-1 units
};break}
1989 bind $ui_diff <Key-Right
> {catch
{%W xview scroll
1 units
};break}
1991 bind .
<Destroy
> do_quit
1992 bind all
<Key-F5
> do_rescan
1993 bind all
<$M1B-Key-r> do_rescan
1994 bind all
<$M1B-Key-R> do_rescan
1995 bind .
<$M1B-Key-s> do_signoff
1996 bind .
<$M1B-Key-S> do_signoff
1997 bind .
<$M1B-Key-i> do_include_all
1998 bind .
<$M1B-Key-I> do_include_all
1999 bind .
<$M1B-Key-Return> do_commit
2000 bind all
<$M1B-Key-q> do_quit
2001 bind all
<$M1B-Key-Q> do_quit
2002 bind all
<$M1B-Key-w> {destroy
[winfo toplevel
%W
]}
2003 bind all
<$M1B-Key-W> {destroy
[winfo toplevel
%W
]}
2004 foreach i
[list
$ui_index $ui_other] {
2005 bind $i <Button-1
> {click
%W
%x
%y
1 %X
%Y
; break}
2006 bind $i <Button-3
> {click
%W
%x
%y
3 %X
%Y
; break}
2007 bind $i <ButtonRelease-1
> {unclick
%W
%x
%y
; break}
2011 set file_lists
($ui_index) [list
]
2012 set file_lists
($ui_other) [list
]
2014 wm title .
"$appname ([file normalize [file dirname $gitdir]])"
2015 focus
-force $ui_comm
2017 populate_remote_menu .mbar.fetch From fetch_from
2018 populate_remote_menu .mbar.push To push_to
2019 populate_pull_menu .mbar.pull