On Mac OS X the OS has "features" that like to draw thick black
borders around the text field that has focus. This is nice if
you want to know where your text is going and are blind as a bat,
but it isn't the best thing to have in a table that is being
faked through the abuse of Tk text widgets.
By setting our takefocus, highlightthickness and padx/y we can
get rid of this border and get our text widgets packed right next
to each other, with no padding between them. This makes the blame
background color smoothly run across the entire line of commit data,
line number and file content.
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Originally I had placed this loaded column between the line number
and the file line data to help users know if a particular line has
received annotation data or not yet. This way users would know if
the line(s) they were interested in were ready for viewing, or if
they still had to wait. It also was an entertaining way for the
user to spend their time waiting for git-blame --incremental to
compute the complete set of annotations.
However it is completely useless now that we show the abbreviated
commit SHA-1 and author initials in the leftmost column. That area
is empty until we get the annotation data, and as soon as we get it
in we display something there, indicating to the user that there is
now blame data ready. Further with the tooltips the user is likely
to see the data as soon as it comes in, as they are probably not
keeping their mouse perfectly still. So I'm removing the field to
save screen space for more useful things, like file content.
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Some commit lines can get really long when users enter a lot of
text without linewrapping (for example). Rather than letting the
menu get out of control in terms of width we clip the summary to
the first 50+ characters.
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Apparently Tk on Mac OS X won't draw a button with an image using a
transparent background. Instead it draws the button using some sort
of 3D effect, even though I asked for no relief and no border. The
background is also not our orange that we expected it to be.
Earlier I had tried this same trick on Windows and it draws the same
way as the button did, so I'm going to switch to the label as that
seems to be more portable.
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
If we have two commits right next to each other in the final
file and they were kept as different blocks in the leftmost
column then its probably because the original filename was
different. To help the user know where they are digging into
when they click on that link we now show the original file in
the tooltip, but to save space we do so only if the original
file is not the same as the file we are currently viewing.
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Consecutive chunks of a file could come from the same commit, but
have different original file names. Previously we would have put
them into a single group, but then the hyperlink would jump to only
one of the files, and the other would not be accessible. Now we can
get to the other file too.
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
gitweb has long had a feature where the user can click on any
commit the blame display and go visit that commit's information
page. From the user could go get the blame display for the file
they are tracking, and try to digg through the history of any
part of the code they are interested in seeing.
We now offer somewhat similiar functionality in git-gui. The 4
digit commit abreviation in the first column of our blame view is
now offered as a hyperlink if the commit isn't the one we are now
viewing the blame output for (as there is no point in linking back
to yourself). Clicking on that link will stop the current blame
engine (if still running), push the new target commit onto the
history stack, and restart the blame viewer at that commit, using
the "original file name" as supplied by git-blame for that chunk
of the output.
Users can navigate back to a version they had been viewing before
by way of a back button, which offers the prior commits in a popup
menu displayed right below the back button. I'm always showing the
menu here as the cost of switching between views is very high; you
don't want to jump to a commit you are not interested in looking at
again.
During switches we throw away all data except the cached commit data,
as that is relatively small compared to most source files and their
annotation marks. Unfortunately throwing this per-file data away in
Tcl seems to take some time; I probably should move the line indexed
arrays to proper lists and use [lindex] rather than the array lookup
(usually lists are faster).
We now start the git-blame process using "nice", so that its priority
will drop hopefully below our own. If I don't do this the blame engine
gets a lot of CPU under Windows 2000 and the git-gui user interface is
almost non-responsive, even though Tcl is just sitting there waiting
for events.
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Computing the blame records for a large file with a long project
history can take git a while to run; traditionally we have shown
a little meter in the status area of our blame viewer that lets
the user know how many lines have been finished, and how far we
are through the process.
Usually such progress indicators are drawn with a little progress
bar in the window, where the bar shows how much has been completed
and hides itself when the process is complete. I'm using a very
simple hack to do that: draw a canvas with a filled rectangle.
Of course the time remaining has absolutely no relationship to the
progress meter. It could take very little time for git-blame to get
the first 90% of the file, and then it could take many times that to
get the remaining 10%. So the progress meter doesn't really have any
sort of assurances that it relates to the true progress of the work.
But in practice on some ugly history it does seem to hold a reasonable
indicator to the completion status. Besides, its amusing to watch and
that keeps the user from realizing git is being somewhat slow.
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
At one point I tried to present the blame viewer to an audience of
people on a 640 by 480 pixel LCD projector. This did not work at
all as the top area (the file data) was taking up all of the screen
realestate and the split point was not adjustable by the user. In
general locking the user into a specific ratio of display is just
not user friendly.
So we now place a split pane control into the middle of our blame
window, so the user can adjust it to their current needs. If the
window increases (or decreases) in height we assign the difference
to the file data area, as that is generally the area of the window
that users are trying to see more of when they grow the window.
Unfortunately there appears to be a bug in the "pack" layout manager
in Tcl/Tk 8.4.1. The status bar and the lower commit pane was being
squashed if the window decreased in height. I think the pack manager
was just not decreasing the size of the panedwindow slave properly if
the main window shrank. Switching to the "grid" layout manager fixes
the problem, but is slightly uglier setup code.
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Frequently when I'm looking at blocks of code in the blame
viewer I want to know who is the culprit, or who I should
be praising for a job well done. The tooltips nicely show
this if I mouse over a block, but it doesn't work to get
this detail at a glance.
Since we don't use the leftmost commit column for anything
after the first line within a commit group I'm now tossing
the author's initials into that field, right justified. It
is quite clearly not a SHA-1 number as we always show the
SHA-1 in lowercase, while we explicitly select only the
uppercase characters from an author's name field, and only
those that are following whitespace.
I'm using initials here over anything else as they are quite
commonly unique within small development teams. The leading
part of the email address field was out for some of the teams
I work with, as there the email addresses are all of the form
"Givenname.Surname@initech.com". That will never fit into the
4 characters available.
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
The | in the continued lines of the same commit group as not
easily seen on the left edge; putting a single space in front
of the pipe makes it slightly more visually appealing to me as
I can follow the line down through the group to the next commit
marker.
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Because we no longer redraw colors every time we select a particular
commit there is no need to redraw the screen after we get a new commit
in from blame --incremental.
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
The selected commit's blame header is now drawn in green, using
the same background color that is shown in the main file content
viewer. The result is a much better looking commit pane, as we
use bold for header "keys" and proportional width fonts for the
stuff that doesn't need to be fixed width to maintain its formatting.
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
When the mouse is over a particular line and we have blame data
for that line, but its not the active commit, we should show the
user information about that commit like who the author was and
what the subject (first line) was.
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Since we don't allow the user to select text from the file
viewer right now I'm disabling the normal text cursor and
putting in a plain arror instead. This way users don't
think they can select and copy text, because they can't.
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
If two consecutive lines in the final file came from the same commit
then we store a "|" in the first column rather than the commit id,
for the second and subsequent lines in that block. This cleans up
the interface so runs associated with the same commit can be more
easily seen visually.
We also now use the abbreviation "work" for the uncommitted stuff in
your working directory, rather than "0000". This looks nicer to the
eyes and explains pretty quickly what is going on.
There was also a minor bug in the commit abbreviation column for the
last line of the file. This is now also fixed.
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
The git-gui blame viewer has always been ugly as s**t. Linus Torvalds
suggested the coloring scheme I'm using here, which is two different
shades of grey for the background colors, and black text on a pale green
background for the currently selected/focused commit.
The difference is a massive improvement. The interface no longer will
cause seizures in people who are prone to that sort of thing. It no
longer uses a very offensive hot pink. The green being current actually
makes sense. And not having the background of the other non-current
lines change when you change the current commit is really a big deal.
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
The blame viewer has this silly blank line at the bottom of it;
we really don't want to see it displayed as we will never get
any blame data for that line (it doesn't exist in the source).
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
A lot of this code was pre-class, which meant that I just sort of
copied and pasted my way through it, rather than being really smart
and using a variable for each widget's path name. Since we have a
field for each path, we can use those throughout the constructor
and make things a lot neater.
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
We now show the first 4 digits of each commit in the left most
column of our blame viewer, before the line numbers. These are
drawn as the data becomes available from git-blame --incremental,
and helps the user to visually group lines together.
I'm using only the first 4 digits because within a given cluster
of lines its unlikely that two neighboring commits will have the
same 4 digit prefix.
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
The default font was already bold, so marking the selected file with bold
font did not work. Change that to lightgray background.
Also, the header colors are now softer, giving better readability.
Signed-off-by: Matthijs Melchior <mmelchior@xs4all.nl>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
This reverts commit c289f6fa1f.
Junio pointed out that Alex's change breaks in some cases, like
when V=1, and is more verbose than it should be even if that worked.
I'm backing it out and redoing it.
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
For quite a while we have been assuming the user is running on
a Tcl/Tk 8.4 or later platform. This may not be the case on
some very old systems. Unfortunately I am pretty far down the
path of using the Tcl/Tk 8.4 commands and options and cannot
easily work around them to support earlier versions of Tcl/Tk.
So we'll check that we are using the correct version up front,
and if not we'll stop with a related error message.
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Earlier I missed making sure our spinbox widgets used the same font
as the other widgets around them. This meant that using a main font
with a size of 20 would make every widget in the options dialog huge,
but the spinboxes would be left with whatever the OS native font is.
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Its wrong to exit the application if we destroy a random widget
contained withing something else; especially if its some small
trivial thing that has no impact on the overall operation.
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Johannes Sixt pointed out that dropping to 0 lines of context
does allow the user to get more fine-grained hunk selection,
especially since we don't currently support "highlight and
apply (or revert)".
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
If the user has no branches at all (their refs/heads/ is empty)
and they are on a detached HEAD we have a valid repository but
there are no branches to populate into the branch pulldown in
the create branch dialog. Instead of erroring out we can skip
that part of the dialog, much like we do with tracking branches
or tags when the user doesn't have any.
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Johannes Sixt asked me to try to avoid embedding the runtime location
of git-gui's library directory in the executable script. Not embedding
it helps the MinGW to be relocatable to another directory should a user
wish to install the programs in a directory other than the location the
packager wanted them to be installed into.
Most of this is a hack. We try to determine if the path of our master
git-gui script will be able to locate the lib by ../share/git-gui/lib.
This should be true if $(gitexecdir) and $(libdir) have the same prefix.
If they do then we defer the assignment of $(libdir) until runtime, and
we get it from $argv0 rather than embedding it into the script itself.
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Alberto Bertogli reported on #git that git-gui was exiting with
alt-q, while gitk on the same system was exiting with ctrl-q.
That was not what I wanted. I really wanted M1B to be bound to
the Control key on most non-Mac OS X platforms, but according to
Sam Vilain M1 on most systems means alt. Since gitk always does
control, I'm doing the same thing for all non-Mac OS X systems.
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Our GITGUI_LIBDIR macro was testing only for @@ at the start of
the path, assuming nobody would ever find that to be a reasonable
prefix for a directory to install our library into. That is most
likely a valid assumption, but its even more unlikely they would
have the start be @@GITGUI_ and the end be @@. Note that we
cannot use the full string here because that would get expanded
by the sed replacement in our Makefile.
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Petr Baudis pointed out the main git.git repository's Makefile dies
now if git-gui 0.7.0-rc1 or later is being used and TCL_PATH was not
set to a working tclsh program path. This breaks people who may have
a working build configuration today and suddenly upgrade to the latest
git release.
The tclIndex is required for git-gui to load its associated lib files,
but using the Tcl auto_load procedure to source only the files we need
is a performance optimization. We can emulate the auto_load by just
source'ing every file in that directory, assuming we source class.tcl
first to initialize our crude class system.
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
This is a simple change to match what gitk does when it shows
a commit; we format using ISO dates (yyyy-mm-dd HH:MM:SS).
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
We can use [list ...] rather than "", especially when we are talking
about values as then they are properly escaped if necessary. Small
nit, but probably not a huge deal as the only data being inlined here
is Tk paths.
Some of the lines in the parser code were longer than 80 characters
wide, and they actually were all the same value on the end part of
the line. Rather than keeping the mess copied-and-pasted around we
can set the last argument into a local variable and reuse it many
times.
The commit display code was also rather difficult to read on an 80
character wide terminal, so I'm moving it all into a double quoted
string that is easier to read.
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
If the user doesn't give us a revision parameter to our blame
subcommand then we can generate blame against the working tree
file by passing the file path off to blame with the --contents
argument. In this case we cannot obtain the contents of the
file from the ODB; instead we must obtain the contents by
reading the working directory file as-is.
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
The browser subcommand now optionally accepts a single revision
argument; if no revision argument is supplied then we use the
current branch as the tree to browse. This is very common, so
its a nice option.
Our blame subcommand now tries to perform the same assumptions
as the command line git-blame; both the revision and the file
are optional. We assume the argument is a filename if the file
exists in the working directory, otherwise we assume the argument
is a revision name. A -- can be supplied between the two to force
parsing, or before the filename to force it to be a filename.
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
I think it was Andy Parkins who pointed out that git gui blame HEAD f
does not work if f is in a subdirectory and we are currently running
git-gui within that subdirectory. This is happening because we did
not take the user's prefix into account when we computed the file
path in the repository.
We now assume the prefix as returned by rev-parse --show-prefix is
valid and we use that during the command line blame subcommand when
we apply the parameters.
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Our blame viewer code has historically been a mess simply
because the data for multiple viewers was all crammed into
a single pair of Tcl arrays. This made the code hard to
read and even harder to maintain.
Now that we have a slightly better way of tracking the data
for our "meta-widgets" we can make use of it here in the
blame viewer to cleanup the code and make it easier to work
with long term.
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
If a variable reference to a field is to an array, and it is
the only reference to that field in that method we cannot make
it an inlined [set foo] call as the regexp was converting the
Tcl code wrong. We were producing "[set foo](x)" for "$foo(x)",
and that isn't valid Tcl when foo is an array. So we just punt
if the only occurance has a ( after it.
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Now that we have a slightly easier method of working with per-widget
data we should make use of that technique in our browser and console
meta-widgets, as both have a decent amount of information that they
store on a per-widget basis and our current approach of handling
it is difficult to follow.
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
As most of the git-gui interface is based upon "meta-widgets"
that need to carry around a good deal of state (e.g. console
windows, browser windows, blame viewer) we have a good deal
of messy code that tries to store this meta-widget state in
global arrays, where keys into the array are formed from a
union of a unique "object instance id" and the field name.
This is a simple class system for Tcl that allows us to
hide much of that mess by making Tcl do what it does best;
process strings to manipulate its own code during startup.
Each object instance is placed into its own namespace. The
namespace is created when the object instance is created and
the namespace is destroyed when the object instance is removed
from the system. Within that namespace we place variables for
each field within the class; these variables can themselves be
scalar values or full-blown Tcl arrays.
A simple class might be defined as:
class map {
field data
field size 0
constructor {} {
return $this
}
method set {name value} {
set data($name) $value
incr size
}
method size {} {
return $size
} ifdeleted { return 0 }
}
All fields must be declared before any constructors or methods. This
allows our class to generate a list of the fields so it can properly
alter the definition of the constructor and method bodies prior to
passing them off to Tcl for definition with proc. A field may optionally
be given a default/initial value. This can only be done for non-array
type fields.
Constructors are given full access to all fields of the class, so they
can initialize the data values. The default values of fields (if any)
are set before the constructor runs, and the implicit local variable
$this is initialized to the instance identifier.
Methods are given access to fields they actually use in their body.
Every method has an implicit "this" argument inserted as its first
parameter; callers of methods must be sure they supply this value.
Some basic optimization tricks are performed (but not much). We
try to only upvar (locally bind) fields that are accessed within a
method, but we err on the side of caution and may upvar more than
we need to. If a variable is accessed only once within a method
and that access is by $foo (read) we avoid the upvar and instead
use [set foo] to obtain the value. This is slightly faster as Tcl
does not need to lookup the variable twice.
We also offer some small syntatic sugar for interacting with Tk and
the fileevent callback system in Tcl. If a field (say "foo") is used
as "@foo" we insert instead the true global variable name of that
variable into the body of the constructor or method. This allows easy
binding to Tk textvariable options, e.g.:
label $w.title -textvariable @title
Proper namespace callbacks can also be setup with the special cb proc
that is defined in each namespace. [cb _foo a] will invoke the method
_foo in the current namespace, passing it $this as the first (implied)
parameter and a as the second parameter. This makes it very simple to
connect an object instance to a -command option for a Tk widget or to
a fileevent readable or writable for a file channel.
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
I found it useful to be able to use j/k (vi-like keys) to move
up and down the list of branches to merge and shift-j/k to do
the selection, much as shift-up/down (arrow keys) would alter
the selection.
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
All menu entries talk about "staging" and "unstaging" changes, but the
titles of the file lists use different wording, which may confuse
newcomers.
Signed-off-by: Johannes Sixt <johannes.sixt@telecom.at>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Since we support vi-like keys for scrolling in other UI contexts
we can easily do so here too. Tk's handy little `event generate'
makes this a lot easier than I thought it would be. We may want
to go back and fix some of the other vi-like bindings to redirect
to the arrow and pageup/pagedown keys, rather than running the
view changes directly.
I've bound 'v' to visualize, as this is a somewhat common thing
to want to do in the merge dialog. Control (or Command) Return
is also bound to start the merge, much as it is bound in the
main window to activate the commit.
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
When merging branches using our local merge feature it can be
handy to know the first few digits of the commit the ref points
at as well as the short description of the branch name.
Unfortunately I'm unable to use three listboxes in a row, as Tcl
freaks out and refuses to let me have a selection in more than
one of them at any given point in time. So instead we use a
fixed width font in the existing listbox and organize the data
into three columns. Not nearly as nice looking, but users can
continue to use the listbox's features.
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Johannes Sixt pointed out that git-gui was randomly selecting
which branch (or tag!) it will show in the merge dialog when
more than one ref points at the same commit. This can be a
problem for the user if they want to merge a branch, but the
ref that git-gui selected to display was actually a tag that
points at the commit at the tip of that branch. Since the
user is looking for the branch, and not the tag, its confusing
to not find it, and worse, merging the tag causes git-merge to
generate a different message than if the branch was selected.
While I am in here and am messing around I have changed the
for-each-ref usage to take advantage of its --tcl formatting,
and to fetch the subject line of the commit (or tag) we are
looking at. This way we could present the subject line in the
UI to the user, given them an even better chance to select
the correct branch.
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>