Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,7 @@ TIG_OBJS = \
src/grep.o \
src/ui.o \
src/apps.o \
src/ansi.o \
$(GRAPH_OBJS) \
$(COMPAT_OBJS)

Expand All @@ -374,10 +375,13 @@ src/tig: $(TIG_OBJS)
TEST_GRAPH_OBJS = test/tools/test-graph.o src/string.o src/util.o src/io.o $(GRAPH_OBJS) $(COMPAT_OBJS)
test/tools/test-graph: $(TEST_GRAPH_OBJS)

TEST_ANSI_OBJS = test/tools/test-ansi.o src/ansi.o $(COMPAT_OBJS)
test/tools/test-ansi: $(TEST_ANSI_OBJS)

DOC_GEN_OBJS = tools/doc-gen.o src/string.o src/types.o src/util.o src/request.o $(COMPAT_OBJS)
tools/doc-gen: $(DOC_GEN_OBJS)

OBJS = $(sort $(TIG_OBJS) $(TEST_GRAPH_OBJS) $(DOC_GEN_OBJS))
OBJS = $(sort $(TIG_OBJS) $(TEST_GRAPH_OBJS) $(TEST_ANSI_OBJS) $(DOC_GEN_OBJS))

DEPS_CFLAGS ?= -MMD -MP -MF .deps/$*.d

Expand Down
17 changes: 17 additions & 0 deletions doc/tigrc.5.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,23 @@ The following variables can be set:
regions are governed by `color diff-add-highlight` and
`color diff-del-highlight`.

'syntax-highlight' (mixed)::

Whether to syntax-highlight file contents in diff, stage, blob, and
pager views using an external highlighter. Defaults to false. When set
to true then 'bat' is used, else the option value is used as the path
to the highlighter command. Requires a terminal with 256-color support
(TERM=xterm-256color or equivalent); silently disabled on terminals
with fewer than 256 colors. +
+
When enabled, diff views show syntax-colored code on dark green
(additions) or dark red (deletions) backgrounds. Can be combined with
'diff-highlight' for intra-line change emphasis. Long lines are wrapped
with a 2-space indent on continuation lines. +
+
The highlighter must accept `--color=always --style=plain --paging=never
--file-name=<name> -` arguments and read from stdin.

'diff-indicator' (bool)::

Show +/- signs in the diff view. On by default.
Expand Down
65 changes: 65 additions & 0 deletions include/tig/ansi.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/* Copyright (c) 2006-2026 Jonas Fonseca <jonas.fonseca@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/

#ifndef TIG_ANSI_H
#define TIG_ANSI_H

#include "tig/tig.h"

#define ANSI_MAX_SPANS 512

enum ansi_color_type {
ANSI_COLOR_DEFAULT,
ANSI_COLOR_BASIC, /* 0-7: standard ANSI colors */
ANSI_COLOR_256, /* 0-255: extended palette */
ANSI_COLOR_RGB /* 24-bit truecolor */
};

struct ansi_color {
enum ansi_color_type type;
union {
int index;
struct { unsigned char r, g, b; } rgb;
};
};

struct ansi_span {
struct ansi_color fg;
struct ansi_color bg;
int attr; /* ncurses attributes: A_BOLD, A_UNDERLINE, etc. */
size_t offset; /* byte offset in stripped text */
size_t length; /* byte length of this span */
};

/*
* Parse a line containing ANSI escape sequences.
*
* Strips escape codes from `raw` and writes plain text to `stripped`.
* Records color/attribute spans in `spans`.
*
* Returns the number of spans written, or -1 on error.
*/
int ansi_parse_line(const char *raw, char *stripped, size_t stripped_size,
struct ansi_span *spans, int max_spans);

/*
* Returns true if the string contains ANSI escape sequences.
*/
static inline bool
ansi_has_escapes(const char *text)
{
return text && strchr(text, 0x1b) != NULL;
}

#endif
/* vim: set ts=8 sw=8 noexpandtab: */
6 changes: 6 additions & 0 deletions include/tig/apps.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@ struct app_external {

struct app_external *app_diff_highlight_load(const char *query);

/*
* syntax-highlight (bat)
*/

struct app_external *app_syntax_highlight_load(const char *query, const char *filename);

#endif

/* vim: set ts=8 sw=8 noexpandtab: */
8 changes: 8 additions & 0 deletions include/tig/diff.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ struct diff_state {
unsigned int lineno;
struct position pos;
struct io view_io;
/* Syntax highlighting state */
bool syntax_highlight;
char syntax_file[SIZEOF_STR]; /* Current file from diff +++ header */
pid_t syntax_pid; /* Persistent bat process */
int syntax_write_fd; /* Write content to bat stdin */
FILE *syntax_read_fp; /* Read highlighted output from bat stdout */
};

enum request diff_common_edit(struct view *view, enum request request, struct line *line);
Expand All @@ -41,6 +47,8 @@ void diff_save_line(struct view *view, struct diff_state *state, enum open_flags
void diff_restore_line(struct view *view, struct diff_state *state);
enum status_code diff_init_highlight(struct view *view, struct diff_state *state);
bool diff_done_highlight(struct diff_state *state);
void diff_init_syntax_highlight(struct diff_state *state);
void diff_done_syntax_highlight(struct diff_state *state);

unsigned int diff_get_lineno(struct view *view, struct line *line, bool old);
const char *diff_get_pathname(struct view *view, struct line *line, bool old);
Expand Down
7 changes: 7 additions & 0 deletions include/tig/line.h
Original file line number Diff line number Diff line change
Expand Up @@ -154,5 +154,12 @@ get_line_attr(const char *prefix, enum line_type type)
return COLOR_PAIR(COLOR_ID(info->color_pair)) | info->attr;
}

/*
* Dynamic color pair allocation for syntax highlighting.
*/
struct ansi_color;
int ansi_color_to_ncurses(const struct ansi_color *color);
int get_dynamic_color_pair(const struct ansi_color *fg, const struct ansi_color *bg);

#endif
/* vim: set ts=8 sw=8 noexpandtab: */
1 change: 1 addition & 0 deletions include/tig/options.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ typedef struct view_column *view_settings;
_(status_show_untracked_dirs, bool, VIEW_STATUS_LIKE) \
_(status_show_untracked_files, bool, VIEW_STATUS_LIKE) \
_(status_view, view_settings, VIEW_NO_FLAGS) \
_(syntax_highlight, const char *, VIEW_NO_FLAGS) \
_(tab_size, int, VIEW_NO_FLAGS) \
_(tree_view, view_settings, VIEW_NO_FLAGS) \
_(truncation_delimiter, const char *, VIEW_NO_FLAGS) \
Expand Down
3 changes: 3 additions & 0 deletions include/tig/view.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ struct view_ops;
struct box_cell {
enum line_type type;
size_t length;
unsigned int direct : 1; /* If set, use color_pair/attr directly */
int color_pair; /* Dynamic ncurses color pair ID */
int attr; /* A_BOLD | A_UNDERLINE | ... */
};

struct box {
Expand Down
Loading
Loading