Skip to content

Commit

Permalink
Add git status column to detail view
Browse files Browse the repository at this point in the history
  • Loading branch information
luukvbaal committed Jun 24, 2021
1 parent 73a175c commit 10da9e1
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 8 deletions.
4 changes: 0 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,6 @@ O_NOX11 := 0 # disable X11 integration
O_GITSTATUS := 0 # add git status to detail view
O_NAMEFIRST := 0 # print file name first, add uid and guid to detail view

ifeq ($(strip $(O_GITSTATUS)),1)
LDLIBS += -lgit2
endif

# convert targets to flags for backwards compatibility
ifneq ($(filter debug,$(MAKECMDGOALS)),)
O_DEBUG := 1
Expand Down
91 changes: 87 additions & 4 deletions src/nnn.c
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,7 @@ typedef struct entry {
uid_t uid; /* 4 bytes */
gid_t gid; /* 4 bytes */
#endif
char git_status[2];
} *pEntry;

/* Key-value pairs from env */
Expand Down Expand Up @@ -319,6 +320,7 @@ typedef struct {
uint_t cliopener : 1; /* All-CLI app opener */
uint_t waitedit : 1; /* For ops that can't be detached, used EDITOR */
uint_t rollover : 1; /* Roll over at edges */
uint_t normalgit : 1; /* Show git status in normal mode */
} settings;

/* Non-persistent program-internal states (alphabeical order) */
Expand Down Expand Up @@ -368,7 +370,19 @@ typedef struct {
} session_header_t;
#endif

typedef struct {
char path[PATH_MAX];
char status[2];
} simple_git_status_t;

typedef struct {
simple_git_status_t *statuses;
size_t len;
bool show;
} simple_git_statuses_t;

/* GLOBALS */
simple_git_statuses_t git_statuses;

/* Configuration, contexts */
static settings cfg = {
Expand Down Expand Up @@ -399,6 +413,7 @@ static settings cfg = {
0, /* cliopener */
0, /* waitedit */
1, /* rollover */
0, /* normalgit */
};

static context g_ctx[CTX_MAX] __attribute__ ((aligned));
Expand Down Expand Up @@ -3506,6 +3521,37 @@ static char *get_kv_val(kv *kvarr, char *buf, int key, uchar_t max, uchar_t id)
return NULL;
}

static size_t get_git_statuses(void) {
FILE *fp = popen("git rev-parse --show-toplevel 2>/dev/null", "r");
static char workdir[PATH_MAX];

fgets(workdir, PATH_MAX, fp);
pclose(fp);

if (!workdir[0])
return 0;

git_statuses.show = FALSE;
workdir[xstrlen(workdir) - 1] = '\0';
fp = popen("git -c core.quotePath=false status --porcelain --ignored=matching -uall 2>/dev/null", "r");

size_t i = -1;
char entry[PATH_MAX], *pathptr;

while (fgets(entry, PATH_MAX, fp) != NULL) {
size_t pathindex = (entry[3] == '"') ? 4 : 3;
entry[xstrlen(entry) - pathindex + 2] = '\0';
pathptr = entry + pathindex;
git_statuses.statuses = xrealloc(git_statuses.statuses, sizeof(simple_git_status_t) * (++i + 1));
git_statuses.statuses[i].status[0] = (entry[0] == ' ') ? '-' : entry[0];
git_statuses.statuses[i].status[1] = (entry[1] == ' ') ? '-' : entry[1];
mkpath(workdir, pathptr, git_statuses.statuses[i].path);
}

pclose(fp);
return ++i;
}

static void resetdircolor(int flags)
{
/* Directories are always shown on top, clear the color when moving to first file */
Expand Down Expand Up @@ -3843,6 +3889,10 @@ static void printent(const struct entry *ent, uint_t namecols, bool sel)

uchar_t color_pair = get_color_pair_name_ind(ent, &ind, &attrs);

if (git_statuses.show && (cfg.showdetail || cfg.normalgit))
printw("%*s%c%c", (cfg.normalgit && !cfg.showdetail) ? 1 : 0, "",
ent->git_status[0], ent->git_status[1]);

addch((ent->flags & FILE_SELECTED) ? '+' | A_REVERSE | A_BOLD : ' ');

if (g_state.oldcolor)
Expand Down Expand Up @@ -5171,6 +5221,10 @@ static int dentfill(char *path, struct entry **ppdents)
attron(COLOR_PAIR(cfg.curctx + 1));
}

char linkpath[PATH_MAX];
if ((git_statuses.len = get_git_statuses()))
realpath(path, linkpath);

#if _POSIX_C_SOURCE >= 200112L
posix_fadvise(fd, 0, 0, POSIX_FADV_SEQUENTIAL);
#endif
Expand Down Expand Up @@ -5369,6 +5423,30 @@ static int dentfill(char *path, struct entry **ppdents)
#endif
}

if (git_statuses.len) {
char dentpath[PATH_MAX];
size_t pathlen = mkpath(linkpath, dentp->name, dentpath) - 1;
dentp->git_status[0] = dentp->git_status[1] = '-';

if (dentp->flags & DIR_OR_DIRLNK) for (size_t i = 0; i < git_statuses.len; ++i) {
if (is_prefix(git_statuses.statuses[i].path, dentpath, pathlen)) {
dentp->git_status[0] = git_statuses.statuses[i].status[0];
if ((dentp->git_status[1] = git_statuses.statuses[i].status[1]) != '!') {
git_statuses.show = TRUE;
if (dentp->git_status[0] == '?')
break;
}
}
} else for (size_t i = 0; i < git_statuses.len; ++i) {
if (!xstrcmp(git_statuses.statuses[i].path, dentpath)) {
dentp->git_status[0] = git_statuses.statuses[i].status[0];
if ((dentp->git_status[1] = git_statuses.statuses[i].status[1]) != '!')
git_statuses.show = TRUE;
break;
}
}
}

++ndents;
} while ((dp = readdir(dirp)));

Expand Down Expand Up @@ -5885,16 +5963,16 @@ static int adjust_cols(int n)
#endif
if (cfg.showdetail) {
/* Fallback to light mode if less than 35 columns */
if (n < 36)
if (n < 38)
cfg.showdetail ^= 1;
else {
/* 2 more accounted for below */
n -= 32;
n -= 34;
}
}

/* 2 columns for preceding space and indicator */
return (n - 2);
return (n - ((git_statuses.show && (cfg.normalgit && !cfg.showdetail)) ? 5 : 2));
}

static void draw_line(char *path, int ncols)
Expand Down Expand Up @@ -7638,6 +7716,7 @@ static void usage(void)
" -F val fifo mode [0:preview 1:explore]\n"
#endif
" -g regex filters\n"
" -G always show git status\n"
" -H show hidden files\n"
" -J no auto-proceed on select\n"
" -K detect key collision\n"
Expand Down Expand Up @@ -7776,6 +7855,7 @@ static void cleanup(void)
fflush(stdout);
}
#endif
free(git_statuses.statuses);
free(selpath);
free(plgpath);
free(cfgpath);
Expand Down Expand Up @@ -7819,7 +7899,7 @@ int main(int argc, char *argv[])

while ((opt = (env_opts_id > 0
? env_opts[--env_opts_id]
: getopt(argc, argv, "aAb:cCdDeEfF:gHJKl:nop:P:QrRs:St:T:uUVwxh"))) != -1) {
: getopt(argc, argv, "aAb:cCdDeEfF:gGHJKl:nop:P:QrRs:St:T:uUVwxh"))) != -1) {
switch (opt) {
#ifndef NOFIFO
case 'a':
Expand Down Expand Up @@ -7870,6 +7950,9 @@ int main(int argc, char *argv[])
cfg.regex = 1;
filterfn = &visible_re;
break;
case 'G':
cfg.normalgit = 1;
break;
case 'H':
cfg.showhidden = 1;
break;
Expand Down

0 comments on commit 10da9e1

Please sign in to comment.