| |   |
| 1 | Release notes |
| 2 | ============= |
| 3 | |
| 4 | tig master branch |
| 5 | ----------------- |
| 6 | |
| 7 | Improvements: |
| 8 | |
| 9 | - F5 also refreshes the current view. |
| 10 | - Allow line graphics to be disabled with new line-graphics option. |
| 11 | - Also include the reference names when searching. |
| 12 | |
| 13 | Bug fixes: |
| 14 | |
| 15 | - Fix regression when staging all diff chunks in a section. |
| 16 | - Bind the maximize view action to 'O'; it conflicted with the |
| 17 | keybinding to launch the merge tool in the status view. |
| 18 | |
| 19 | tig-0.11 |
| 20 | -------- |
| 21 | |
| 22 | Incompatibilities: |
| 23 | |
| 24 | - Remove parsing of deprecated options: -g, -l, -d. |
| 25 | - The first seen '--' will stop option parsing and is passed to git |
| 26 | instead of breaking out of tig's option parsing. |
| 27 | |
| 28 | New features: |
| 29 | |
| 30 | - Blame view; bound to 'B' by default, reachable from the command line |
| 31 | and the tree, status, and stage views. |
| 32 | - Blame/main view: allow display of date, author, and references to be |
| 33 | toggled on/off. Bound to 'D', 'A', and 'F' respectively. |
| 34 | - Add action to maximize the current view. |
| 35 | |
| 36 | Improvements: |
| 37 | |
| 38 | - Show the current branch in the status view. |
| 39 | - Show local/light-weight tags. |
| 40 | |
| 41 | Bug fixes: |
| 42 | |
| 43 | - Fix regressions for the pager mode. |
| 44 | - Fix refreshing of the index with working directory info. |
| 45 | |
| 46 | tig-0.10.1 |
| 47 | ---------- |
| 48 | |
| 49 | Improvements: |
| 50 | |
| 51 | - Status view: detect renamed files and show them with 'R'. |
| 52 | - Status view: refresh the index to avoid "empty diffs". |
| 53 | - Diff view: make diff headers more verbose to include e.g. committer. |
| 54 | - Configure: check for the ncursesw library. |
| 55 | |
| 56 | Bug fixes: |
| 57 | |
| 58 | - Fix UTF8 handling for tag names and commit messages. |
| 59 | - Fix the check for git-config(1) in configure to handle the case when |
| 60 | git has been installed using a libexecdir which is not in the path. |
| 61 | - Fix replacing of SYSCONFDIR when installing from released tarballs. |
| 62 | |
| 63 | tig-0.10 |
| 64 | --------- |
| 65 | |
| 66 | Incompatibilities: |
| 67 | |
| 68 | - Deprecate most tig specific command line options to make tig more |
| 69 | compatible with gitk. The deprecated options are: -g, -l, -d, and -S. |
| 70 | Use of any of them will result in a warning being printed to stderr. |
| 71 | Instead of '-S', use the new 'status' subcommand. |
| 72 | - Make man page building depend on DocBook XSL version >= 1.72.0. |
| 73 | - Install man pages in $(prefix)/share/man. |
| 74 | - Implement the cherry pick action (bound to 'C') using new support for |
| 75 | running external commands. This obsoletes the TIG_CHEERY_PICK |
| 76 | environment variable |
| 77 | |
| 78 | New features: |
| 79 | |
| 80 | - Add support for binding keys to external commands. To bind '.' to |
| 81 | running git-commit(1), add the line: "bind generic . !git commit" to |
| 82 | your ~/.tigrc. Each command can have replacement string such as |
| 83 | %(commit), %(head), and %(blob), which are substituted before the |
| 84 | command is run. |
| 85 | - Add system-wide configuration file defaulting to $(prefix)/etc/tigrc. |
| 86 | - Add the environment variables TIGRC_USER and TIGRC_SYSTEM to change |
| 87 | user and system-wide configuration files, respectively. |
| 88 | |
| 89 | Improvements: |
| 90 | |
| 91 | - Main view: color the revision graph. |
| 92 | - Main view: show boundary commits; they are marked with '^' in the |
| 93 | revision graph. |
| 94 | - Tree view: add tree-parent action to jump to view of the parent tree. |
| 95 | Bound to ',' by default. |
| 96 | - Allow the default terminal colors to be overwritten. To use black |
| 97 | text on white, add the line "color default white black" to your |
| 98 | ~/.tigrc. |
| 99 | - Misc. documentation improvements. |
| 100 | |
| 101 | Bug fixes: |
| 102 | |
| 103 | - Use git-diff-index(1) and git-diff-files(1) instead of git-diff(1) to |
| 104 | avoid running external diff drivers. |
| 105 | - Use --no-color when calling git-log(1). |
| 106 | - Fix crash when opening mergetool for lines that are not unmerged. |
| 107 | |
| 108 | tig-0.9.1 |
| 109 | --------- |
| 110 | |
| 111 | Incompatibilities: |
| 112 | |
| 113 | - Make the clean rule to never remove generated documentation files. |
| 114 | Use the distclean rule for accomplishing this. |
| 115 | |
| 116 | New features: |
| 117 | |
| 118 | - Add support for cherry-picking commits in the main view to the |
| 119 | current branch. Bound to 'C' by default. |
| 120 | |
| 121 | Improvements: |
| 122 | |
| 123 | - Add support for launching git-mergetool(1) from the status view. |
| 124 | Bound to 'M' by default. |
| 125 | - Add support for refreshing/reloading the status view |
| 126 | - Detect working trees and disable the status view when it is missing. |
| 127 | |
| 128 | Bug fixes: |
| 129 | |
| 130 | - Fix iconv() checking in configure. |
| 131 | - Fix editor invocation to make paths relative to the project root. |
| 132 | - Fix out-of-range current line when reloading the status view. |
| 133 | - Include autoconf files in the tarball generated by `make dist`. |
| 134 | |
| 135 | tig-0.9 |
| 136 | ------- |
| 137 | |
| 138 | New features: |
| 139 | |
| 140 | - Add bash completion script for tig (contrib/tig-completion.bash). |
| 141 | - Add optional autoconf-based build infrastructure. |
| 142 | - Add stage view for showing changes in the working tree and add |
| 143 | support for staging individual diff chunks for commit. |
| 144 | |
| 145 | Improvements: |
| 146 | |
| 147 | - Status view: allow all files in a section to be staged for commit. |
| 148 | - Status view: Add support for opening files in an editor. Bound to 'e' |
| 149 | by default. |
| 150 | - Tree view: use a stack for remembering the lines for parent tree. |
| toggle raw diff |
--- /dev/null
+++ b/NEWS
@@ -0,0 +1,150 @@
+Release notes
+=============
+
+tig master branch
+-----------------
+
+Improvements:
+
+ - F5 also refreshes the current view.
+ - Allow line graphics to be disabled with new line-graphics option.
+ - Also include the reference names when searching.
+
+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.
+
+tig-0.11
+--------
+
+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.
+
+New features:
+
+ - 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.
+
+Improvements:
+
+ - Show the current branch in the status view.
+ - Show local/light-weight tags.
+
+Bug fixes:
+
+ - Fix regressions for the pager mode.
+ - Fix refreshing of the index with working directory info.
+
+tig-0.10.1
+----------
+
+Improvements:
+
+ - 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.
+
+Bug fixes:
+
+ - 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.
+
+tig-0.10
+---------
+
+Incompatibilities:
+
+ - 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:
+
+ - 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.
+
+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.
+
+Bug fixes:
+
+ - 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-0.9.1
+---------
+
+Incompatibilities:
+
+ - Make the clean rule to never remove generated documentation files.
+ Use the distclean rule for accomplishing this.
+
+New features:
+
+ - Add support for cherry-picking commits in the main view to the
+ current branch. Bound to 'C' by default.
+
+Improvements:
+
+ - 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.
+
+Bug fixes:
+
+ - 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`.
+
+tig-0.9
+-------
+
+New features:
+
+ - 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:
+
+ - 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. |
| |   |
| 58 | 58 | static void report(const char *msg, ...); |
| 59 | 59 | static int read_properties(FILE *pipe, const char *separators, int (*read)(char *, size_t, char *, size_t)); |
| 60 | 60 | static void set_nonblocking_input(bool loading); |
| 61 | | static size_t utf8_length(const char *string, size_t max_width, int *trimmed, bool reserve); |
| 61 | static size_t utf8_length(const char *string, int *width, size_t max_width, int *trimmed, bool reserve); |
| 62 | 62 | |
| 63 | 63 | #define ABS(x) ((x) >= 0 ? (x) : -(x)) |
| 64 | 64 | #define MIN(x, y) ((x) < (y) ? (x) : (y)) |
| … | … | |
| 77 | 77 | #define REVGRAPH_BRANCH '+' |
| 78 | 78 | #define REVGRAPH_COMMIT '*' |
| 79 | 79 | #define REVGRAPH_BOUND '^' |
| 80 | | #define REVGRAPH_LINE '|' |
| 81 | 80 | |
| 82 | 81 | #define SIZEOF_REVGRAPH 19 /* Size of revision ancestry graphics. */ |
| 83 | 82 | |
| … | … | |
| 98 | 98 | /* The default interval between line numbers. */ |
| 99 | 99 | #define NUMBER_INTERVAL 5 |
| 100 | 100 | |
| 101 | | #define TABSIZE 8 |
| 101 | #define TAB_SIZE 8 |
| 102 | 102 | |
| 103 | 103 | #define SCALE_SPLIT_VIEW(height) ((height) * 2 / 3) |
| 104 | 104 | |
| … | … | |
| 437 | 437 | static bool opt_date = TRUE; |
| 438 | 438 | static bool opt_author = TRUE; |
| 439 | 439 | static bool opt_line_number = FALSE; |
| 440 | static bool opt_line_graphics = TRUE; |
| 440 | 441 | static bool opt_rev_graph = FALSE; |
| 441 | 442 | static bool opt_show_refs = TRUE; |
| 442 | 443 | static int opt_num_interval = NUMBER_INTERVAL; |
| 443 | | static int opt_tab_size = TABSIZE; |
| 444 | static int opt_tab_size = TAB_SIZE; |
| 444 | 445 | static enum request opt_request = REQ_VIEW_MAIN; |
| 445 | 446 | static char opt_cmd[SIZEOF_STR] = ""; |
| 446 | 447 | static char opt_path[SIZEOF_STR] = ""; |
| … | … | |
| 612 | 612 | enum line_type { |
| 613 | 613 | #define LINE(type, line, fg, bg, attr) \ |
| 614 | 614 | LINE_##type |
| 615 | | LINE_INFO |
| 615 | LINE_INFO, |
| 616 | LINE_NONE |
| 616 | 617 | #undef LINE |
| 617 | 618 | }; |
| 618 | 619 | |
| … | … | |
| 732 | 732 | { KEY_UP, REQ_PREVIOUS }, |
| 733 | 733 | { KEY_DOWN, REQ_NEXT }, |
| 734 | 734 | { 'R', REQ_REFRESH }, |
| 735 | | { 'M', REQ_MAXIMIZE }, |
| 735 | { KEY_F(5), REQ_REFRESH }, |
| 736 | { 'O', REQ_MAXIMIZE }, |
| 736 | 737 | |
| 737 | 738 | /* Cursor navigation */ |
| 738 | 739 | { 'k', REQ_MOVE_UP }, |
| … | … | |
| 956 | 956 | static enum request |
| 957 | 957 | add_run_request(enum keymap keymap, int key, int argc, char **argv) |
| 958 | 958 | { |
| 959 | | struct run_request *tmp; |
| 960 | | struct run_request req = { keymap, key }; |
| 959 | struct run_request *req; |
| 960 | char cmd[SIZEOF_STR]; |
| 961 | 961 | size_t bufpos; |
| 962 | 962 | |
| 963 | 963 | for (bufpos = 0; argc > 0; argc--, argv++) |
| 964 | | if (!string_format_from(req.cmd, &bufpos, "%s ", *argv)) |
| 964 | if (!string_format_from(cmd, &bufpos, "%s ", *argv)) |
| 965 | 965 | return REQ_NONE; |
| 966 | 966 | |
| 967 | | req.cmd[bufpos - 1] = 0; |
| 968 | | |
| 969 | | tmp = realloc(run_request, (run_requests + 1) * sizeof(*run_request)); |
| 970 | | if (!tmp) |
| 967 | req = realloc(run_request, (run_requests + 1) * sizeof(*run_request)); |
| 968 | if (!req) |
| 971 | 969 | return REQ_NONE; |
| 972 | 970 | |
| 973 | | run_request = tmp; |
| 974 | | run_request[run_requests++] = req; |
| 971 | run_request = req; |
| 972 | req = &run_request[run_requests++]; |
| 973 | string_copy(req->cmd, cmd); |
| 974 | req->keymap = keymap; |
| 975 | req->key = key; |
| 975 | 976 | |
| 976 | 977 | return REQ_NONE + run_requests; |
| 977 | 978 | } |
| … | … | |
| 1129 | 1129 | return OK; |
| 1130 | 1130 | } |
| 1131 | 1131 | |
| 1132 | if (!strcmp(argv[0], "line-graphics")) { |
| 1133 | opt_line_graphics = parse_bool(argv[2]); |
| 1134 | return OK; |
| 1135 | } |
| 1136 | |
| 1132 | 1137 | if (!strcmp(argv[0], "line-number-interval")) { |
| 1133 | 1138 | opt_num_interval = atoi(argv[2]); |
| 1134 | 1139 | return OK; |
| … | … | |
| 1399 | 1399 | size_t line_size; /* Total number of used lines */ |
| 1400 | 1400 | unsigned int digits; /* Number of digits in the lines member. */ |
| 1401 | 1401 | |
| 1402 | /* Drawing */ |
| 1403 | struct line *curline; /* Line currently being drawn. */ |
| 1404 | enum line_type curtype; /* Attribute currently used for drawing. */ |
| 1405 | unsigned long col; /* Column when drawing. */ |
| 1406 | |
| 1402 | 1407 | /* Loading */ |
| 1403 | 1408 | FILE *pipe; |
| 1404 | 1409 | time_t start_time; |
| … | … | |
| 1417 | 1417 | /* Read one line; updates view->line. */ |
| 1418 | 1418 | bool (*read)(struct view *view, char *data); |
| 1419 | 1419 | /* Draw one line; @lineno must be < view->height. */ |
| 1420 | | bool (*draw)(struct view *view, struct line *line, unsigned int lineno, bool selected); |
| 1420 | bool (*draw)(struct view *view, struct line *line, unsigned int lineno); |
| 1421 | 1421 | /* Depending on view handle a special requests. */ |
| 1422 | 1422 | enum request (*request)(struct view *view, enum request request, struct line *line); |
| 1423 | 1423 | /* Search for regex in a line. */ |
| … | … | |
| 1464 | 1464 | #define view_is_displayed(view) \ |
| 1465 | 1465 | (view == display[0] || view == display[1]) |
| 1466 | 1466 | |
| 1467 | |
| 1468 | enum line_graphic { |
| 1469 | LINE_GRAPHIC_VLINE |
| 1470 | }; |
| 1471 | |
| 1472 | static int line_graphics[] = { |
| 1473 | /* LINE_GRAPHIC_VLINE: */ '|' |
| 1474 | }; |
| 1475 | |
| 1476 | static inline void |
| 1477 | set_view_attr(struct view *view, enum line_type type) |
| 1478 | { |
| 1479 | if (!view->curline->selected && view->curtype != type) { |
| 1480 | wattrset(view->win, get_line_attr(type)); |
| 1481 | wchgat(view->win, -1, 0, type, NULL); |
| 1482 | view->curtype = type; |
| 1483 | } |
| 1484 | } |
| 1485 | |
| 1467 | 1486 | static int |
| 1468 | | draw_text(struct view *view, const char *string, int max_len, |
| 1469 | | bool use_tilde, bool selected) |
| 1487 | draw_chars(struct view *view, enum line_type type, const char *string, |
| 1488 | int max_len, bool use_tilde) |
| 1470 | 1489 | { |
| 1471 | 1490 | int len = 0; |
| 1491 | int col = 0; |
| 1472 | 1492 | int trimmed = FALSE; |
| 1473 | 1493 | |
| 1474 | 1494 | if (max_len <= 0) |
| 1475 | 1495 | return 0; |
| 1476 | 1496 | |
| 1477 | 1497 | if (opt_utf8) { |
| 1478 | | len = utf8_length(string, max_len, &trimmed, use_tilde); |
| 1498 | len = utf8_length(string, &col, max_len, &trimmed, use_tilde); |
| 1479 | 1499 | } else { |
| 1480 | | len = strlen(string); |
| 1500 | col = len = strlen(string); |
| 1481 | 1501 | if (len > max_len) { |
| 1482 | 1502 | if (use_tilde) { |
| 1483 | 1503 | max_len -= 1; |
| 1484 | 1504 | } |
| 1485 | | len = max_len; |
| 1505 | col = len = max_len; |
| 1486 | 1506 | trimmed = TRUE; |
| 1487 | 1507 | } |
| 1488 | 1508 | } |
| 1489 | 1509 | |
| 1510 | set_view_attr(view, type); |
| 1490 | 1511 | waddnstr(view->win, string, len); |
| 1491 | 1512 | if (trimmed && use_tilde) { |
| 1492 | | if (!selected) |
| 1493 | | wattrset(view->win, get_line_attr(LINE_DELIMITER)); |
| 1513 | set_view_attr(view, LINE_DELIMITER); |
| 1494 | 1514 | waddch(view->win, '~'); |
| 1495 | | len++; |
| 1515 | col++; |
| 1496 | 1516 | } |
| 1497 | 1517 | |
| 1498 | | return len; |
| 1518 | return col; |
| 1499 | 1519 | } |
| 1500 | 1520 | |
| 1501 | 1521 | static int |
| 1502 | | draw_lineno(struct view *view, unsigned int lineno, int max, bool selected) |
| 1522 | draw_space(struct view *view, enum line_type type, int max, int spaces) |
| 1503 | 1523 | { |
| 1504 | | static char fmt[] = "%1ld"; |
| 1505 | | char number[10] = " "; |
| 1524 | static char space[] = " "; |
| 1525 | int col = 0; |
| 1526 | |
| 1527 | spaces = MIN(max, spaces); |
| 1528 | |
| 1529 | while (spaces > 0) { |
| 1530 | int len = MIN(spaces, sizeof(space) - 1); |
| 1531 | |
| 1532 | col += draw_chars(view, type, space, spaces, FALSE); |
| 1533 | spaces -= len; |
| 1534 | } |
| 1535 | |
| 1536 | return col; |
| 1537 | } |
| 1538 | |
| 1539 | static bool |
| 1540 | draw_lineno(struct view *view, unsigned int lineno) |
| 1541 | { |
| 1542 | char number[10]; |
| 1506 | 1543 | int digits3 = view->digits < 3 ? 3 : view->digits; |
| 1507 | 1544 | int max_number = MIN(digits3, STRING_SIZE(number)); |
| 1508 | | bool showtrimmed = FALSE; |
| 1545 | int max = view->width - view->col; |
| 1509 | 1546 | int col; |
| 1510 | 1547 | |
| 1548 | if (max < max_number) |
| 1549 | max_number = max; |
| 1550 | |
| 1511 | 1551 | lineno += view->offset + 1; |
| 1512 | 1552 | if (lineno == 1 || (lineno % opt_num_interval) == 0) { |
| 1553 | static char fmt[] = "%1ld"; |
| 1554 | |
| 1513 | 1555 | if (view->digits <= 9) |
| 1514 | 1556 | fmt[1] = '0' + digits3; |
| 1515 | 1557 | |
| 1516 | 1558 | if (!string_format(number, fmt, lineno)) |
| 1517 | 1559 | number[0] = 0; |
| 1518 | | showtrimmed = TRUE; |
| 1560 | col = draw_chars(view, LINE_LINE_NUMBER, number, max_number, TRUE); |
| 1561 | } else { |
| 1562 | col = draw_space(view, LINE_LINE_NUMBER, max_number, max_number); |
| 1519 | 1563 | } |
| 1520 | 1564 | |
| 1521 | | if (max < max_number) |
| 1522 | | max_number = max; |
| 1523 | | |
| 1524 | | if (!selected) |
| 1525 | | wattrset(view->win, get_line_attr(LINE_LINE_NUMBER)); |
| 1526 | | col = draw_text(view, number, max_number, showtrimmed, selected); |
| 1527 | 1565 | if (col < max) { |
| 1528 | | if (!selected) |
| 1529 | | wattrset(view->win, A_NORMAL); |
| 1530 | | waddch(view->win, ACS_VLINE); |
| 1566 | set_view_attr(view, LINE_DEFAULT); |
| 1567 | waddch(view->win, line_graphics[LINE_GRAPHIC_VLINE]); |
| 1531 | 1568 | col++; |
| 1532 | 1569 | } |
| 1533 | | if (col < max) { |
| 1570 | |
| 1571 | if (col < max) |
| 1572 | col += draw_space(view, LINE_DEFAULT, max - col, 1); |
| 1573 | view->col += col; |
| 1574 | |
| 1575 | return view->width - view->col <= 0; |
| 1576 | } |
| 1577 | |
| 1578 | static bool |
| 1579 | draw_text(struct view *view, enum line_type type, const char *string, bool trim) |
| 1580 | { |
| 1581 | view->col += draw_chars(view, type, string, view->width - view->col, trim); |
| 1582 | return view->width - view->col <= 0; |
| 1583 | } |
| 1584 | |
| 1585 | static bool |
| 1586 | draw_graphic(struct view *view, enum line_type type, chtype graphic[], size_t size) |
| 1587 | { |
| 1588 | int max = view->width - view->col; |
| 1589 | int i; |
| 1590 | |
| 1591 | if (max < size) |
| 1592 | size = max; |
| 1593 | |
| 1594 | set_view_attr(view, type); |
| 1595 | /* Using waddch() instead of waddnstr() ensures that |
| 1596 | * they'll be rendered correctly for the cursor line. */ |
| 1597 | for (i = 0; i < size; i++) |
| 1598 | waddch(view->win, graphic[i]); |
| 1599 | |
| 1600 | view->col += size; |
| 1601 | if (size < max) { |
| 1534 | 1602 | waddch(view->win, ' '); |
| 1535 | | col++; |
| 1603 | view->col++; |
| 1536 | 1604 | } |
| 1537 | 1605 | |
| 1538 | | return col; |
| 1606 | return view->width - view->col <= 0; |
| 1539 | 1607 | } |
| 1540 | 1608 | |
| 1541 | | static int |
| 1542 | | draw_date(struct view *view, struct tm *time, int max, bool selected) |
| 1609 | static bool |
| 1610 | draw_field(struct view *view, enum line_type type, char *text, int len, bool trim) |
| 1543 | 1611 | { |
| 1544 | | char buf[DATE_COLS]; |
| 1612 | int max = MIN(view->width - view->col, len); |
| 1545 | 1613 | int col; |
| 1614 | |
| 1615 | if (text) |
| 1616 | col = draw_chars(view, type, text, max - 1, trim); |
| 1617 | else |
| 1618 | col = draw_space(view, type, max - 1, max - 1); |
| 1619 | |
| 1620 | view->col += col + draw_space(view, LINE_DEFAULT, max - col, max - col); |
| 1621 | return view->width - view->col <= 0; |
| 1622 | } |
| 1623 | |
| 1624 | static bool |
| 1625 | draw_date(struct view *view, struct tm *time) |
| 1626 | { |
| 1627 | char buf[DATE_COLS]; |
| 1628 | char *date; |
| 1546 | 1629 | int timelen = 0; |
| 1547 | 1630 | |
| 1548 | | if (max > DATE_COLS) |
| 1549 | | max = DATE_COLS; |
| 1550 | 1631 | if (time) |
| 1551 | 1632 | timelen = strftime(buf, sizeof(buf), DATE_FORMAT, time); |
| 1552 | | if (!timelen) { |
| 1553 | | memset(buf, ' ', sizeof(buf) - 1); |
| 1554 | | buf[sizeof(buf) - 1] = 0; |
| 1555 | | } |
| 1556 | | |
| 1557 | | if (!selected) |
| 1558 | | wattrset(view->win, get_line_attr(LINE_DATE)); |
| 1559 | | col = draw_text(view, buf, max, FALSE, selected); |
| 1560 | | if (col < max) { |
| 1561 | | if (!selected) |
| 1562 | | wattrset(view->win, get_line_attr(LINE_DEFAULT)); |
| 1563 | | waddch(view->win, ' '); |
| 1564 | | col++; |
| 1565 | | } |
| 1633 | date = timelen ? buf : NULL; |
| 1566 | 1634 | |
| 1567 | | return col; |
| 1635 | return draw_field(view, LINE_DATE, date, DATE_COLS, FALSE); |
| 1568 | 1636 | } |
| 1569 | 1637 | |
| 1570 | 1638 | static bool |
| … | … | |
| 1650 | 1650 | line = &view->line[view->offset + lineno]; |
| 1651 | 1651 | |
| 1652 | 1652 | wmove(view->win, lineno, 0); |
| 1653 | view->col = 0; |
| 1654 | view->curline = line; |
| 1655 | view->curtype = LINE_NONE; |
| 1656 | line->selected = FALSE; |
| 1653 | 1657 | |
| 1654 | 1658 | if (selected) { |
| 1659 | set_view_attr(view, LINE_CURSOR); |
| 1655 | 1660 | line->selected = TRUE; |
| 1656 | 1661 | view->ops->select(view, line); |
| 1657 | | wchgat(view->win, -1, 0, LINE_CURSOR, NULL); |
| 1658 | | wattrset(view->win, get_line_attr(LINE_CURSOR)); |
| 1659 | 1662 | } else if (line->selected) { |
| 1660 | | line->selected = FALSE; |
| 1661 | 1663 | wclrtoeol(view->win); |
| 1662 | 1664 | } |
| 1663 | 1665 | |
| 1664 | 1666 | scrollok(view->win, FALSE); |
| 1665 | | draw_ok = view->ops->draw(view, line, lineno, selected); |
| 1667 | draw_ok = view->ops->draw(view, line, lineno); |
| 1666 | 1668 | scrollok(view->win, TRUE); |
| 1667 | 1669 | |
| 1668 | 1670 | return draw_ok; |
| … | … | |
| 2423 | 2423 | OPEN_SPLIT = 1, /* Split current view. */ |
| 2424 | 2424 | OPEN_BACKGROUNDED = 2, /* Backgrounded. */ |
| 2425 | 2425 | OPEN_RELOAD = 4, /* Reload view even if it is the current. */ |
| 2426 | | OPEN_NOMAXIMIZE = 8, /* Do not maximize the current view. */ |
| 2426 | OPEN_NOMAXIMIZE = 8 /* Do not maximize the current view. */ |
| 2427 | 2427 | }; |
| 2428 | 2428 | |
| 2429 | 2429 | static void |
| … | … | |
| 2863 | 2863 | */ |
| 2864 | 2864 | |
| 2865 | 2865 | static bool |
| 2866 | | pager_draw(struct view *view, struct line *line, unsigned int lineno, bool selected) |
| 2866 | pager_draw(struct view *view, struct line *line, unsigned int lineno) |
| 2867 | 2867 | { |
| 2868 | | static char spaces[] = " "; |
| 2869 | 2868 | char *text = line->data; |
| 2870 | | int col = 0; |
| 2871 | | |
| 2872 | | if (opt_line_number) { |
| 2873 | | col += draw_lineno(view, lineno, view->width, selected); |
| 2874 | | if (col >= view->width) |
| 2875 | | return TRUE; |
| 2876 | | } |
| 2877 | | |
| 2878 | | if (!selected) |
| 2879 | | wattrset(view->win, get_line_attr(line->type)); |
| 2880 | | |
| 2881 | | if (opt_tab_size < TABSIZE) { |
| 2882 | | int col_offset = col; |
| 2883 | | |
| 2884 | | col = 0; |
| 2885 | | while (text && col_offset + col < view->width) { |
| 2886 | | int cols_max = view->width - col_offset - col; |
| 2887 | | char *pos = text; |
| 2888 | | int cols; |
| 2889 | | |
| 2890 | | if (*text == '\t') { |
| 2891 | | text++; |
| 2892 | | assert(sizeof(spaces) > TABSIZE); |
| 2893 | | pos = spaces; |
| 2894 | | cols = opt_tab_size - (col % opt_tab_size); |
| 2895 | | |
| 2896 | | } else { |
| 2897 | | text = strchr(text, '\t'); |
| 2898 | | cols = line ? text - pos : strlen(pos); |
| 2899 | | } |
| 2900 | | |
| 2901 | | waddnstr(view->win, pos, MIN(cols, cols_max)); |
| 2902 | | col += cols; |
| 2903 | | } |
| 2904 | 2869 | |
| 2905 | | } else { |
| 2906 | | draw_text(view, text, view->width - col, TRUE, selected); |
| 2907 | | } |
| 2870 | if (opt_line_number && draw_lineno(view, lineno)) |
| 2871 | return TRUE; |
| 2908 | 2872 | |
| 2873 | draw_text(view, line->type, text, TRUE); |
| 2909 | 2874 | return TRUE; |
| 2910 | 2875 | } |
| 2911 | 2876 | |
| … | … | |
| 3654 | 3654 | } |
| 3655 | 3655 | |
| 3656 | 3656 | static bool |
| 3657 | | blame_draw(struct view *view, struct line *line, unsigned int lineno, bool selected) |
| 3657 | blame_draw(struct view *view, struct line *line, unsigned int lineno) |
| 3658 | 3658 | { |
| 3659 | 3659 | struct blame *blame = line->data; |
| 3660 | | int col = 0; |
| 3661 | | |
| 3662 | | if (opt_date) { |
| 3663 | | struct tm *time = blame->commit && *blame->commit->filename |
| 3664 | | ? &blame->commit->time : NULL; |
| 3660 | struct tm *time = NULL; |
| 3661 | char *id = NULL, *author = NULL; |
| 3665 | 3662 | |
| 3666 | | col += draw_date(view, time, view->width, selected); |
| 3667 | | if (col >= view->width) |
| 3668 | | return TRUE; |
| 3663 | if (blame->commit && *blame->commit->filename) { |
| 3664 | id = blame->commit->id; |
| 3665 | author = blame->commit->author; |
| 3666 | time = &blame->commit->time; |
| 3669 | 3667 | } |
| 3670 | 3668 | |
| 3671 | | if (opt_author) { |
| 3672 | | int max = MIN(AUTHOR_COLS - 1, view->width - col); |
| 3669 | if (opt_date && draw_date(view, time)) |
| 3670 | return TRUE; |
| 3673 | 3671 | |
| 3674 | | if (!selected) |
| 3675 | | wattrset(view->win, get_line_attr(LINE_MAIN_AUTHOR)); |
| 3676 | | if (blame->commit) |
| 3677 | | draw_text(view, blame->commit->author, max, TRUE, selected); |
| 3678 | | col += AUTHOR_COLS; |
| 3679 | | if (col >= view->width) |
| 3680 | | return TRUE; |
| 3681 | | wmove(view->win, lineno, col); |
| 3682 | | } |
| 3672 | if (opt_author && |
| 3673 | draw_field(view, LINE_MAIN_AUTHOR, author, AUTHOR_COLS, TRUE)) |
| 3674 | return TRUE; |
| 3683 | 3675 | |
| 3684 | | { |
| 3685 | | int max = MIN(ID_COLS - 1, view->width - col); |
| 3686 | | |
| 3687 | | if (!selected) |
| 3688 | | wattrset(view->win, get_line_attr(LINE_BLAME_ID)); |
| 3689 | | if (blame->commit) |
| 3690 | | draw_text(view, blame->commit->id, max, FALSE, -1); |
| 3691 | | col += ID_COLS; |
| 3692 | | if (col >= view->width) |
| 3693 | | return TRUE; |
| 3694 | | wmove(view->win, lineno, col); |
| 3695 | | } |
| 3676 | if (draw_field(view, LINE_BLAME_ID, id, ID_COLS, FALSE)) |
| 3677 | return TRUE; |
| 3696 | 3678 | |
| 3697 | | col += draw_lineno(view, lineno, view->width - col, selected); |
| 3698 | | if (col >= view->width) |
| 3679 | if (draw_lineno(view, lineno)) |
| 3699 | 3680 | return TRUE; |
| 3700 | 3681 | |
| 3701 | | col += draw_text(view, blame->text, view->width - col, TRUE, selected); |
| 3682 | draw_text(view, LINE_DEFAULT, blame->text, TRUE); |
| 3702 | 3683 | return TRUE; |
| 3703 | 3684 | } |
| 3704 | 3685 | |
| … | … | |
| 3721 | 3721 | struct blame_commit *commit = blame->commit; |
| 3722 | 3722 | regmatch_t pmatch; |
| 3723 | 3723 | |
| 3724 | | #define MATCH(text) \ |
| 3725 | | (*text && regexec(view->regex, text, 1, &pmatch, 0) != REG_NOMATCH) |
| 3724 | #define MATCH(text, on) \ |
| 3725 | (on && *text && regexec(view->regex, text, 1, &pmatch, 0) != REG_NOMATCH) |
| 3726 | 3726 | |
| 3727 | 3727 | if (commit) { |
| 3728 | 3728 | char buf[DATE_COLS + 1]; |
| 3729 | 3729 | |
| 3730 | | if (MATCH(commit->title) || |
| 3731 | | MATCH(commit->author) || |
| 3732 | | MATCH(commit->id)) |
| 3730 | if (MATCH(commit->title, 1) || |
| 3731 | MATCH(commit->author, opt_author) || |
| 3732 | MATCH(commit->id, opt_date)) |
| 3733 | 3733 | return TRUE; |
| 3734 | 3734 | |
| 3735 | 3735 | if (strftime(buf, sizeof(buf), DATE_FORMAT, &commit->time) && |
| 3736 | | MATCH(buf)) |
| 3736 | MATCH(buf, 1)) |
| 3737 | 3737 | return TRUE; |
| 3738 | 3738 | } |
| 3739 | 3739 | |
| 3740 | | return MATCH(blame->text); |
| 3740 | return MATCH(blame->text, 1); |
| 3741 | 3741 | |
| 3742 | 3742 | #undef MATCH |
| 3743 | 3743 | } |
| … | … | |
| 4006 | 4006 | return FALSE; |
| 4007 | 4007 | } |
| 4008 | 4008 | |
| 4009 | | system("git update-index -q --refresh 2>/dev/null"); |
| 4009 | system("git update-index -q --refresh >/dev/null 2>/dev/null"); |
| 4010 | 4010 | |
| 4011 | 4011 | if (!status_run(view, indexcmd, indexstatus, LINE_STAT_STAGED) || |
| 4012 | 4012 | !status_run(view, STATUS_DIFF_FILES_CMD, 0, LINE_STAT_UNSTAGED) || |
| … | … | |
| 4038 | 4038 | } |
| 4039 | 4039 | |
| 4040 | 4040 | static bool |
| 4041 | | status_draw(struct view *view, struct line *line, unsigned int lineno, bool selected) |
| 4041 | status_draw(struct view *view, struct line *line, unsigned int lineno) |
| 4042 | 4042 | { |
| 4043 | 4043 | struct status *status = line->data; |
| 4044 | enum line_type type; |
| 4044 | 4045 | char *text; |
| 4045 | | int col = 0; |
| 4046 | | |
| 4047 | | if (selected) { |
| 4048 | | /* No attributes. */ |
| 4049 | | |
| 4050 | | } else if (line->type == LINE_STAT_HEAD) { |
| 4051 | | wattrset(view->win, get_line_attr(LINE_STAT_HEAD)); |
| 4052 | | wchgat(view->win, -1, 0, LINE_STAT_HEAD, NULL); |
| 4053 | | |
| 4054 | | } else if (!status && line->type != LINE_STAT_NONE) { |
| 4055 | | wattrset(view->win, get_line_attr(LINE_STAT_SECTION)); |
| 4056 | | wchgat(view->win, -1, 0, LINE_STAT_SECTION, NULL); |
| 4057 | | |
| 4058 | | } else { |
| 4059 | | wattrset(view->win, get_line_attr(line->type)); |
| 4060 | | } |
| 4061 | 4046 | |
| 4062 | 4047 | if (!status) { |
| 4063 | 4048 | switch (line->type) { |
| 4064 | 4049 | case LINE_STAT_STAGED: |
| 4050 | type = LINE_STAT_SECTION; |
| 4065 | 4051 | text = "Changes to be committed:"; |
| 4066 | 4052 | break; |
| 4067 | 4053 | |
| 4068 | 4054 | case LINE_STAT_UNSTAGED: |
| 4055 | type = LINE_STAT_SECTION; |
| 4069 | 4056 | text = "Changed but not updated:"; |
| 4070 | 4057 | break; |
| 4071 | 4058 | |
| 4072 | 4059 | case LINE_STAT_UNTRACKED: |
| 4060 | type = LINE_STAT_SECTION; |
| 4073 | 4061 | text = "Untracked files:"; |
| 4074 | 4062 | break; |
| 4075 | 4063 | |
| 4076 | 4064 | case LINE_STAT_NONE: |
| 4065 | type = LINE_DEFAULT; |
| 4077 | 4066 | text = " (no files)"; |
| 4078 | 4067 | break; |
| 4079 | 4068 | |
| 4080 | 4069 | case LINE_STAT_HEAD: |
| 4070 | type = LINE_STAT_HEAD; |
| 4081 | 4071 | text = status_onbranch; |
| 4082 | 4072 | break; |
| 4083 | 4073 | |
<