mirror of https://github.com/ericonr/ep.git
Add framework to display detected programming languages.
Very dumb initial C detection.
This commit is contained in:
parent
c7a24d775d
commit
81c7f243a7
2
Makefile
2
Makefile
|
@ -13,7 +13,7 @@ bindir = $(PREFIX)/bin
|
||||||
|
|
||||||
all: ep
|
all: ep
|
||||||
|
|
||||||
ep: ep.c out.c path.c git.c $(LANGUAGE)
|
ep: ep.c out.c path.c git.c lang.c $(LANGUAGE)
|
||||||
|
|
||||||
install: ep
|
install: ep
|
||||||
install -m755 $< $(bindir)/ep
|
install -m755 $< $(bindir)/ep
|
||||||
|
|
17
ep.c
17
ep.c
|
@ -46,9 +46,17 @@ int main(int argc, char **argv)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* start threads for long(er) running steps */
|
/* start threads for long(er) running steps */
|
||||||
|
struct threaded_task root_lang_task = { .task = task_launch_root_lang };
|
||||||
pthread_t git_handle;
|
pthread_t git_handle;
|
||||||
if (pthread_create(&git_handle, NULL, git_thread, NULL)) {
|
if (pthread_create(&git_handle, NULL, git_thread, &root_lang_task)) {
|
||||||
e(WARN, "couldn't create git thread", errno);
|
e(ERROR, "couldn't create git thread", errno);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_t pwd_lang_handle;
|
||||||
|
if (pthread_create(&pwd_lang_handle, NULL, lang_thread, NULL)) {
|
||||||
|
e(ERROR, "couldn't create lang thread", errno);
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (chroot)
|
if (chroot)
|
||||||
|
@ -69,6 +77,11 @@ int main(int argc, char **argv)
|
||||||
pthread_join(git_handle, NULL);
|
pthread_join(git_handle, NULL);
|
||||||
print_git();
|
print_git();
|
||||||
|
|
||||||
|
/* programming languages */
|
||||||
|
pthread_join(pwd_lang_handle, NULL);
|
||||||
|
if (root_lang_task.launched) pthread_join(root_lang_task.handle, NULL);
|
||||||
|
print_lang();
|
||||||
|
|
||||||
/* print currently active shell jobs */
|
/* print currently active shell jobs */
|
||||||
if (shell_jobs) {
|
if (shell_jobs) {
|
||||||
int n = atoi(shell_jobs);
|
int n = atoi(shell_jobs);
|
||||||
|
|
16
ep.h
16
ep.h
|
@ -2,6 +2,18 @@
|
||||||
#define EP_H
|
#define EP_H
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
|
enum task_identity {
|
||||||
|
task_launch_root_lang,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct threaded_task {
|
||||||
|
pthread_t handle;
|
||||||
|
sig_atomic_t launched;
|
||||||
|
enum task_identity task;
|
||||||
|
};
|
||||||
|
|
||||||
/* from out.c */
|
/* from out.c */
|
||||||
extern FILE *out, *outerr;
|
extern FILE *out, *outerr;
|
||||||
|
@ -18,4 +30,8 @@ void print_pwd(const char *);
|
||||||
void *git_thread(void *);
|
void *git_thread(void *);
|
||||||
void print_git(void);
|
void print_git(void);
|
||||||
|
|
||||||
|
/* from lang.c */
|
||||||
|
void *lang_thread(void *);
|
||||||
|
void print_lang(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
51
git.c
51
git.c
|
@ -1,10 +1,11 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
#include "ep.h"
|
#include "ep.h"
|
||||||
|
|
||||||
static char *git_branch_name, *git_status;
|
static char *git_branch_name, *git_status, *git_root;
|
||||||
void print_git(void)
|
void print_git(void)
|
||||||
{
|
{
|
||||||
if (git_branch_name) {
|
if (git_branch_name) {
|
||||||
|
@ -26,20 +27,29 @@ struct rlfc_data {
|
||||||
int status;
|
int status;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void read_line_from_command(const char *c, struct rlfc_data *d)
|
static void read_line_from_command(const char *cmd, struct rlfc_data *d)
|
||||||
{
|
{
|
||||||
FILE *f = popen("git rev-parse --abbrev-ref HEAD 2>/dev/null", "re");
|
FILE *f = popen(cmd, "re");
|
||||||
if (!f)
|
if (!f)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
d->l = getline(&d->line, &d->n, f);
|
d->l = getline(&d->line, &d->n, f);
|
||||||
d->status = pclose(f);
|
d->status = pclose(f);
|
||||||
|
|
||||||
|
if (d->l > 0) {
|
||||||
|
d->line[d->l-1] = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *get_git_status(void);
|
static void *get_git_status(void *);
|
||||||
|
static void *get_git_root(void *);
|
||||||
|
|
||||||
void *git_thread(void *arg)
|
void *git_thread(void *arg)
|
||||||
{
|
{
|
||||||
|
struct threaded_task *root_lang_task = arg;
|
||||||
|
/* only knows how to launch this task */
|
||||||
|
if (root_lang_task->task != task_launch_root_lang) root_lang_task = NULL;
|
||||||
|
|
||||||
struct rlfc_data c = { 0 };
|
struct rlfc_data c = { 0 };
|
||||||
read_line_from_command("git rev-parse --abbrev-ref HEAD 2>/dev/null", &c);
|
read_line_from_command("git rev-parse --abbrev-ref HEAD 2>/dev/null", &c);
|
||||||
|
|
||||||
|
@ -48,7 +58,7 @@ void *git_thread(void *arg)
|
||||||
|
|
||||||
if (c.l > 0) {
|
if (c.l > 0) {
|
||||||
/* TODO: treat case where it reads HEAD */
|
/* TODO: treat case where it reads HEAD */
|
||||||
c.line[c.l-1] = 0;
|
|
||||||
/* line ownserhip goes to outside this function */
|
/* line ownserhip goes to outside this function */
|
||||||
git_branch_name = c.line;
|
git_branch_name = c.line;
|
||||||
}
|
}
|
||||||
|
@ -59,8 +69,20 @@ void *git_thread(void *arg)
|
||||||
/* since we are in a repo, read git status;
|
/* since we are in a repo, read git status;
|
||||||
* if we add more stuff to do in repos, launch more threads */
|
* if we add more stuff to do in repos, launch more threads */
|
||||||
|
|
||||||
get_git_status();
|
pthread_t status_handle, root_handle;
|
||||||
|
if (pthread_create(&status_handle, NULL, get_git_status, NULL))
|
||||||
|
goto status_create_error;
|
||||||
|
if (pthread_create(&root_handle, NULL, get_git_root, NULL))
|
||||||
|
goto root_create_error;
|
||||||
|
|
||||||
|
void *local_git_root;
|
||||||
|
pthread_join(root_handle, &local_git_root);
|
||||||
|
if (root_lang_task) {
|
||||||
|
root_lang_task->launched = !pthread_create(&root_lang_task->handle, NULL, lang_thread, local_git_root);
|
||||||
|
}
|
||||||
|
root_create_error:
|
||||||
|
pthread_join(status_handle, NULL);
|
||||||
|
status_create_error:
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,8 +94,10 @@ struct statuses {
|
||||||
};
|
};
|
||||||
enum status_index { added, deleted, modified_unstaged, modified_staged, untracked, status_index_n };
|
enum status_index { added, deleted, modified_unstaged, modified_staged, untracked, status_index_n };
|
||||||
|
|
||||||
static char *get_git_status(void)
|
static void *get_git_status(void *arg)
|
||||||
{
|
{
|
||||||
|
(void)arg;
|
||||||
|
|
||||||
FILE *f = popen("git status --porcelain=v1 -z 2>/dev/null", "re");
|
FILE *f = popen("git status --porcelain=v1 -z 2>/dev/null", "re");
|
||||||
if (!f)
|
if (!f)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -116,3 +140,16 @@ static char *get_git_status(void)
|
||||||
|
|
||||||
return git_status;
|
return git_status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void *get_git_root(void *arg)
|
||||||
|
{
|
||||||
|
(void)arg;
|
||||||
|
|
||||||
|
struct rlfc_data c = { 0 };
|
||||||
|
read_line_from_command("git rev-parse --show-toplevel 2>/dev/null", &c);
|
||||||
|
|
||||||
|
if (c.l > 0)
|
||||||
|
git_root = c.line;
|
||||||
|
|
||||||
|
return git_root;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,67 @@
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <fnmatch.h>
|
||||||
|
|
||||||
|
#include "ep.h"
|
||||||
|
|
||||||
|
enum lang_index {
|
||||||
|
c_lang,
|
||||||
|
//cpp_lang,
|
||||||
|
//python_lang,
|
||||||
|
//go_lang,
|
||||||
|
lang_index_n
|
||||||
|
};
|
||||||
|
static int c_lang_check(const char *, unsigned char);
|
||||||
|
|
||||||
|
struct lang_check {
|
||||||
|
int (*check)(const char *, unsigned char);
|
||||||
|
char display[8];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct lang_check l[] = {
|
||||||
|
[c_lang] = { .check = c_lang_check, .display = " C" },
|
||||||
|
};
|
||||||
|
|
||||||
|
/* bitmap of 1<<lang_index */
|
||||||
|
static uint64_t pwd_langs, root_langs;
|
||||||
|
|
||||||
|
void print_lang(void) {
|
||||||
|
uint64_t mask = pwd_langs | root_langs;
|
||||||
|
|
||||||
|
for (int i = 0; i < lang_index_n; i++) {
|
||||||
|
if (mask & (1 << i)) {
|
||||||
|
p(l[i].display);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void *lang_thread(void *arg)
|
||||||
|
{
|
||||||
|
/* scan current dir or received root of project */
|
||||||
|
char *path = arg ? arg : ".";
|
||||||
|
uint64_t *mask = arg ? &root_langs : &pwd_langs;
|
||||||
|
|
||||||
|
DIR *d = opendir(path);
|
||||||
|
if (!d)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
struct dirent *item;
|
||||||
|
while ((item = readdir(d))) {
|
||||||
|
for (int i = 0; i < lang_index_n; i++) {
|
||||||
|
/* skip if language has already been detected */
|
||||||
|
if (*mask & (1 << i))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
*mask |= l[i].check(item->d_name, item->d_type) << i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int isfile(unsigned char t) { return t & (DT_REG | DT_LNK); }
|
||||||
|
|
||||||
|
static int c_lang_check(const char *s, unsigned char t)
|
||||||
|
{
|
||||||
|
return isfile(t) && !fnmatch("*.c", s, 0);
|
||||||
|
}
|
Loading…
Reference in New Issue