]> git.pld-linux.org Git - packages/tig.git/commitdiff
- up auto/ac/tig-0_12_1-1 auto/th/tig-0_12_1-1
authorAdam Gołębiowski <adamg@pld-linux.org>
Thu, 16 Oct 2008 08:03:29 +0000 (08:03 +0000)
committercvs2git <feedback@pld-linux.org>
Sun, 24 Jun 2012 12:13:13 +0000 (12:13 +0000)
Changed files:
    tig-git.patch -> 1.5

tig-git.patch

index 7767add161efffc8d68ee71bbc4cb01c727084d6..3c398b9a9cff94ba0caef4f52bdf9f37f40abf90 100644 (file)
-diff --git a/INSTALL b/INSTALL
-index 85662a3..3f6ff92 100644
---- a/INSTALL
-+++ b/INSTALL
-@@ -23,6 +23,10 @@ need to first make the configure script:
-       $ make configure
-+Release notes documenting notable changes are available in the NEWS file. When
-+upgrading, you are adviced to also read them after you have completed the
-+installation.
-+
- The following tools and packages are needed:
- `-------------------------------`----------------------------------------------
-diff --git a/Makefile b/Makefile
-index 575c5bf..1107f95 100644
---- a/Makefile
-+++ b/Makefile
-@@ -37,7 +37,7 @@ CFLAGS ?= -Wall -O2
- DFLAGS        = -g -DDEBUG -Werror
- PROGS = tig
- MANDOC        = tig.1 tigrc.5
--HTMLDOC = tig.1.html tigrc.5.html manual.html README.html
-+HTMLDOC = tig.1.html tigrc.5.html manual.html README.html NEWS.html
- ALLDOC        = $(MANDOC) $(HTMLDOC) manual.html-chunked manual.pdf
- # Never include the release number in the tarname for tagged
-@@ -99,8 +99,9 @@ clean:
-       $(RM) $(PROGS) core *.o *.xml
- distclean: clean
--      $(RM) -r manual.html-chunked *.toc $(ALLDOC)
--      $(RM) -r autom4te.cache aclocal.m4 config.{h,log,make,status} config.h.in configure
-+      $(RM) -r manual.html-chunked autom4te.cache
-+      $(RM) *.toc $(ALLDOC) aclocal.m4 configure
-+      $(RM) config.h config.log config.make config.status config.h.in
- spell-check:
-       aspell --lang=en --check tig.1.txt tigrc.5.txt manual.txt
-@@ -162,6 +163,9 @@ manual.toc: manual.txt
- README.html: README asciidoc.conf
-       $(ASCIIDOC) $(ASCIIDOC_FLAGS) -b xhtml11 -d article -a readme $<
-+NEWS.html: NEWS asciidoc.conf
-+      $(ASCIIDOC) $(ASCIIDOC_FLAGS) -b xhtml11 -d article $<
-+
- %.1.html : %.1.txt asciidoc.conf
-       $(ASCIIDOC) $(ASCIIDOC_FLAGS) -b xhtml11 -d manpage $<
 diff --git a/NEWS b/NEWS
-new file mode 100644
-index 0000000..d93fb04
---- /dev/null
+index 7e219af..a0f75c6 100644
+--- a/NEWS
 +++ b/NEWS
-@@ -0,0 +1,159 @@
-+Release notes
-+=============
-+
-+tig master branch
-+-----------------
+@@ -1,6 +1,21 @@
+ Release notes
+ =============
++tig master
++----------
 +
 +Improvements:
 +
-+ - F5 also refreshes the current view.
-+ - Allow line graphics to be disabled with new line-graphics option.
-+ - Main view: also include the reference names when searching.
-+ - Stage view: add stage-next action to jump to next diff chunk that can
-+   be staged. By default bound to '@'.
-+ - Configure: check for the ncurses header files.
-+ - Add author-width option to costumize the width of the author column.
-+   For example, put the following in ~/.tigrc: set author-width = 10
++ - Display repository references in the sorted order: tags, heads,
++   tracked remotes, remotes.
++ - Add bash completion for blame.
 +
 +Bug fixes:
 +
-+ - Fix regression when staging all diff chunks in a section.
-+ - Bind the maximize view action to 'O'; it conflicted with the
-+   keybinding to launch the merge tool in the status view.
-+ - Fix problem with $(cmd) usage in shell code. Some shells (jsh)
-+   installed as /bin/sh does not support it.
-+ - Do not show incomplete boundary commits when --no-walk is used.
-+ - Documentation: Rename gitlink macro to support AsciiDoc 8.2.3.
-+
-+tig-0.11
-+--------
++ - Separate blame revision and file argument by "--" to avoid problems.
++ - Main view: fix redrawing of the last commit wrt. the revision graph.
++ - Fix waiting for input after executing a run request in pager mode.
 +
-+Incompatibilities:
-+
-+ - Remove parsing of deprecated options: -g, -l, -d.
-+ - The first seen '--' will stop option parsing and is passed to git
-+   instead of breaking out of tig's option parsing.
+ tig-0.12.1
+ ----------
+diff --git a/contrib/tig-completion.bash b/contrib/tig-completion.bash
+index 79b414b..40bfcfa 100755
+--- a/contrib/tig-completion.bash
++++ b/contrib/tig-completion.bash
+@@ -182,6 +182,26 @@ _tig_options ()
+       __tig_complete_revlist
+ }
++_tig_blame ()
++{
++      local reply="" ref=HEAD cur="${COMP_WORDS[COMP_CWORD]}"
 +
-+New features:
++      if test "$COMP_CWORD" -lt 3; then
++              reply="$(__tig_refs)"
++      else
++              ref="${COMP_WORDS[2]}"
++      fi
++
++      reply="$reply $(git --git-dir="$(__tigdir)" ls-tree "$ref" \
++                      | sed '/^100... blob /s,^.*     ,,
++                             /^040000 tree /{
++                                 s,^.*        ,,
++                                 s,$,/,
++                             }
++                             s/^.*    //')"
++      _tigcomp "$reply"
++}
 +
-+ - Blame view; bound to 'B' by default, reachable from the command line
-+   and the tree, status, and stage views.
-+ - Blame/main view: allow display of date, author, and references to be
-+   toggled on/off. Bound to 'D', 'A', and 'F' respectively.
-+ - Add action to maximize the current view.
+ _tig_show ()
+ {
+       local cur="${COMP_WORDS[COMP_CWORD]}"
+@@ -218,12 +238,13 @@ _tig ()
+               case "${COMP_WORDS[COMP_CWORD]}" in
+               --*=*) COMPREPLY=() ;;
+               -*)   _tig_options ;;
+-              *)    _tigcomp "status show $(__tig_refs)" ;;
++              *)    _tigcomp "blame status show $(__tig_refs)" ;;
+               esac
+               return
+       fi
+       case "$command" in
++      blame)  _tig_blame ;;
+       show)   _tig_show ;;
+       status) ;;
+       *)      _tigcomp "
+diff --git a/manual.txt b/manual.txt
+index f11b77a..447dec0 100644
+--- a/manual.txt
++++ b/manual.txt
+@@ -44,7 +44,7 @@ given command and all will be shell quoted before they are passed to the
+ shell.
+ NOTE: If you specify options for the main view, you should not use the
+-`--pretty` option as this option will be set automatically to the format
++`\--pretty` option as this option will be set automatically to the format
+ expected by the main view.
+ Example on how to view a commit and show both author and committer
+@@ -54,100 +54,10 @@ information:
+ $ tig show --pretty=fuller
+ -----------------------------------------------------------------------------
+-See the <<refspec, "Specifying revisions">> section below for an introduction
+-to revision options supported by the git commands. For details on specific git
++See the section on <<refspec, specifying revisions>> for an introduction to
++revision options supported by the git commands. For details on specific git
+ command options, refer to the man page of the command in question.
+-[[env-variables]]
+-Environment Variables
+----------------------
+-
+-Several options related to the interface with git can be configured via
+-environment options.
+-
+-[[configuration-files]]
+-Configuration Files
+-~~~~~~~~~~~~~~~~~~~
+-
+-Upon startup, tig first reads the system wide configuration file
+-(`{sysconfdir}/tigrc` by default) and then proceeds to read the user's
+-configuration file (`~/.tigrc` by default). The paths to either of these files
+-can be overridden through the following environment variables:
+-
+-TIGRC_USER::
+-      Path of the user configuration file.
+-
+-TIGRC_SYSTEM::
+-      Path of the system wide configuration file.
+-
+-[[repo-refs]]
+-Repository References
+-~~~~~~~~~~~~~~~~~~~~~
+-
+-Commits that are referenced by tags and branch heads will be marked by the
+-reference name surrounded by '[' and ']':
+-
+------------------------------------------------------------------------------
+-2006-03-26 19:42 Petr Baudis         | [cogito-0.17.1] Cogito 0.17.1
+------------------------------------------------------------------------------
+-
+-If you want to filter out certain directories under `.git/refs/`, say `tmp`
+-you can do it by setting the following variable:
+-
+------------------------------------------------------------------------------
+-$ TIG_LS_REMOTE="git ls-remote . | sed /\/tmp\//d" tig
+------------------------------------------------------------------------------
+-
+-Or set the variable permanently in your environment.
+-
+-TIG_LS_REMOTE::
+-      Set command for retrieving all repository references. The command
+-      should output data in the same format as git-ls-remote(1).
+-
+-[[history-commands]]
+-History Commands
+-~~~~~~~~~~~~~~~~
+-
+-It is possible to alter which commands are used for the different views.  If
+-for example you prefer commits in the main view to be sorted by date and only
+-show 500 commits, use:
+-
+------------------------------------------------------------------------------
+-$ TIG_MAIN_CMD="git log --date-order -n500 --pretty=raw %s" tig
+------------------------------------------------------------------------------
+-
+-Or set the variable permanently in your environment.
+-
+-Notice, how `%s` is used to specify the commit reference. There can be a
+-maximum of 5 `%s` ref specifications.
+-
+-TIG_DIFF_CMD::
+-      The command used for the diff view. By default, git show is used
+-      as a backend.
+-
+-TIG_LOG_CMD::
+-      The command used for the log view. If you prefer to have both
+-      author and committer shown in the log view be sure to pass
+-      `--pretty=fuller` to git log.
+-
+-TIG_MAIN_CMD::
+-      The command used for the main view. Note, you must always specify
+-      the option: `--pretty=raw` since the main view parser expects to
+-      read that format.
+-
+-[[tree-commands]]
+-Tree Commands
+-~~~~~~~~~~~~~
+-
+-TIG_TREE_CMD::
+-      The command used for the tree view. Takes two arguments, the first
+-      is the revision ID and the second is the path of the directory tree,
+-      empty for the root directory. Defaults to "git ls-tree %s %s".
+-
+-TIG_BLOB_CMD::
+-      The command used for the blob view. Takes one argument which is
+-      the blob ID. Defaults to "git cat-file blob %s".
+-
+ [[viewer]]
+ The Viewer
+ ----------
+@@ -167,18 +77,6 @@ You will split the view so that the log view is displayed in the top window
+ and the diff view in the bottom window. You can switch between the two views
+ by pressing 'Tab'. To maximize the log view again, simply press 'l'.
+-[[commit-id]]
+-Current Head and Commit ID
+-~~~~~~~~~~~~~~~~~~~~~~~~~~
+-
+-The viewer keeps track of both what head and commit ID you are currently
+-viewing. The commit ID will follow the cursor line and change every time
+-you highlight a different commit. Whenever you reopen the diff view it will be
+-reloaded, if the commit ID changed.
+-
+-The head ID is used when opening the main and log view to indicate from what
+-revision to show history.
+-
+ [[views]]
+ Views
+ ~~~~~
+@@ -226,7 +124,30 @@ The pager view::
+       commands entered in the internal prompt.
+ The help view::
+-      Displays key binding quick reference.
++      Displays a quick reference of key bindings.
++
++[[commit-id]]
++Browsing State and User-defined Commands
++~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++
++The viewer keeps track of both what head and commit ID you are currently
++viewing. The commit ID will follow the cursor line and change every time you
++highlight a different commit. Whenever you reopen the diff view it will be
++reloaded, if the commit ID changed. The head ID is used when opening the main
++and log view to indicate from what revision to show history.
++
++Some of the commands used or provided by tig can be configured. This goes for
++the <<external-commands, external commands>>. These user-defined commands can
++use arguments that refer to the current browsing state by using one of the
++following variables.
++
++`-----------------------`-----------------------------------------------------
++Browsing state variables
++------------------------------------------------------------------------------
++%(head)                       The currently viewed 'head' ID. Defaults to HEAD
++%(commit)             The currently selected commit ID.
++%(blob)                       The currently selected blob ID.
++------------------------------------------------------------------------------
+ [[title-window]]
+ Title Windows
+@@ -247,6 +168,134 @@ be appended:
+ [main] 77d9e40fbcea3238015aea403e06f61542df9a31 - commit 1 of 779 (0%) 5s
+ -----------------------------------------------------------------------------
++[[env-variables]]
++Environment Variables
++---------------------
 +
-+Improvements:
++Several options related to the interface with git can be configured via
++environment options.
 +
-+ - Show the current branch in the status view.
-+ - Show local/light-weight tags.
++[[configuration-files]]
++Configuration Files
++~~~~~~~~~~~~~~~~~~~
 +
-+Bug fixes:
++Upon startup, tig first reads the system wide configuration file
++(`{sysconfdir}/tigrc` by default) and then proceeds to read the user's
++configuration file (`~/.tigrc` by default). The paths to either of these files
++can be overridden through the following environment variables:
 +
-+ - Fix regressions for the pager mode.
-+ - Fix refreshing of the index with working directory info.
++TIGRC_USER::
++      Path of the user configuration file.
 +
-+tig-0.10.1
-+----------
++TIGRC_SYSTEM::
++      Path of the system wide configuration file.
 +
-+Improvements:
++[[repo-refs]]
++Repository References
++~~~~~~~~~~~~~~~~~~~~~
 +
-+ - Status view: detect renamed files and show them with 'R'.
-+ - Status view: refresh the index to avoid "empty diffs".
-+ - Diff view: make diff headers more verbose to include e.g. committer.
-+ - Configure: check for the ncursesw library.
++Commits that are referenced by tags and branch heads will be marked by the
++reference name surrounded by '[' and ']':
 +
-+Bug fixes:
++-----------------------------------------------------------------------------
++2006-03-26 19:42 Petr Baudis         | [cogito-0.17.1] Cogito 0.17.1
++-----------------------------------------------------------------------------
 +
-+ - Fix UTF8 handling for tag names and commit messages.
-+ - Fix the check for git-config(1) in configure to handle the case when
-+   git has been installed using a libexecdir which is not in the path.
-+ - Fix replacing of SYSCONFDIR when installing from released tarballs.
++If you want to filter what branches gets shown, say limit to only show
++branches named `master` or which starts with the `jf/` prefix, you can
++do it by setting the following variable:
 +
-+tig-0.10
-+---------
++-----------------------------------------------------------------------------
++$ TIG_LS_REMOTE="git ls-remote . master jf/*" tig
++-----------------------------------------------------------------------------
 +
-+Incompatibilities:
++Or set the variable permanently in your environment.
 +
-+ - Deprecate most tig specific command line options to make tig more
-+   compatible with gitk. The deprecated options are: -g, -l, -d, and -S.
-+   Use of any of them will result in a warning being printed to stderr.
-+   Instead of '-S', use the new 'status' subcommand.
-+ - Make man page building depend on DocBook XSL version >= 1.72.0.
-+ - Install man pages in $(prefix)/share/man.
-+ - Implement the cherry pick action (bound to 'C') using new support for
-+   running external commands. This obsoletes the TIG_CHEERY_PICK
-+   environment variable
++--
 +
-+New features:
++TIG_LS_REMOTE::
 +
-+ - Add support for binding keys to external commands. To bind '.' to
-+   running git-commit(1), add the line: "bind generic . !git commit" to
-+   your ~/.tigrc. Each command can have replacement string such as
-+   %(commit), %(head), and %(blob), which are substituted before the
-+   command is run.
-+ - Add system-wide configuration file defaulting to $(prefix)/etc/tigrc.
-+ - Add the environment variables TIGRC_USER and TIGRC_SYSTEM to change
-+   user and system-wide configuration files, respectively.
++      Set command for retrieving all repository references. The command
++      should output data in the same format as git-ls-remote(1). Defaults
++      to:
++-----------------------------------------------------------------------------
++git ls-remote .
++-----------------------------------------------------------------------------
 +
-+Improvements:
++--
 +
-+ - Main view: color the revision graph.
-+ - Main view: show boundary commits; they are marked with '^' in the
-+   revision graph.
-+ - Tree view: add tree-parent action to jump to view of the parent tree.
-+   Bound to ',' by default.
-+ - Allow the default terminal colors to be overwritten. To use black
-+   text on white, add the line "color default white black" to your
-+   ~/.tigrc.
-+ - Misc. documentation improvements.
++[[history-commands]]
++History Commands
++~~~~~~~~~~~~~~~~
 +
-+Bug fixes:
++It is possible to alter which commands are used for the different views.  If
++for example you prefer commits in the main view to be sorted by date and only
++show 500 commits, use:
 +
-+ - Use git-diff-index(1) and git-diff-files(1) instead of git-diff(1) to
-+   avoid running external diff drivers.
-+ - Use --no-color when calling git-log(1).
-+ - Fix crash when opening mergetool for lines that are not unmerged.
++-----------------------------------------------------------------------------
++$ TIG_MAIN_CMD="git log --date-order -n500 --pretty=raw %s" tig
++-----------------------------------------------------------------------------
 +
-+tig-0.9.1
-+---------
++Or set the variable permanently in your environment.
 +
-+Incompatibilities:
++Notice, how `%s` is used to specify the commit reference. There can be a
++maximum of 5 `%s` ref specifications.
 +
-+ - Make the clean rule to never remove generated documentation files.
-+   Use the distclean rule for accomplishing this.
++--
 +
-+New features:
++TIG_DIFF_CMD::
 +
-+ - Add support for cherry-picking commits in the main view to the
-+   current branch. Bound to 'C' by default.
++      The command used for the diff view. Defaults to:
++-----------------------------------------------------------------------------
++git show --pretty=fuller --no-color --root 
++       --patch-with-stat --find-copies-harder -C %s
++-----------------------------------------------------------------------------
 +
-+Improvements:
++TIG_LOG_CMD::
 +
-+ - Add support for launching git-mergetool(1) from the status view.
-+   Bound to 'M' by default.
-+ - Add support for refreshing/reloading the status view
-+ - Detect working trees and disable the status view when it is missing.
++      The command used for the log view. If you prefer to have both
++      author and committer shown in the log view be sure to pass
++      `\--pretty=fuller` to git log. Defaults to:
++-----------------------------------------------------------------------------
++git log --no-color --cc --stat -n100 %s
++-----------------------------------------------------------------------------
 +
-+Bug fixes:
++TIG_MAIN_CMD::
 +
-+ - Fix iconv() checking in configure.
-+ - Fix editor invocation to make paths relative to the project root.
-+ - Fix out-of-range current line when reloading the status view.
-+ - Include autoconf files in the tarball generated by `make dist`.
++      The command used for the main view. Note, you must always specify
++      the option: `\--pretty=raw` since the main view parser expects to
++      read that format.
++-----------------------------------------------------------------------------
++git log --no-color --pretty=raw --parents --topo-order %s
++-----------------------------------------------------------------------------
 +
-+tig-0.9
-+-------
++--
 +
-+New features:
++[[tree-commands]]
++Tree Commands
++~~~~~~~~~~~~~
 +
-+ - Add bash completion script for tig (contrib/tig-completion.bash).
-+ - Add optional autoconf-based build infrastructure.
-+ - Add stage view for showing changes in the working tree and add
-+   support for staging individual diff chunks for commit.
++--
 +
-+Improvements:
++TIG_TREE_CMD::
 +
-+ - Status view: allow all files in a section to be staged for commit.
-+ - Status view: Add support for opening files in an editor. Bound to 'e'
-+   by default.
-+ - Tree view: use a stack for remembering the lines for parent tree.
-diff --git a/TODO b/TODO
-index 437f0d4..919734a 100644
---- a/TODO
-+++ b/TODO
-@@ -28,3 +28,6 @@ Features that should be explored.
-  - Color the revgraph to make it easier to follow branches. Idea by
-    Dominik Vogt
++      The command used for the tree view. Takes two arguments, the first is
++      the revision ID and the second is the path of the directory tree,
++      empty for the root directory. Defaults to:
++-----------------------------------------------------------------------------
++git ls-tree %s %s
++-----------------------------------------------------------------------------
 +
-+ - Allow names in the author column to be abbreviated to initials.
-+   Will optimize screen usage for the blame view.
-diff --git a/asciidoc.conf b/asciidoc.conf
-index 630552c..90fdb6a 100644
---- a/asciidoc.conf
-+++ b/asciidoc.conf
-@@ -1,5 +1,5 @@
- ifdef::backend-docbook[]
--[gitlink-inlinemacro]
-+[manpage-inlinemacro]
- {0%{target}}
- {0#<citerefentry>}
- {0#<refentrytitle>{target}</refentrytitle><manvolnum>{0}</manvolnum>}
-@@ -7,7 +7,7 @@ ifdef::backend-docbook[]
- endif::backend-docbook[]
- ifdef::backend-xhtml11[]
--[gitlink-inlinemacro]
-+[manpage-inlinemacro]
- <a href="{target}{0?.{0}}.html">{target}{0?({0})}</a>
- endif::backend-xhtml11[]
-@@ -56,4 +56,7 @@ ifdef::readme[]
- [footer]
- </div>
++TIG_BLOB_CMD::
 +
-+[replacements]
-+(^|[^-\\])--($|[^-])=\1--\2
- endif::readme[]
-diff --git a/configure.ac b/configure.ac
-index 764190a..6b0fc45 100644
---- a/configure.ac
-+++ b/configure.ac
-@@ -1,13 +1,23 @@
--AC_INIT([tig], [0],
--      [Jonas Fonseca <fonseca@diku.dk>],
--      [tig])
-+AC_INIT([tig], [0], [Jonas Fonseca <fonseca@diku.dk>], [tig])
- AC_LANG([C])
- AC_CONFIG_HEADER(config.h)
- AC_CONFIG_SRCDIR(tig.c)
--AC_SEARCH_LIBS([wclear], [ncursesw ncurses curses], [],
--             [AC_ERROR([curses not found])])
-+cursed=no
-+AC_CHECK_HEADERS([ncursesw/ncurses.h],
-+               [AC_SEARCH_LIBS([initscr], [ncursesw], [cursed=yes])])
-+case "$cursed" in "no")
-+      AC_CHECK_HEADERS([ncurses/ncurses.h ncurses.h],
-+                       [AC_SEARCH_LIBS([wclear], [ncurses], [cursed=yes])])
++      The command used for the blob view. Takes one argument which is the
++      blob ID. Defaults to:
++-----------------------------------------------------------------------------
++git cat-file blob %s
++-----------------------------------------------------------------------------
 +
-+      case "$cursed" in "no")
-+              AC_ERROR([ncurses not found])
-+      esac
++--
 +
-+      AC_MSG_WARN([The found ncurses library does not support wide-char.])
-+      AC_MSG_WARN([This means that tig will not correctly render UTF-8.])
-+esac
+ [[keys]]
+ Default Keybindings
+ -------------------
+@@ -377,9 +426,10 @@ e Open file in editor.
+ External Commands
+ ~~~~~~~~~~~~~~~~~
+-Tig also comes with a few builtin external commands. These are simple shell
+-commands that are run and can take arguments from the current browsing state,
+-such as the current commit ID. The default commands are:
++For more custom needs, external commands provide a way to easily execute
++a script or program. They are bound to keys and use information from the
++current browsing state, such as the current commit ID. Tig comes with
++the following builtin external commands:
  
- AM_ICONV
+ `-------`--------------------------------------------------------------------
+ Key   Action
+@@ -400,7 +450,7 @@ git-rev-list(1).
  
-@@ -26,9 +36,3 @@ AC_CHECK_PROGS(DOCBOOK2PDF, [docbook2pdf false])
+ You can tune the interaction with git by making use of the options explained
+ in this section. For example, by configuring the environment variables
+-described in the  <<history-commands, "History commands">> section.
++described in the section on <<history-commands, history commands>>.
  
- AC_CONFIG_FILES([config.make])
- AC_OUTPUT
+ [[path-limiting]]
+ Limit by Path Name
+@@ -422,17 +472,13 @@ thus you will have to use:
+ $ tig -- status
+ -----------------------------------------------------------------------------
+-NOTE: For the main view, avoiding ambiguity will in some cases require you to
+-specify two "\--" options. The first will make tig stop option processing
+-and the latter will be passed to git log.
 -
--case "$LIBS" in
--*-lncursesw*) ;;
--*) AC_MSG_RESULT([NOTE: The found ncurses library does not support wide-char.])
--   AC_MSG_RESULT([NOTE: This means that tig will not correctly render UTF-8])
--esac
-diff --git a/manual.txt b/manual.txt
-index e4f937a..3157eb3 100644
---- a/manual.txt
-+++ b/manual.txt
-@@ -366,6 +366,7 @@ u  Update status of file. In the status view, this allows you to add an \
- M     Resolve unmerged file by launching git-mergetool(1). Note, to work \
-       correctly this might require some initial configuration of your \
-       preferred merge tool. See the manpage of git-mergetool(1).
-+@     Move to next chunk in the stage view.
- ','   Move tree view to the parent tree.
- e     Open file in editor.
+ [[date-number-limiting]]
+ Limit by Date or Number
+ ~~~~~~~~~~~~~~~~~~~~~~~
+ To speed up interaction with git, you can limit the amount of commits to show
+ both for the log and main view. Either limit by date using e.g.
+-`--since=1.month` or limit by the number of commits using `-n400`.
++`\--since=1.month` or limit by the number of commits using `-n400`.
+ If you are only interested in changed that happened between two dates you can
+ use:
+@@ -442,7 +488,7 @@ $ tig --after="May 5th" --before="2006-05-16 15:44"
  -----------------------------------------------------------------------------
-@@ -526,8 +527,8 @@ References and Related Tools
- Manpages:
-- - gitlink:tig[1]
-- - gitlink:tigrc[5]
-+ - manpage:tig[1]
-+ - manpage:tigrc[5]
- Online resources:
-diff --git a/tig.1.txt b/tig.1.txt
-index ee96a97..6a7e266 100644
---- a/tig.1.txt
-+++ b/tig.1.txt
-@@ -135,7 +135,7 @@ TIG_BLOB_CMD::
- FILES
- -----
- '~/.tigrc'::
--      User configuration file. See gitlink:tigrc[5] for examples.
-+      User configuration file. See manpage:tigrc[5] for examples.
- '{sysconfdir}/tigrc'::
-       System wide configuration file.
-@@ -158,7 +158,7 @@ the Free Software Foundation; either version 2 of the License, or
- SEE ALSO
- --------
--gitlink:tigrc[5], git(7), cogito(7), as well as other git repository browsers:
-+manpage:tigrc[5], git(7), cogito(7), as well as other git repository browsers:
- gitk(1), qgit(1), gitview(1).
- Online resources:
+ NOTE: If you want to avoid having to quote dates containing spaces you can use
+-"." instead, e.g. `--after=May.5th`.
++"." instead, e.g. `\--after=May.5th`.
+ [[commit-range-limiting]]
+ Limiting by Commit Ranges
 diff --git a/tig.c b/tig.c
-index 5280da8..8362ecf 100644
+index 5c456e7..3394d40 100644
 --- a/tig.c
 +++ b/tig.c
-@@ -45,7 +45,15 @@
- /* ncurses(3): Must be defined to have extended wide-character functions. */
- #define _XOPEN_SOURCE_EXTENDED
--#include <curses.h>
-+#ifdef HAVE_NCURSESW_NCURSES_H
-+#include <ncursesw/ncurses.h>
-+#else
-+#ifdef HAVE_NCURSES_NCURSES_H
-+#include <ncurses/ncurses.h>
-+#else
-+#include <ncurses.h>
-+#endif
-+#endif
- #if __GNUC__ >= 3
- #define __NORETURN __attribute__((__noreturn__))
-@@ -58,7 +66,7 @@ static void warn(const char *msg, ...);
- static void report(const char *msg, ...);
- static int read_properties(FILE *pipe, const char *separators, int (*read)(char *, size_t, char *, size_t));
- static void set_nonblocking_input(bool loading);
--static size_t utf8_length(const char *string, size_t max_width, int *trimmed, bool reserve);
-+static size_t utf8_length(const char *string, int *width, size_t max_width, int *trimmed, bool reserve);
- #define ABS(x)                ((x) >= 0  ? (x) : -(x))
- #define MIN(x, y)     ((x) < (y) ? (x) :  (y))
-@@ -77,7 +85,6 @@ static size_t utf8_length(const char *string, size_t max_width, int *trimmed, bo
- #define REVGRAPH_BRANCH       '+'
- #define REVGRAPH_COMMIT       '*'
- #define REVGRAPH_BOUND        '^'
--#define REVGRAPH_LINE '|'
- #define SIZEOF_REVGRAPH       19      /* Size of revision ancestry graphics. */
-@@ -99,7 +106,7 @@ static size_t utf8_length(const char *string, size_t max_width, int *trimmed, bo
- /* The default interval between line numbers. */
- #define NUMBER_INTERVAL       5
--#define TABSIZE               8
-+#define TAB_SIZE      8
- #define       SCALE_SPLIT_VIEW(height)        ((height) * 2 / 3)
-@@ -110,7 +117,7 @@ static size_t utf8_length(const char *string, size_t max_width, int *trimmed, bo
- #endif
- #define TIG_LS_REMOTE \
--      "git ls-remote $(git rev-parse --git-dir) 2>/dev/null"
-+      "git ls-remote . 2>/dev/null"
- #define TIG_DIFF_CMD \
-       "git show --pretty=fuller --no-color --root --patch-with-stat --find-copies-harder -C %s 2>/dev/null"
-@@ -369,6 +376,7 @@ sq_quote(char buf[SIZEOF_STR], size_t bufsize, const char *src)
-       REQ_(TOGGLE_REFS,       "Toggle reference display (tags/branches)"), \
-       REQ_(STATUS_UPDATE,     "Update file status"), \
-       REQ_(STATUS_MERGE,      "Merge file using external tool"), \
-+      REQ_(STAGE_NEXT,        "Find next chunk to stage"), \
-       REQ_(TREE_PARENT,       "Switch to parent directory in tree view"), \
-       REQ_(EDIT,              "Open in editor"), \
-       REQ_(NONE,              "Do nothing")
-@@ -438,11 +446,12 @@ static const char usage[] =
- static bool opt_date                  = TRUE;
- static bool opt_author                        = TRUE;
- static bool opt_line_number           = FALSE;
-+static bool opt_line_graphics         = TRUE;
- static bool opt_rev_graph             = FALSE;
- static bool opt_show_refs             = TRUE;
- static int opt_num_interval           = NUMBER_INTERVAL;
--static int opt_tab_size                       = TABSIZE;
--static enum request opt_request               = REQ_VIEW_MAIN;
-+static int opt_tab_size                       = TAB_SIZE;
-+static int opt_author_cols            = AUTHOR_COLS-1;
- static char opt_cmd[SIZEOF_STR]               = "";
- static char opt_path[SIZEOF_STR]      = "";
- static char opt_file[SIZEOF_STR]      = "";
-@@ -461,34 +470,32 @@ static char opt_git_dir[SIZEOF_STR]      = "";
+@@ -164,7 +164,7 @@ struct ref {
+       unsigned int next:1;    /* For ref lists: are there more refs? */
+ };
+-static struct ref **get_refs(char *id);
++static struct ref **get_refs(const char *id);
+ struct int_map {
+       const char *name;
+@@ -277,6 +277,9 @@ string_enum_compare(const char *str1, const char *str2, int len)
+       return 0;
+ }
++#define prefixcmp(str1, str2) \
++      strncmp(str1, str2, STRING_SIZE(str2))
++
+ /* Shell quoting
+  *
+  * NOTE: The following is a slightly modified copy of the git project's shell
+@@ -408,9 +411,9 @@ enum request {
+ struct request_info {
+       enum request request;
+-      char *name;
++      const char *name;
+       int namelen;
+-      char *help;
++      const char *help;
+ };
+ static struct request_info req_info[] = {
+@@ -480,13 +483,14 @@ static char opt_cdup[SIZEOF_STR] = "";
+ static char opt_git_dir[SIZEOF_STR]   = "";
  static signed char opt_is_inside_work_tree    = -1; /* set to TRUE or FALSE */
  static char opt_editor[SIZEOF_STR]    = "";
++static FILE *opt_tty                  = NULL;
  
--static bool
-+static enum request
- parse_options(int argc, char *argv[])
+ static enum request
+-parse_options(int argc, char *argv[])
++parse_options(int argc, const char *argv[])
  {
-+      enum request request = REQ_VIEW_MAIN;
+       enum request request = REQ_VIEW_MAIN;
        size_t buf_size;
-       char *subcommand;
+-      char *subcommand;
++      const char *subcommand;
        bool seen_dashdash = FALSE;
        int i;
  
-       if (!isatty(STDIN_FILENO)) {
--              opt_request = REQ_VIEW_PAGER;
-               opt_pipe = stdin;
--              return TRUE;
-+              return REQ_VIEW_PAGER;
-       }
+@@ -540,7 +544,7 @@ parse_options(int argc, char *argv[])
+       buf_size = strlen(opt_cmd);
  
-       if (argc <= 1)
--              return TRUE;
-+              return REQ_VIEW_MAIN;
-       subcommand = argv[1];
-       if (!strcmp(subcommand, "status") || !strcmp(subcommand, "-S")) {
--              opt_request = REQ_VIEW_STATUS;
-               if (!strcmp(subcommand, "-S"))
-                       warn("`-S' has been deprecated; use `tig status' instead");
-               if (argc > 2)
-                       warn("ignoring arguments after `%s'", subcommand);
--              return TRUE;
-+              return REQ_VIEW_STATUS;
-       } else if (!strcmp(subcommand, "blame")) {
--              opt_request = REQ_VIEW_BLAME;
-               if (argc <= 2 || argc > 4)
-                       die("invalid number of options to blame\n\n%s", usage);
-@@ -499,14 +506,13 @@ parse_options(int argc, char *argv[])
-               }
-               string_ncopy(opt_file, argv[i], strlen(argv[i]));
--              return TRUE;
-+              return REQ_VIEW_BLAME;
-       } else if (!strcmp(subcommand, "show")) {
--              opt_request = REQ_VIEW_DIFF;
-+              request = REQ_VIEW_DIFF;
+       for (i = 1 + !!subcommand; i < argc; i++) {
+-              char *opt = argv[i];
++              const char *opt = argv[i];
  
-       } else if (!strcmp(subcommand, "log") || !strcmp(subcommand, "diff")) {
--              opt_request = subcommand[0] == 'l'
--                          ? REQ_VIEW_LOG : REQ_VIEW_DIFF;
-+              request = subcommand[0] == 'l' ? REQ_VIEW_LOG : REQ_VIEW_DIFF;
-               warn("`tig %s' has been deprecated", subcommand);
+               if (seen_dashdash || !strcmp(opt, "--")) {
+                       seen_dashdash = TRUE;
+@@ -867,7 +871,7 @@ get_keybinding(enum keymap keymap, int key)
  
-       } else {
-@@ -530,11 +536,11 @@ parse_options(int argc, char *argv[])
-               } else if (!strcmp(opt, "-v") || !strcmp(opt, "--version")) {
-                       printf("tig version %s\n", TIG_VERSION);
--                      return FALSE;
-+                      return REQ_NONE;
  
-               } else if (!strcmp(opt, "-h") || !strcmp(opt, "--help")) {
-                       printf("%s\n", usage);
--                      return FALSE;
-+                      return REQ_NONE;
-               }
-               opt_cmd[buf_size++] = ' ';
-@@ -545,7 +551,7 @@ parse_options(int argc, char *argv[])
-       opt_cmd[buf_size] = 0;
+ struct key {
+-      char *name;
++      const char *name;
+       int value;
+ };
  
--      return TRUE;
-+      return request;
+@@ -917,11 +921,11 @@ get_key_value(const char *name)
+       return ERR;
  }
  
-@@ -612,7 +618,8 @@ LINE(BLAME_ID,     "",                     COLOR_MAGENTA,  COLOR_DEFAULT,  0)
- enum line_type {
- #define LINE(type, line, fg, bg, attr) \
-       LINE_##type
--      LINE_INFO
-+      LINE_INFO,
-+      LINE_NONE
- #undef        LINE
- };
-@@ -731,7 +738,8 @@ static struct keybinding default_keybindings[] = {
-       { KEY_UP,       REQ_PREVIOUS },
-       { KEY_DOWN,     REQ_NEXT },
-       { 'R',          REQ_REFRESH },
--      { 'M',          REQ_MAXIMIZE },
-+      { KEY_F(5),     REQ_REFRESH },
-+      { 'O',          REQ_MAXIMIZE },
-       /* Cursor navigation */
-       { 'k',          REQ_MOVE_UP },
-@@ -769,6 +777,7 @@ static struct keybinding default_keybindings[] = {
-       { ':',          REQ_PROMPT },
-       { 'u',          REQ_STATUS_UPDATE },
-       { 'M',          REQ_STATUS_MERGE },
-+      { '@',          REQ_STAGE_NEXT },
-       { ',',          REQ_TREE_PARENT },
-       { 'e',          REQ_EDIT },
-@@ -954,22 +963,23 @@ static size_t run_requests;
- static enum request
- add_run_request(enum keymap keymap, int key, int argc, char **argv)
+-static char *
++static const char *
+ get_key_name(int key_value)
  {
--      struct run_request *tmp;
--      struct run_request req = { keymap, key };
-+      struct run_request *req;
-+      char cmd[SIZEOF_STR];
-       size_t bufpos;
-       for (bufpos = 0; argc > 0; argc--, argv++)
--              if (!string_format_from(req.cmd, &bufpos, "%s ", *argv))
-+              if (!string_format_from(cmd, &bufpos, "%s ", *argv))
-                       return REQ_NONE;
--      req.cmd[bufpos - 1] = 0;
--
--      tmp = realloc(run_request, (run_requests + 1) * sizeof(*run_request));
--      if (!tmp)
-+      req = realloc(run_request, (run_requests + 1) * sizeof(*run_request));
-+      if (!req)
-               return REQ_NONE;
--      run_request = tmp;
--      run_request[run_requests++] = req;
-+      run_request = req;
-+      req = &run_request[run_requests++];
-+      string_copy(req->cmd, cmd);
-+      req->keymap = keymap;
-+      req->key = key;
-       return REQ_NONE + run_requests;
+       static char key_char[] = "'X'";
+-      char *seq = NULL;
++      const char *seq = NULL;
+       int key;
+       for (key = 0; key < ARRAY_SIZE(key_table); key++)
+@@ -938,7 +942,7 @@ get_key_name(int key_value)
+       return seq ? seq : "(no key)";
  }
-@@ -1087,6 +1097,14 @@ static bool parse_bool(const char *s)
-               !strcmp(s, "yes")) ? TRUE : FALSE;
- }
-+static int
-+parse_int(const char *s, int default_value, int min, int max)
-+{
-+      int value = atoi(s);
-+
-+      return (value < min || value > max) ? default_value : value;
-+}
-+
- /* Wants: name = value */
- static int
- option_set_command(int argc, char *argv[])
-@@ -1126,13 +1144,23 @@ option_set_command(int argc, char *argv[])
-               return OK;
-       }
  
-+      if (!strcmp(argv[0], "line-graphics")) {
-+              opt_line_graphics = parse_bool(argv[2]);
-+              return OK;
-+      }
-+
-       if (!strcmp(argv[0], "line-number-interval")) {
--              opt_num_interval = atoi(argv[2]);
-+              opt_num_interval = parse_int(argv[2], opt_num_interval, 1, 1024);
-+              return OK;
-+      }
-+
-+      if (!strcmp(argv[0], "author-width")) {
-+              opt_author_cols = parse_int(argv[2], opt_author_cols, 0, 1024);
-               return OK;
-       }
-       if (!strcmp(argv[0], "tab-size")) {
--              opt_tab_size = atoi(argv[2]);
-+              opt_tab_size = parse_int(argv[2], opt_tab_size, 1, 1024);
-               return OK;
-       }
-@@ -1391,6 +1419,11 @@ struct view {
-       size_t line_size;       /* Total number of used lines */
-       unsigned int digits;    /* Number of digits in the lines member. */
-+      /* Drawing */
-+      struct line *curline;   /* Line currently being drawn. */
-+      enum line_type curtype; /* Attribute currently used for drawing. */
-+      unsigned long col;      /* Column when drawing. */
-+
-       /* Loading */
-       FILE *pipe;
-       time_t start_time;
-@@ -1404,7 +1437,7 @@ struct view_ops {
-       /* Read one line; updates view->line. */
-       bool (*read)(struct view *view, char *data);
-       /* Draw one line; @lineno must be < view->height. */
--      bool (*draw)(struct view *view, struct line *line, unsigned int lineno, bool selected);
-+      bool (*draw)(struct view *view, struct line *line, unsigned int lineno);
-       /* Depending on view handle a special requests. */
-       enum request (*request)(struct view *view, enum request request, struct line *line);
-       /* Search for regex in a line. */
-@@ -1451,107 +1484,175 @@ static struct view views[] = {
- #define view_is_displayed(view) \
-       (view == display[0] || view == display[1])
-+
-+enum line_graphic {
-+      LINE_GRAPHIC_VLINE
-+};
-+
-+static int line_graphics[] = {
-+      /* LINE_GRAPHIC_VLINE: */ '|'
-+};
-+
-+static inline void
-+set_view_attr(struct view *view, enum line_type type)
-+{
-+      if (!view->curline->selected && view->curtype != type) {
-+              wattrset(view->win, get_line_attr(type));
-+              wchgat(view->win, -1, 0, type, NULL);
-+              view->curtype = type;
-+      }
-+}
-+
- static int
--draw_text(struct view *view, const char *string, int max_len,
--        bool use_tilde, bool selected)
-+draw_chars(struct view *view, enum line_type type, const char *string,
-+         int max_len, bool use_tilde)
+-static char *
++static const char *
+ get_key(enum request request)
  {
-       int len = 0;
-+      int col = 0;
-       int trimmed = FALSE;
-       if (max_len <= 0)
-               return 0;
+       static char buf[BUFSIZ];
+@@ -1062,7 +1066,7 @@ static struct int_map attr_map[] = {
  
-       if (opt_utf8) {
--              len = utf8_length(string, max_len, &trimmed, use_tilde);
-+              len = utf8_length(string, &col, max_len, &trimmed, use_tilde);
-       } else {
--              len = strlen(string);
-+              col = len = strlen(string);
-               if (len > max_len) {
-                       if (use_tilde) {
-                               max_len -= 1;
-                       }
--                      len = max_len;
-+                      col = len = max_len;
-                       trimmed = TRUE;
-               }
-       }
+ static int   config_lineno;
+ static bool  config_errors;
+-static char *config_msg;
++static const char *config_msg;
  
-+      set_view_attr(view, type);
-       waddnstr(view->win, string, len);
-       if (trimmed && use_tilde) {
--              if (!selected)
--                      wattrset(view->win, get_line_attr(LINE_DELIMITER));
-+              set_view_attr(view, LINE_DELIMITER);
-               waddch(view->win, '~');
--              len++;
-+              col++;
-       }
--      return len;
-+      return col;
+ /* Wants: object fgcolor bgcolor [attr] */
+ static int
+@@ -1249,7 +1253,7 @@ option_bind_command(int argc, const char *argv[])
  }
  
  static int
--draw_lineno(struct view *view, unsigned int lineno, int max, bool selected)
-+draw_space(struct view *view, enum line_type type, int max, int spaces)
-+{
-+      static char space[] = "                    ";
-+      int col = 0;
-+
-+      spaces = MIN(max, spaces);
-+
-+      while (spaces > 0) {
-+              int len = MIN(spaces, sizeof(space) - 1);
-+
-+              col += draw_chars(view, type, space, spaces, FALSE);
-+              spaces -= len;
-+      }
-+
-+      return col;
-+}
-+
-+static bool
-+draw_lineno(struct view *view, unsigned int lineno)
+-set_option(char *opt, char *value)
++set_option(const char *opt, char *value)
  {
--      static char fmt[] = "%1ld";
--      char number[10] = "          ";
-+      char number[10];
-       int digits3 = view->digits < 3 ? 3 : view->digits;
-       int max_number = MIN(digits3, STRING_SIZE(number));
--      bool showtrimmed = FALSE;
-+      int max = view->width - view->col;
-       int col;
-+      if (max < max_number)
-+              max_number = max;
-+
-       lineno += view->offset + 1;
-       if (lineno == 1 || (lineno % opt_num_interval) == 0) {
-+              static char fmt[] = "%1ld";
-+
-               if (view->digits <= 9)
-                       fmt[1] = '0' + digits3;
-               if (!string_format(number, fmt, lineno))
-                       number[0] = 0;
--              showtrimmed = TRUE;
-+              col = draw_chars(view, LINE_LINE_NUMBER, number, max_number, TRUE);
-+      } else {
-+              col = draw_space(view, LINE_LINE_NUMBER, max_number, max_number);
-       }
--      if (max < max_number)
--              max_number = max;
--
--      if (!selected)
--              wattrset(view->win, get_line_attr(LINE_LINE_NUMBER));
--      col = draw_text(view, number, max_number, showtrimmed, selected);
-       if (col < max) {
--              if (!selected)
--                      wattrset(view->win, A_NORMAL);
--              waddch(view->win, ACS_VLINE);
-+              set_view_attr(view, LINE_DEFAULT);
-+              waddch(view->win, line_graphics[LINE_GRAPHIC_VLINE]);
-               col++;
-       }
--      if (col < max) {
-+
-+      if (col < max)
-+              col += draw_space(view, LINE_DEFAULT, max - col, 1);
-+      view->col += col;
-+
-+      return view->width - view->col <= 0;
-+}
-+
-+static bool
-+draw_text(struct view *view, enum line_type type, const char *string, bool trim)
-+{
-+      view->col += draw_chars(view, type, string, view->width - view->col, trim);
-+      return view->width - view->col <= 0;
-+}
-+
-+static bool
-+draw_graphic(struct view *view, enum line_type type, chtype graphic[], size_t size)
-+{
-+      int max = view->width - view->col;
-+      int i;
-+
-+      if (max < size)
-+              size = max;
-+
-+      set_view_attr(view, type);
-+      /* Using waddch() instead of waddnstr() ensures that
-+       * they'll be rendered correctly for the cursor line. */
-+      for (i = 0; i < size; i++)
-+              waddch(view->win, graphic[i]);
-+
-+      view->col += size;
-+      if (size < max) {
-               waddch(view->win, ' ');
--              col++;
-+              view->col++;
-       }
--      return col;
-+      return view->width - view->col <= 0;
- }
--static int
--draw_date(struct view *view, struct tm *time, int max, bool selected)
-+static bool
-+draw_field(struct view *view, enum line_type type, char *text, int len, bool trim)
+       const char *argv[SIZEOF_ARG];
+       int valuelen;
+@@ -1343,9 +1347,9 @@ load_option_file(const char *path)
+ static int
+ load_options(void)
  {
--      char buf[DATE_COLS];
-+      int max = MIN(view->width - view->col, len);
-       int col;
-+
-+      if (text)
-+              col = draw_chars(view, type, text, max - 1, trim);
-+      else
-+              col = draw_space(view, type, max - 1, max - 1);
-+
-+      view->col += col + draw_space(view, LINE_DEFAULT, max - col, max - col);
-+      return view->width - view->col <= 0;
-+}
-+
-+static bool
-+draw_date(struct view *view, struct tm *time)
-+{
-+      char buf[DATE_COLS];
-+      char *date;
-       int timelen = 0;
--      if (max > DATE_COLS)
--              max = DATE_COLS;
-       if (time)
-               timelen = strftime(buf, sizeof(buf), DATE_FORMAT, time);
--      if (!timelen) {
--              memset(buf, ' ', sizeof(buf) - 1);
--              buf[sizeof(buf) - 1] = 0;
--      }
-+      date = timelen ? buf : NULL;
--      if (!selected)
--              wattrset(view->win, get_line_attr(LINE_DATE));
--      col = draw_text(view, buf, max, FALSE, selected);
--      if (col < max) {
--              if (!selected)
--                      wattrset(view->win, get_line_attr(LINE_DEFAULT));
--              waddch(view->win, ' ');
--              col++;
--      }
--
--      return col;
-+      return draw_field(view, LINE_DATE, date, DATE_COLS, FALSE);
+-      char *home = getenv("HOME");
+-      char *tigrc_user = getenv("TIGRC_USER");
+-      char *tigrc_system = getenv("TIGRC_SYSTEM");
++      const char *home = getenv("HOME");
++      const char *tigrc_user = getenv("TIGRC_USER");
++      const char *tigrc_system = getenv("TIGRC_SYSTEM");
+       char buf[SIZEOF_STR];
+       add_builtin_run_requests();
+@@ -1639,7 +1643,7 @@ draw_graphic(struct view *view, enum line_type type, chtype graphic[], size_t si
  }
  
  static bool
-@@ -1569,19 +1670,21 @@ draw_view_line(struct view *view, unsigned int lineno)
-       line = &view->line[view->offset + lineno];
-       wmove(view->win, lineno, 0);
-+      view->col = 0;
-+      view->curline = line;
-+      view->curtype = LINE_NONE;
-+      line->selected = FALSE;
-       if (selected) {
-+              set_view_attr(view, LINE_CURSOR);
-               line->selected = TRUE;
-               view->ops->select(view, line);
--              wchgat(view->win, -1, 0, LINE_CURSOR, NULL);
--              wattrset(view->win, get_line_attr(LINE_CURSOR));
-       } else if (line->selected) {
--              line->selected = FALSE;
-               wclrtoeol(view->win);
-       }
-       scrollok(view->win, FALSE);
--      draw_ok = view->ops->draw(view, line, lineno, selected);
-+      draw_ok = view->ops->draw(view, line, lineno);
-       scrollok(view->win, TRUE);
-       return draw_ok;
-@@ -2070,10 +2173,13 @@ search_view(struct view *view, enum request request)
-  */
- static void
--end_update(struct view *view)
-+end_update(struct view *view, bool force)
- {
-       if (!view->pipe)
-               return;
-+      while (!view->ops->read(view, NULL))
-+              if (!force)
-+                      return;
-       set_nonblocking_input(FALSE);
-       if (view->pipe == stdin)
-               fclose(view->pipe);
-@@ -2085,9 +2191,6 @@ end_update(struct view *view)
- static bool
- begin_update(struct view *view)
+-draw_field(struct view *view, enum line_type type, char *text, int len, bool trim)
++draw_field(struct view *view, enum line_type type, const char *text, int len, bool trim)
  {
--      if (view->pipe)
--              end_update(view);
--
-       if (opt_cmd[0]) {
-               string_copy(view->cmd, opt_cmd);
-               opt_cmd[0] = 0;
-@@ -2289,23 +2392,20 @@ update_view(struct view *view)
-       update_view_title(view);
+       int max = MIN(view->width - view->col, len);
+       int col;
+@@ -2375,8 +2379,14 @@ update_view(struct view *view)
+               }
+       }
  
- check_pipe:
--      if (ferror(view->pipe)) {
+-      if (!view_is_displayed(view))
+-              goto check_pipe;
 +      if (ferror(view->pipe) && errno != 0) {
-               report("Failed to read: %s", strerror(errno));
--              goto end;
++              report("Failed to read: %s", strerror(errno));
 +              end_update(view, TRUE);
-       } else if (feof(view->pipe)) {
-               report("");
--              goto end;
++
++      } else if (feof(view->pipe)) {
++              report("");
 +              end_update(view, FALSE);
-       }
++      }
  
+       if (view == VIEW(REQ_VIEW_TREE)) {
+               /* Clear the view and redraw everything since the tree sorting
+@@ -2406,17 +2416,6 @@ update_view(struct view *view)
+       /* Update the title _after_ the redraw so that if the redraw picks up a
+        * commit reference in view->ref it'll be available here. */
+       update_view_title(view);
+-
+-check_pipe:
+-      if (ferror(view->pipe) && errno != 0) {
+-              report("Failed to read: %s", strerror(errno));
+-              end_update(view, TRUE);
+-
+-      } else if (feof(view->pipe)) {
+-              report("");
+-              end_update(view, FALSE);
+-      }
+-
        return TRUE;
  
  alloc_error:
-       report("Allocation failure");
--
--end:
--      if (view->ops->read(view, NULL))
--              end_update(view);
-+      end_update(view, TRUE);
-       return FALSE;
+@@ -2438,10 +2437,9 @@ add_line_data(struct view *view, void *data, enum line_type type)
  }
  
-@@ -2340,7 +2440,7 @@ enum open_flags {
-       OPEN_SPLIT = 1,         /* Split current view. */
-       OPEN_BACKGROUNDED = 2,  /* Backgrounded. */
-       OPEN_RELOAD = 4,        /* Reload view even if it is the current. */
--      OPEN_NOMAXIMIZE = 8,    /* Do not maximize the current view. */
-+      OPEN_NOMAXIMIZE = 8     /* Do not maximize the current view. */
- };
- static void
-@@ -2381,6 +2481,9 @@ open_view(struct view *prev, enum request request, enum open_flags flags)
-           (nviews == 1 && base_view != display[0]))
-               resize_display();
-+      if (view->pipe)
-+              end_update(view, TRUE);
-+
-       if (view->ops->open) {
-               if (!view->ops->open(view)) {
-                       report("Failed to load %s view", view->name);
-@@ -2702,11 +2805,6 @@ view_driver(struct view *view, enum request request)
-               redraw_display();
-               break;
--      case REQ_PROMPT:
--              /* Always reload^Wrerun commands from the prompt. */
--              open_view(view, opt_request, OPEN_RELOAD);
--              break;
--
-       case REQ_SEARCH:
-       case REQ_SEARCH_BACK:
-               search_view(view, request);
-@@ -2722,7 +2820,7 @@ view_driver(struct view *view, enum request request)
-                       view = &views[i];
-                       if (view->pipe)
-                               report("Stopped loading the %s view", view->name),
--                      end_update(view);
-+                      end_update(view, TRUE);
-               }
-               break;
-@@ -2741,12 +2839,10 @@ view_driver(struct view *view, enum request request)
-               report("Nothing to edit");
-               break;
+ static struct line *
+-add_line_text(struct view *view, char *data, enum line_type type)
++add_line_text(struct view *view, const char *text, enum line_type type)
+ {
+-      if (data)
+-              data = strdup(data);
++      char *data = text ? strdup(text) : NULL;
  
--
-       case REQ_ENTER:
-               report("Nothing to enter");
-               break;
+       return data ? add_line_data(view, data, type) : NULL;
+ }
+@@ -2565,7 +2563,7 @@ open_external_viewer(const char *cmd)
+       endwin();                  /* restore original tty modes */
+       system(cmd);
+       fprintf(stderr, "Press Enter to continue");
+-      getc(stdin);
++      getc(opt_tty);
+       reset_prog_mode();
+       redraw_display();
+ }
+@@ -2587,7 +2585,7 @@ open_editor(bool from_root, const char *file)
+ {
+       char cmd[SIZEOF_STR];
+       char file_sq[SIZEOF_STR];
+-      char *editor;
++      const char *editor;
+       char *prefix = from_root ? opt_cdup : "";
+       editor = getenv("GIT_EDITOR");
+@@ -2893,7 +2891,6 @@ view_driver(struct view *view, enum request request)
+               return FALSE;
  
--
-       case REQ_VIEW_CLOSE:
-               /* XXX: Mark closed views by letting view->parent point to the
-                * view itself. Parents to closed view should never be
-@@ -2780,49 +2876,14 @@ view_driver(struct view *view, enum request request)
-  */
+       default:
+-              /* An unknown key will show most commonly used commands. */
+               report("Unknown key, press 'h' for help");
+               return TRUE;
+       }
+@@ -2919,7 +2916,7 @@ pager_draw(struct view *view, struct line *line, unsigned int lineno)
+ }
  
  static bool
--pager_draw(struct view *view, struct line *line, unsigned int lineno, bool selected)
-+pager_draw(struct view *view, struct line *line, unsigned int lineno)
+-add_describe_ref(char *buf, size_t *bufpos, char *commit_id, const char *sep)
++add_describe_ref(char *buf, size_t *bufpos, const char *commit_id, const char *sep)
  {
--      static char spaces[] = "                    ";
-       char *text = line->data;
--      int col = 0;
--
--      if (opt_line_number) {
--              col += draw_lineno(view, lineno, view->width, selected);
--              if (col >= view->width)
--                      return TRUE;
--      }
--
--      if (!selected)
--              wattrset(view->win, get_line_attr(line->type));
--
--      if (opt_tab_size < TABSIZE) {
--              int col_offset = col;
--
--              col = 0;
--              while (text && col_offset + col < view->width) {
--                      int cols_max = view->width - col_offset - col;
--                      char *pos = text;
--                      int cols;
--                      if (*text == '\t') {
--                              text++;
--                              assert(sizeof(spaces) > TABSIZE);
--                              pos = spaces;
--                              cols = opt_tab_size - (col % opt_tab_size);
--
--                      } else {
--                              text = strchr(text, '\t');
--                              cols = line ? text - pos : strlen(pos);
--                      }
--
--                      waddnstr(view->win, pos, MIN(cols, cols_max));
--                      col += cols;
--              }
--
--      } else {
--              draw_text(view, text, view->width - col, TRUE, selected);
--      }
-+      if (opt_line_number && draw_lineno(view, lineno))
-+              return TRUE;
-+      draw_text(view, line->type, text, TRUE);
-       return TRUE;
+       char refbuf[SIZEOF_STR];
+       char *ref = NULL;
+@@ -2967,8 +2964,8 @@ add_pager_refs(struct view *view, struct line *line)
+       do {
+               struct ref *ref = refs[refpos];
+-              char *fmt = ref->tag    ? "%s[%s]" :
+-                          ref->remote ? "%s<%s>" : "%s%s";
++              const char *fmt = ref->tag    ? "%s[%s]" :
++                                ref->remote ? "%s<%s>" : "%s%s";
+               if (!string_format_from(buf, &bufpos, fmt, sep, ref->name))
+                       return;
+@@ -3130,7 +3127,7 @@ help_open(struct view *view)
+       add_line_text(view, "Quick reference for tig keybindings:", LINE_DEFAULT);
+       for (i = 0; i < ARRAY_SIZE(req_info); i++) {
+-              char *key;
++              const char *key;
+               if (req_info[i].request == REQ_NONE)
+                       continue;
+@@ -3158,7 +3155,7 @@ help_open(struct view *view)
+       for (i = 0; i < run_requests; i++) {
+               struct run_request *req = get_run_request(REQ_NONE + i + 1);
+-              char *key;
++              const char *key;
+               if (!req)
+                       continue;
+@@ -3215,7 +3212,7 @@ pop_tree_stack_entry(void)
  }
  
-@@ -3525,9 +3586,6 @@ blame_read_file(struct view *view, char *line)
-               size_t linelen = strlen(line);
-               struct blame *blame = malloc(sizeof(*blame) + linelen);
+ static void
+-push_tree_stack_entry(char *name, unsigned long lineno)
++push_tree_stack_entry(const char *name, unsigned long lineno)
+ {
+       struct tree_stack_entry *entry = calloc(1, sizeof(*entry));
+       size_t pathlen = strlen(opt_path);
+@@ -3251,8 +3248,8 @@ push_tree_stack_entry(char *name, unsigned long lineno)
+ #define TREE_UP_FORMAT "040000 tree %s\t.."
  
--              if (!line)
--                      return FALSE;
--
-               blame->commit = NULL;
-               strncpy(blame->text, line, linelen);
-               blame->text[linelen] = 0;
-@@ -3606,51 +3664,32 @@ blame_read(struct view *view, char *line)
+ static int
+-tree_compare_entry(enum line_type type1, char *name1,
+-                 enum line_type type2, char *name2)
++tree_compare_entry(enum line_type type1, const char *name1,
++                 enum line_type type2, const char *name2)
+ {
+       if (type1 != type2) {
+               if (type1 == LINE_TREE_DIR)
+@@ -3263,10 +3260,10 @@ tree_compare_entry(enum line_type type1, char *name1,
+       return strcmp(name1, name2);
  }
  
- static bool
--blame_draw(struct view *view, struct line *line, unsigned int lineno, bool selected)
-+blame_draw(struct view *view, struct line *line, unsigned int lineno)
+-static char *
++static const char *
+ tree_path(struct line *line)
  {
-       struct blame *blame = line->data;
--      int col = 0;
--
--      if (opt_date) {
--              struct tm *time = blame->commit && *blame->commit->filename
--                              ? &blame->commit->time : NULL;
-+      struct tm *time = NULL;
-+      char *id = NULL, *author = NULL;
--              col += draw_date(view, time, view->width, selected);
--              if (col >= view->width)
--                      return TRUE;
-+      if (blame->commit && *blame->commit->filename) {
-+              id = blame->commit->id;
-+              author = blame->commit->author;
-+              time = &blame->commit->time;
-       }
+-      char *path = line->data;
++      const char *path = line->data;
  
--      if (opt_author) {
--              int max = MIN(AUTHOR_COLS - 1, view->width - col);
-+      if (opt_date && draw_date(view, time))
-+              return TRUE;
--              if (!selected)
--                      wattrset(view->win, get_line_attr(LINE_MAIN_AUTHOR));
--              if (blame->commit)
--                      draw_text(view, blame->commit->author, max, TRUE, selected);
--              col += AUTHOR_COLS;
--              if (col >= view->width)
--                      return TRUE;
--              wmove(view->win, lineno, col);
--      }
-+      if (opt_author &&
-+          draw_field(view, LINE_MAIN_AUTHOR, author, opt_author_cols, TRUE))
-+              return TRUE;
--      {
--              int max = MIN(ID_COLS - 1, view->width - col);
--
--              if (!selected)
--                      wattrset(view->win, get_line_attr(LINE_BLAME_ID));
--              if (blame->commit)
--                      draw_text(view, blame->commit->id, max, FALSE, -1);
--              col += ID_COLS;
--              if (col >= view->width)
--                      return TRUE;
--              wmove(view->win, lineno, col);
--      }
-+      if (draw_field(view, LINE_BLAME_ID, id, ID_COLS, FALSE))
-+              return TRUE;
+       return path + SIZEOF_TREE_ATTR;
+ }
+@@ -3318,7 +3315,7 @@ tree_read(struct view *view, char *text)
+       /* Skip "Directory ..." and ".." line. */
+       for (pos = 1 + !!*opt_path; pos < view->lines; pos++) {
+               struct line *line = &view->line[pos];
+-              char *path1 = tree_path(line);
++              const char *path1 = tree_path(line);
+               char *path2 = text + SIZEOF_TREE_ATTR;
+               int cmp = tree_compare_entry(line->type, path1, type, path2);
+@@ -3357,7 +3354,7 @@ tree_request(struct view *view, enum request request, struct line *line)
+       enum open_flags flags;
+       if (request == REQ_VIEW_BLAME) {
+-              char *filename = tree_path(line);
++              const char *filename = tree_path(line);
+               if (line->type == LINE_TREE_DIR) {
+                       report("Cannot show blame for directory %s", opt_path);
+@@ -3393,7 +3390,7 @@ tree_request(struct view *view, enum request request, struct line *line)
+                       pop_tree_stack_entry();
+               } else {
+-                      char *basename = tree_path(line);
++                      const char *basename = tree_path(line);
+                       push_tree_stack_entry(basename, view->lineno);
+               }
+@@ -3490,7 +3487,7 @@ struct blame {
+ };
  
--      col += draw_lineno(view, lineno, view->width - col, selected);
--      if (col >= view->width)
-+      if (draw_lineno(view, lineno))
-               return TRUE;
+ #define BLAME_CAT_FILE_CMD "git cat-file blob %s:%s"
+-#define BLAME_INCREMENTAL_CMD "git blame --incremental %s %s"
++#define BLAME_INCREMENTAL_CMD "git blame --incremental %s -- %s"
  
--      col += draw_text(view, blame->text, view->width - col, TRUE, selected);
-+      draw_text(view, LINE_DEFAULT, blame->text, TRUE);
-       return TRUE;
+ static bool
+ blame_open(struct view *view)
+@@ -3556,9 +3553,9 @@ get_blame_commit(struct view *view, const char *id)
  }
  
-@@ -3692,23 +3731,23 @@ blame_grep(struct view *view, struct line *line)
-       struct blame_commit *commit = blame->commit;
-       regmatch_t pmatch;
--#define MATCH(text) \
--      (*text && regexec(view->regex, text, 1, &pmatch, 0) != REG_NOMATCH)
-+#define MATCH(text, on)                                                       \
-+      (on && *text && regexec(view->regex, text, 1, &pmatch, 0) != REG_NOMATCH)
-       if (commit) {
-               char buf[DATE_COLS + 1];
--              if (MATCH(commit->title) ||
--                  MATCH(commit->author) ||
--                  MATCH(commit->id))
-+              if (MATCH(commit->title, 1) ||
-+                  MATCH(commit->author, opt_author) ||
-+                  MATCH(commit->id, opt_date))
-                       return TRUE;
-               if (strftime(buf, sizeof(buf), DATE_FORMAT, &commit->time) &&
--                  MATCH(buf))
-+                  MATCH(buf, 1))
-                       return TRUE;
-       }
--      return MATCH(blame->text);
-+      return MATCH(blame->text, 1);
+ static bool
+-parse_number(char **posref, size_t *number, size_t min, size_t max)
++parse_number(const char **posref, size_t *number, size_t min, size_t max)
+ {
+-      char *pos = *posref;
++      const char *pos = *posref;
  
- #undef MATCH
+       *posref = NULL;
+       pos = strchr(pos + 1, ' ');
+@@ -3573,11 +3570,11 @@ parse_number(char **posref, size_t *number, size_t min, size_t max)
  }
-@@ -3759,6 +3798,8 @@ struct status {
- static char status_onbranch[SIZEOF_STR];
- static struct status stage_status;
- static enum line_type stage_line_type;
-+static size_t stage_chunks;
-+static int *stage_chunk;
- /* Get fields from the diff line:
-  * :100644 100644 06a5d6ae9eca55be2e0e585a152e6b1336f2b20e 0000000000000000000000000000000000000000 M
-@@ -3977,7 +4018,7 @@ status_open(struct view *view)
-                       return FALSE;
-       }
--      system("git update-index -q --refresh 2>/dev/null");
-+      system("git update-index -q --refresh >/dev/null 2>/dev/null");
  
-       if (!status_run(view, indexcmd, indexstatus, LINE_STAT_STAGED) ||
-           !status_run(view, STATUS_DIFF_FILES_CMD, 0, LINE_STAT_UNSTAGED) ||
-@@ -4009,46 +4050,36 @@ status_open(struct view *view)
+ static struct blame_commit *
+-parse_blame_commit(struct view *view, char *text, int *blamed)
++parse_blame_commit(struct view *view, const char *text, int *blamed)
+ {
+       struct blame_commit *commit;
+       struct blame *blame;
+-      char *pos = text + SIZEOF_REV - 1;
++      const char *pos = text + SIZEOF_REV - 1;
+       size_t lineno;
+       size_t group;
+@@ -3606,7 +3603,7 @@ parse_blame_commit(struct view *view, char *text, int *blamed)
  }
  
  static bool
--status_draw(struct view *view, struct line *line, unsigned int lineno, bool selected)
-+status_draw(struct view *view, struct line *line, unsigned int lineno)
+-blame_read_file(struct view *view, char *line)
++blame_read_file(struct view *view, const char *line)
+ {
+       if (!line) {
+               FILE *pipe = NULL;
+@@ -3711,7 +3708,7 @@ blame_draw(struct view *view, struct line *line, unsigned int lineno)
+ {
+       struct blame *blame = line->data;
+       struct tm *time = NULL;
+-      char *id = NULL, *author = NULL;
++      const char *id = NULL, *author = NULL;
+       if (blame->commit && *blame->commit->filename) {
+               id = blame->commit->id;
+@@ -3855,13 +3852,13 @@ status_has_none(struct view *view, struct line *line)
+  * :100644 100644 06a5d6ae9eca55be2e0e585a152e6b1336f2b20e 0000000000000000000000000000000000000000 M
+  */
+ static inline bool
+-status_get_diff(struct status *file, char *buf, size_t bufsize)
++status_get_diff(struct status *file, const char *buf, size_t bufsize)
+ {
+-      char *old_mode = buf +  1;
+-      char *new_mode = buf +  8;
+-      char *old_rev  = buf + 15;
+-      char *new_rev  = buf + 56;
+-      char *status   = buf + 97;
++      const char *old_mode = buf +  1;
++      const char *new_mode = buf +  8;
++      const char *old_rev  = buf + 15;
++      const char *new_rev  = buf + 56;
++      const char *status   = buf + 97;
+       if (bufsize < 99 ||
+           old_mode[-1] != ':' ||
+@@ -4078,7 +4075,7 @@ status_draw(struct view *view, struct line *line, unsigned int lineno)
  {
        struct status *status = line->data;
-+      enum line_type type;
-       char *text;
--      int col = 0;
--
--      if (selected) {
--              /* No attributes. */
--
--      } else if (line->type == LINE_STAT_HEAD) {
--              wattrset(view->win, get_line_attr(LINE_STAT_HEAD));
--              wchgat(view->win, -1, 0, LINE_STAT_HEAD, NULL);
--
--      } else if (!status && line->type != LINE_STAT_NONE) {
--              wattrset(view->win, get_line_attr(LINE_STAT_SECTION));
--              wchgat(view->win, -1, 0, LINE_STAT_SECTION, NULL);
--
--      } else {
--              wattrset(view->win, get_line_attr(line->type));
--      }
+       enum line_type type;
+-      char *text;
++      const char *text;
  
        if (!status) {
                switch (line->type) {
-               case LINE_STAT_STAGED:
-+                      type = LINE_STAT_SECTION;
-                       text = "Changes to be committed:";
-                       break;
-               case LINE_STAT_UNSTAGED:
-+                      type = LINE_STAT_SECTION;
-                       text = "Changed but not updated:";
-                       break;
-               case LINE_STAT_UNTRACKED:
-+                      type = LINE_STAT_SECTION;
-                       text = "Untracked files:";
-                       break;
-               case LINE_STAT_NONE:
-+                      type = LINE_DEFAULT;
-                       text = "    (no files)";
-                       break;
-               case LINE_STAT_HEAD:
-+                      type = LINE_STAT_HEAD;
-                       text = status_onbranch;
-                       break;
-@@ -4056,15 +4087,16 @@ status_draw(struct view *view, struct line *line, unsigned int lineno, bool sele
-                       return FALSE;
-               }
-       } else {
--              char buf[] = { status->status, ' ', ' ', ' ', 0 };
-+              static char buf[] = { '?', ' ', ' ', ' ', 0 };
--              col += draw_text(view, buf, view->width, TRUE, selected);
--              if (!selected)
--                      wattrset(view->win, A_NORMAL);
-+              buf[0] = status->status;
-+              if (draw_text(view, line->type, buf, TRUE))
-+                      return TRUE;
-+              type = LINE_DEFAULT;
-               text = status->new.name;
-       }
--      draw_text(view, text, view->width - col, TRUE, selected);
-+      draw_text(view, type, text, TRUE);
-       return TRUE;
- }
-@@ -4159,6 +4191,7 @@ status_enter(struct view *view, struct line *line)
-               }
-               stage_line_type = line->type;
-+              stage_chunks = 0;
-               string_format(VIEW(REQ_VIEW_STAGE)->ref, info, stage_status.new.name);
-       }
-@@ -4303,11 +4336,14 @@ status_update(struct view *view)
+@@ -4130,7 +4127,7 @@ status_enter(struct view *view, struct line *line)
+       struct status *status = line->data;
+       char oldpath[SIZEOF_STR] = "";
+       char newpath[SIZEOF_STR] = "";
+-      char *info;
++      const char *info;
+       size_t cmdsize = 0;
+       enum open_flags split;
+@@ -4393,7 +4390,7 @@ status_revert(struct status *status, enum line_type type, bool has_none)
+               char file_sq[SIZEOF_STR];
+               if (sq_quote(file_sq, 0, status->old.name) >= sizeof(file_sq) ||
+-                  !string_format(cmd, "git checkout %s%s", opt_cdup, file_sq))
++                  !string_format(cmd, "git checkout -- %s%s", opt_cdup, file_sq))
                        return FALSE;
-               }
--              if (!status_update_files(view, line + 1))
-+              if (!status_update_files(view, line + 1)) {
-                       report("Failed to update file status");
-+                      return FALSE;
-+              }
  
-       } else if (!status_update_file(line->data, line->type)) {
-               report("Failed to update file status");
-+              return FALSE;
-       }
-       return TRUE;
-@@ -4545,6 +4581,18 @@ stage_update(struct view *view, struct line *line)
-                       return FALSE;
-               }
+               return run_confirm(cmd, "Are you sure you want to overwrite any changes?");
+@@ -4463,8 +4460,8 @@ status_select(struct view *view, struct line *line)
+ {
+       struct status *status = line->data;
+       char file[SIZEOF_STR] = "all files";
+-      char *text;
+-      char *key;
++      const char *text;
++      const char *key;
  
-+      } else if (!stage_status.status) {
-+              view = VIEW(REQ_VIEW_STATUS);
-+
-+              for (line = view->line; line < view->line + view->lines; line++)
-+                      if (line->type == stage_line_type)
-+                              break;
-+
-+              if (!status_update_files(view, line + 1)) {
-+                      report("Failed to update files");
-+                      return FALSE;
-+              }
-+
-       } else if (!status_update_file(&stage_status, stage_line_type)) {
-               report("Failed to update file");
+       if (status && !string_format(file, "'%s'", status->new.name))
+               return;
+@@ -4517,7 +4514,7 @@ status_grep(struct view *view, struct line *line)
                return FALSE;
-@@ -4553,14 +4601,60 @@ stage_update(struct view *view, struct line *line)
-       return TRUE;
- }
  
-+static void
-+stage_next(struct view *view, struct line *line)
-+{
-+      int i;
-+
-+      if (!stage_chunks) {
-+              static size_t alloc = 0;
-+              int *tmp;
-+
-+              for (line = view->line; line < view->line + view->lines; line++) {
-+                      if (line->type != LINE_DIFF_CHUNK)
-+                              continue;
-+
-+                      tmp = realloc_items(stage_chunk, &alloc,
-+                                          stage_chunks, sizeof(*tmp));
-+                      if (!tmp) {
-+                              report("Allocation failure");
-+                              return;
-+                      }
-+
-+                      stage_chunk = tmp;
-+                      stage_chunk[stage_chunks++] = line - view->line;
-+              }
-+      }
-+
-+      for (i = 0; i < stage_chunks; i++) {
-+              if (stage_chunk[i] > view->lineno) {
-+                      do_scroll_view(view, stage_chunk[i] - view->lineno);
-+                      report("Chunk %d of %d", i + 1, stage_chunks);
-+                      return;
-+              }
-+      }
-+
-+      report("No next chunk found");
-+}
-+
- static enum request
- stage_request(struct view *view, enum request request, struct line *line)
- {
-       switch (request) {
-       case REQ_STATUS_UPDATE:
--              stage_update(view, line);
-+              if (!stage_update(view, line))
-+                      return REQ_NONE;
-               break;
-+      case REQ_STAGE_NEXT:
-+              if (stage_line_type == LINE_STAT_UNTRACKED) {
-+                      report("File is untracked; press %s to add",
-+                             get_key(REQ_STATUS_UPDATE));
-+                      return REQ_NONE;
-+              }
-+              stage_next(view, line);
-+              return REQ_NONE;
-+
-       case REQ_EDIT:
-               if (!stage_status.new.name[0])
-                       return request;
-@@ -4732,7 +4826,7 @@ draw_rev_graph(struct rev_graph *graph)
-       };
-       enum { DEFAULT, RSHARP, RDIAG, LDIAG };
-       static struct rev_filler fillers[] = {
--              { ' ',  REVGRAPH_LINE },
-+              { ' ',  '|' },
-               { '`',  '.' },
-               { '\'', ' ' },
-               { '/',  ' ' },
-@@ -4741,6 +4835,9 @@ draw_rev_graph(struct rev_graph *graph)
-       struct rev_filler *filler;
-       size_t i;
-+      if (opt_line_graphics)
-+              fillers[DEFAULT].line = line_graphics[LINE_GRAPHIC_VLINE];
-+
-       filler = &fillers[DEFAULT];
-       for (i = 0; i < graph->pos; i++) {
-@@ -4824,100 +4921,54 @@ update_rev_graph(struct rev_graph *graph)
-  */
+       for (state = S_STATUS; state < S_END; state++) {
+-              char *text;
++              const char *text;
  
+               switch (state) {
+               case S_NAME:    text = status->new.name;        break;
+@@ -4551,7 +4548,7 @@ static struct view_ops status_ops = {
  static bool
--main_draw(struct view *view, struct line *line, unsigned int lineno, bool selected)
-+main_draw(struct view *view, struct line *line, unsigned int lineno)
+ stage_diff_line(FILE *pipe, struct line *line)
  {
-       struct commit *commit = line->data;
--      enum line_type type;
--      int col = 0;
+-      char *buf = line->data;
++      const char *buf = line->data;
+       size_t bufsize = strlen(buf);
+       size_t written = 0;
  
-       if (!*commit->author)
-               return FALSE;
+@@ -4874,7 +4871,7 @@ done_rev_graph(struct rev_graph *graph)
+ }
  
--      if (selected) {
--              type = LINE_CURSOR;
--      } else {
--              type = LINE_MAIN_COMMIT;
--      }
--
--      if (opt_date) {
--              col += draw_date(view, &commit->time, view->width, selected);
--              if (col >= view->width)
--                      return TRUE;
--      }
--      if (type != LINE_CURSOR)
--              wattrset(view->win, get_line_attr(LINE_MAIN_AUTHOR));
--
--      if (opt_author) {
--              int max_len;
--
--              max_len = view->width - col;
--              if (max_len > AUTHOR_COLS - 1)
--                      max_len = AUTHOR_COLS - 1;
--              draw_text(view, commit->author, max_len, TRUE, selected);
--              col += AUTHOR_COLS;
--              if (col >= view->width)
--                      return TRUE;
--      }
--
--      if (opt_rev_graph && commit->graph_size) {
--              size_t graph_size = view->width - col;
--              size_t i;
--
--              if (type != LINE_CURSOR)
--                      wattrset(view->win, get_line_attr(LINE_MAIN_REVGRAPH));
--              wmove(view->win, lineno, col);
--              if (graph_size > commit->graph_size)
--                      graph_size = commit->graph_size;
--              /* Using waddch() instead of waddnstr() ensures that
--               * they'll be rendered correctly for the cursor line. */
--              for (i = 0; i < graph_size; i++)
--                      waddch(view->win, commit->graph[i]);
-+      if (opt_date && draw_date(view, &commit->time))
-+              return TRUE;
--              col += commit->graph_size + 1;
--              if (col >= view->width)
--                      return TRUE;
--              waddch(view->win, ' ');
--      }
--      if (type != LINE_CURSOR)
--              wattrset(view->win, A_NORMAL);
-+      if (opt_author &&
-+          draw_field(view, LINE_MAIN_AUTHOR, commit->author, opt_author_cols, TRUE))
-+              return TRUE;
--      wmove(view->win, lineno, col);
-+      if (opt_rev_graph && commit->graph_size &&
-+          draw_graphic(view, LINE_MAIN_REVGRAPH, commit->graph, commit->graph_size))
-+              return TRUE;
-       if (opt_show_refs && commit->refs) {
-               size_t i = 0;
-               do {
--                      if (type == LINE_CURSOR)
--                              ;
--                      else if (commit->refs[i]->head)
--                              wattrset(view->win, get_line_attr(LINE_MAIN_HEAD));
-+                      enum line_type type;
-+
-+                      if (commit->refs[i]->head)
-+                              type = LINE_MAIN_HEAD;
-                       else if (commit->refs[i]->ltag)
--                              wattrset(view->win, get_line_attr(LINE_MAIN_LOCAL_TAG));
-+                              type = LINE_MAIN_LOCAL_TAG;
-                       else if (commit->refs[i]->tag)
--                              wattrset(view->win, get_line_attr(LINE_MAIN_TAG));
-+                              type = LINE_MAIN_TAG;
-                       else if (commit->refs[i]->tracked)
--                              wattrset(view->win, get_line_attr(LINE_MAIN_TRACKED));
-+                              type = LINE_MAIN_TRACKED;
-                       else if (commit->refs[i]->remote)
--                              wattrset(view->win, get_line_attr(LINE_MAIN_REMOTE));
-+                              type = LINE_MAIN_REMOTE;
-                       else
--                              wattrset(view->win, get_line_attr(LINE_MAIN_REF));
--
--                      col += draw_text(view, "[", view->width - col, TRUE, selected);
--                      col += draw_text(view, commit->refs[i]->name, view->width - col,
--                                       TRUE, selected);
--                      col += draw_text(view, "]", view->width - col, TRUE, selected);
--                      if (type != LINE_CURSOR)
--                              wattrset(view->win, A_NORMAL);
--                      col += draw_text(view, " ", view->width - col, TRUE, selected);
--                      if (col >= view->width)
-+                              type = LINE_MAIN_REF;
-+
-+                      if (draw_text(view, type, "[", TRUE) ||
-+                          draw_text(view, type, commit->refs[i]->name, TRUE) ||
-+                          draw_text(view, type, "]", TRUE))
-+                              return TRUE;
-+
-+                      if (draw_text(view, LINE_DEFAULT, " ", TRUE))
-                               return TRUE;
-               } while (commit->refs[i++]->next);
-       }
+ static void
+-push_rev_graph(struct rev_graph *graph, char *parent)
++push_rev_graph(struct rev_graph *graph, const char *parent)
+ {
+       int i;
  
--      if (type != LINE_CURSOR)
--              wattrset(view->win, get_line_attr(type));
+@@ -5531,13 +5528,13 @@ init_display(void)
+       /* Initialize the curses library */
+       if (isatty(STDIN_FILENO)) {
+               cursed = !!initscr();
++              opt_tty = stdin;
+       } else {
+               /* Leave stdin and stdout alone when acting as a pager. */
+-              FILE *io = fopen("/dev/tty", "r+");
 -
--      draw_text(view, commit->title, view->width - col, TRUE, selected);
-+      draw_text(view, LINE_DEFAULT, commit->title, TRUE);
-       return TRUE;
- }
-@@ -4932,6 +4983,14 @@ main_read(struct view *view, char *line)
-       if (!line) {
-               if (!view->lines && !view->parent)
-                       die("No revisions match the given arguments.");
-+              if (view->lines > 0) {
-+                      commit = view->line[view->lines - 1].data;
-+                      if (!*commit->author) {
-+                              view->lines--;
-+                              free(commit);
-+                              graph->commit = NULL;
-+                      }
-+              }
-               update_rev_graph(graph);
-               return TRUE;
+-              if (!io)
++              opt_tty = fopen("/dev/tty", "r+");
++              if (!opt_tty)
+                       die("Failed to open /dev/tty");
+-              cursed = !!newterm(NULL, io, io);
++              cursed = !!newterm(NULL, opt_tty, opt_tty);
        }
-@@ -5061,10 +5120,26 @@ main_request(struct view *view, enum request request, struct line *line)
- }
  
- static bool
-+grep_refs(struct ref **refs, regex_t *regex)
+       if (!cursed)
+@@ -5698,8 +5695,27 @@ static struct ref ***id_refs = NULL;
+ static size_t id_refs_alloc = 0;
+ static size_t id_refs_size = 0;
++static int
++compare_refs(const void *ref1_, const void *ref2_)
 +{
-+      regmatch_t pmatch;
-+      size_t i = 0;
-+
-+      if (!refs)
-+              return FALSE;
-+      do {
-+              if (regexec(regex, refs[i]->name, 1, &pmatch, 0) != REG_NOMATCH)
-+                      return TRUE;
-+      } while (refs[i++]->next);
-+
-+      return FALSE;
++      const struct ref *ref1 = *(const struct ref **)ref1_;
++      const struct ref *ref2 = *(const struct ref **)ref2_;
++
++      if (ref1->tag != ref2->tag)
++              return ref2->tag - ref1->tag;
++      if (ref1->ltag != ref2->ltag)
++              return ref2->ltag - ref2->ltag;
++      if (ref1->head != ref2->head)
++              return ref2->head - ref1->head;
++      if (ref1->tracked != ref2->tracked)
++              return ref2->tracked - ref1->tracked;
++      if (ref1->remote != ref2->remote)
++              return ref2->remote - ref1->remote;
++      return strcmp(ref1->name, ref2->name);
 +}
 +
-+static bool
- main_grep(struct view *view, struct line *line)
- {
-       struct commit *commit = line->data;
--      enum { S_TITLE, S_AUTHOR, S_DATE, S_END } state;
-+      enum { S_TITLE, S_AUTHOR, S_DATE, S_REFS, S_END } state;
-       char buf[DATE_COLS + 1];
-       regmatch_t pmatch;
-@@ -5073,13 +5148,24 @@ main_grep(struct view *view, struct line *line)
-               switch (state) {
-               case S_TITLE:   text = commit->title;   break;
--              case S_AUTHOR:  text = commit->author;  break;
-+              case S_AUTHOR:
-+                      if (!opt_author)
-+                              continue;
-+                      text = commit->author;
-+                      break;
-               case S_DATE:
-+                      if (!opt_date)
-+                              continue;
-                       if (!strftime(buf, sizeof(buf), DATE_FORMAT, &commit->time))
-                               continue;
-                       text = buf;
-                       break;
--
-+              case S_REFS:
-+                      if (!opt_show_refs)
-+                              continue;
-+                      if (grep_refs(commit->refs, view->regex) == TRUE)
-+                              return TRUE;
-+                      continue;
-               default:
-                       return FALSE;
-               }
-@@ -5216,13 +5302,14 @@ utf8_to_unicode(const char *string, size_t length)
-  *
-  * Returns the number of bytes to output from string to satisfy max_width. */
- static size_t
--utf8_length(const char *string, size_t max_width, int *trimmed, bool reserve)
-+utf8_length(const char *string, int *width, size_t max_width, int *trimmed, bool reserve)
+ static struct ref **
+-get_refs(char *id)
++get_refs(const char *id)
  {
-       const char *start = string;
-       const char *end = strchr(string, '\0');
-       unsigned char last_bytes = 0;
--      size_t width = 0;
-+      size_t last_ucwidth = 0;
-+      *width = 0;
-       *trimmed = 0;
-       while (string < end) {
-@@ -5243,17 +5330,20 @@ utf8_length(const char *string, size_t max_width, int *trimmed, bool reserve)
-                       break;
-               ucwidth = unicode_width(unicode);
--              width  += ucwidth;
--              if (width > max_width) {
-+              *width  += ucwidth;
-+              if (*width > max_width) {
-                       *trimmed = 1;
--                      if (reserve && width - ucwidth == max_width) {
-+                      *width -= ucwidth;
-+                      if (reserve && *width == max_width) {
-                               string -= last_bytes;
-+                              *width -= last_ucwidth;
-                       }
-                       break;
+       struct ref ***tmp_id_refs;
+       struct ref **ref_list = NULL;
+@@ -5733,19 +5749,20 @@ get_refs(char *id)
                }
  
-               string  += bytes;
-               last_bytes = bytes;
-+              last_ucwidth = ucwidth;
+               ref_list = tmp;
+-              if (ref_list_size > 0)
+-                      ref_list[ref_list_size - 1]->next = 1;
+               ref_list[ref_list_size] = &refs[i];
+-
+               /* XXX: The properties of the commit chains ensures that we can
+                * safely modify the shared ref. The repo references will
+                * always be similar for the same id. */
+-              ref_list[ref_list_size]->next = 0;
++              ref_list[ref_list_size]->next = 1;
++
+               ref_list_size++;
        }
  
-       return string - start;
-@@ -5365,6 +5455,11 @@ init_display(void)
-       /* Enable keyboard mapping */
-       keypad(status_win, TRUE);
-       wbkgdset(status_win, get_line_attr(LINE_STATUS));
-+
-+      TABSIZE = opt_tab_size;
-+      if (opt_line_graphics) {
-+              line_graphics[LINE_GRAPHIC_VLINE] = ACS_VLINE;
+-      if (ref_list)
++      if (ref_list) {
++              qsort(ref_list, ref_list_size, sizeof(*ref_list), compare_refs);
++              ref_list[ref_list_size - 1]->next = 0;
+               id_refs[id_refs_size++] = ref_list;
 +      }
- }
- static char *
-@@ -5773,11 +5868,12 @@ main(int argc, char *argv[])
-       if (load_git_config() == ERR)
-               die("Failed to load repo config.");
--      if (!parse_options(argc, argv))
-+      request = parse_options(argc, argv);
-+      if (request == REQ_NONE)
-               return 0;
  
-       /* Require a git repository unless when running in pager mode. */
--      if (!opt_git_dir[0] && opt_request != REQ_VIEW_PAGER)
-+      if (!opt_git_dir[0] && request != REQ_VIEW_PAGER)
-               die("Not a git repository");
+       return ref_list;
+ }
+@@ -5761,7 +5778,7 @@ read_ref(char *id, size_t idlen, char *name, size_t namelen)
+       bool check_replace = FALSE;
+       bool head = FALSE;
+-      if (!strncmp(name, "refs/tags/", STRING_SIZE("refs/tags/"))) {
++      if (!prefixcmp(name, "refs/tags/")) {
+               if (!strcmp(name + namelen - 3, "^{}")) {
+                       namelen -= 3;
+                       name[namelen] = 0;
+@@ -5775,13 +5792,13 @@ read_ref(char *id, size_t idlen, char *name, size_t namelen)
+               namelen -= STRING_SIZE("refs/tags/");
+               name    += STRING_SIZE("refs/tags/");
+-      } else if (!strncmp(name, "refs/remotes/", STRING_SIZE("refs/remotes/"))) {
++      } else if (!prefixcmp(name, "refs/remotes/")) {
+               remote = TRUE;
+               namelen -= STRING_SIZE("refs/remotes/");
+               name    += STRING_SIZE("refs/remotes/");
+               tracked  = !strcmp(opt_remote, name);
+-      } else if (!strncmp(name, "refs/heads/", STRING_SIZE("refs/heads/"))) {
++      } else if (!prefixcmp(name, "refs/heads/")) {
+               namelen -= STRING_SIZE("refs/heads/");
+               name    += STRING_SIZE("refs/heads/");
+               head     = !strncmp(opt_head, name, namelen);
+@@ -5794,7 +5811,7 @@ read_ref(char *id, size_t idlen, char *name, size_t namelen)
+       if (check_replace && !strcmp(name, refs[refs_size - 1].name)) {
+               /* it's an annotated tag, replace the previous sha1 with the
+                * resolved commit id; relies on the fact git-ls-remote lists
+-               * the commit id of an annotated tag right beofre the commit id
++               * the commit id of an annotated tag right before the commit id
+                * it points to. */
+               refs[refs_size - 1].ltag = ltag;
+               string_copy_rev(refs[refs_size - 1].id, id);
+@@ -5861,7 +5878,7 @@ read_repo_config_option(char *name, size_t namelen, char *value, size_t valuelen
+           !strcmp(name + 7 + strlen(opt_head), ".merge")) {
+               size_t from = strlen(opt_remote);
+-              if (!strncmp(value, "refs/heads/", STRING_SIZE("refs/heads/"))) {
++              if (!prefixcmp(value, "refs/heads/")) {
+                       value += STRING_SIZE("refs/heads/");
+                       valuelen -= STRING_SIZE("refs/heads/");
+               }
+@@ -5897,7 +5914,7 @@ read_repo_info(char *name, size_t namelen, char *value, size_t valuelen)
+       } else if (opt_cdup[0] == ' ') {
+               string_ncopy(opt_cdup, name, namelen);
+       } else {
+-              if (!strncmp(name, "refs/heads/", STRING_SIZE("refs/heads/"))) {
++              if (!prefixcmp(name, "refs/heads/")) {
+                       namelen -= STRING_SIZE("refs/heads/");
+                       name    += STRING_SIZE("refs/heads/");
+                       string_ncopy(opt_head, name, namelen);
+@@ -6009,7 +6026,7 @@ warn(const char *msg, ...)
+ }
  
-       if (*opt_encoding && strcasecmp(opt_encoding, "UTF-8"))
-@@ -5795,8 +5891,6 @@ main(int argc, char *argv[])
-       for (i = 0; i < ARRAY_SIZE(views) && (view = &views[i]); i++)
+ int
+-main(int argc, char *argv[])
++main(int argc, const char *argv[])
+ {
+       struct view *view;
+       enum request request;
+@@ -6052,7 +6069,7 @@ main(int argc, char *argv[])
+       if (load_refs() == ERR)
+               die("Failed to load refs.");
+-      for (i = 0; i < ARRAY_SIZE(views) && (view = &views[i]); i++)
++      foreach_view (view, i)
                view->cmd_env = getenv(view->cmd_env);
  
--      request = opt_request;
--
        init_display();
+@@ -6063,6 +6080,7 @@ main(int argc, char *argv[])
  
-       while (view_driver(display[current_view], request)) {
-@@ -5827,11 +5921,13 @@ main(int argc, char *argv[])
-                       if (cmd && string_format(opt_cmd, "git %s", cmd)) {
-                               if (strncmp(cmd, "show", 4) && isspace(cmd[4])) {
--                                      opt_request = REQ_VIEW_DIFF;
-+                                      request = REQ_VIEW_DIFF;
-                               } else {
--                                      opt_request = REQ_VIEW_PAGER;
-+                                      request = REQ_VIEW_PAGER;
-                               }
--                              break;
-+
-+                              /* Always reload^Wrerun commands from the prompt. */
-+                              open_view(view, request, OPEN_RELOAD);
-                       }
-                       request = REQ_NONE;
-diff --git a/tigrc.5.txt b/tigrc.5.txt
-index 369fc65..471aab3 100644
---- a/tigrc.5.txt
-+++ b/tigrc.5.txt
-@@ -47,6 +47,8 @@ set show-date = yes          # Show commit date?
- set show-rev-graph = yes      # Show revision graph?
- set show-refs = yes           # Show references?
- set show-line-numbers = no    # Show line numbers?
-+set author-width = 10         # Set width of the author column
-+set line-graphics = no                # Disable graphics characters
- set line-number-interval = 5  # Interval between line numbers
- set tab-size = 8              # Number of spaces per tab
- set encoding = "UTF-8"                # Commit encoding
-@@ -81,6 +83,14 @@ The following variables can be set:
-       (branches, tags, and remotes) in the main view on start-up. Can all be
-       toggled.
-+'author-width' (int)::
-+
-+      Width of the author column.
-+
-+'line-graphics' (bool)::
-+
-+      Whether to use graphic characters for line drawing.
-+
- 'line-number-interval' (int)::
-       Interval between line numbers. Note, you have to toggle on line
-@@ -259,6 +269,7 @@ toggle-rev-graph   Toggle revision graph visualization
- toggle-refs           Toggle reference display
- status-update         Update file status
- status-merge          Resolve unmerged file
-+stage-next            Find next chunk to stage
- tree-parent           Switch to parent directory in tree view
- edit                  Open in editor
- ------------------------------------------------------------------------------
-@@ -343,6 +354,7 @@ Main view colors:
- ------------------------------------------------------------------------------
- main-author           The commit author.
- main-revgraph         The revision graph.
-+main-commit           The commit comment.
- main-head             Label of the current branch.
- main-remote           Label of a remote.
- main-tracked          Label of the remote tracked by the current branch.
-@@ -431,4 +443,4 @@ Licensed under the terms of the GNU General Public License.
- SEE ALSO
- --------
--gitlink:tig[1] and the http://jonas.nitro.dk/tig/manual.html[tig manual].
-+manpage:tig[1] and the http://jonas.nitro.dk/tig/manual.html[tig manual].
+               foreach_view (view, i)
+                       update_view(view);
++              view = display[current_view];
+               /* Refresh, accept single keystroke of input */
+               key = wgetch(status_win);
+@@ -6074,7 +6092,7 @@ main(int argc, char *argv[])
+                       continue;
+               }
+-              request = get_keybinding(display[current_view]->keymap, key);
++              request = get_keybinding(view->keymap, key);
+               /* Some low-level request handling. This keeps access to
+                * status_win restricted. */
+@@ -6100,8 +6118,7 @@ main(int argc, char *argv[])
+               case REQ_SEARCH:
+               case REQ_SEARCH_BACK:
+               {
+-                      const char *prompt = request == REQ_SEARCH
+-                                         ? "/" : "?";
++                      const char *prompt = request == REQ_SEARCH ? "/" : "?";
+                       char *search = read_prompt(prompt);
+                       if (search)
This page took 0.280172 seconds and 4 git commands to generate.