bim: update to 1.6.1, and include tags

This commit is contained in:
K. Lange 2019-07-09 21:18:20 +09:00
parent ee293eaa59
commit fec073784a
4 changed files with 220 additions and 5 deletions

1
.gitignore vendored
View File

@ -4,6 +4,7 @@
*.iso
*.efi
.gdb_history
/tags
/.make/*
/base/bin/*

View File

@ -55,6 +55,12 @@ LIBS=$(patsubst lib/%.c,%,$(wildcard lib/*.c))
LIBS_X=$(foreach lib,$(LIBS),base/lib/libtoaru_$(lib).so)
LIBS_Y=$(foreach lib,$(LIBS),.make/$(lib).lmak)
SOURCE_FILES = $(wildcard kernel/*.c kernel/*/*.c kernel/*/*/*.c modules/*.c)
SOURCE_FILES += $(wildcard apps/*.c linker/*.c libc/*.c libc/*/*.c lib/*.c)
tags: $(SOURCE_FILES)
ctags -f tags $(SOURCE_FILES)
##
# Files that must be present in the ramdisk (apps, libraries)
RAMDISK_FILES= ${APPS_X} ${APPS_SH_X} ${LIBS_X} base/lib/ld.so base/lib/libm.so

View File

@ -42,7 +42,7 @@
#include <sys/ioctl.h>
#include <sys/stat.h>
#define BIM_VERSION "1.6.0"
#define BIM_VERSION "1.6.1"
#define BIM_COPYRIGHT "Copyright 2012-2019 K. Lange <\033[3mklange@toaruos.org\033[23m>"
#define BLOCK_SIZE 4096
@ -478,6 +478,9 @@ int fetch_from_biminfo(buffer_t * buf) {
/* Read */
sscanf(line+1+strlen(tmp_path)+1,"%d",&buf->line_no);
sscanf(line+1+strlen(tmp_path)+21,"%d",&buf->col_no);
if (buf->line_no > buf->line_count) buf->line_no = buf->line_count;
if (buf->col_no > buf->lines[buf->line_no-1]->actual) buf->col_no = buf->lines[buf->line_no-1]->actual;
return 0;
}
}
@ -1394,8 +1397,9 @@ static char * syn_java_special[] = {
};
static char * syn_java_at_comments[] = {
"@author","@see","@since","@param","@return","@throws",
"@author","@see","@since","@return","@throws",
"@version","@exception","@deprecated",
/* @param is special */
NULL
};
@ -1422,8 +1426,13 @@ static int paint_java_comment(struct syntax_state * state) {
else if (match_and_paint(state, "FIXME", FLAG_NOTICE, c_keyword_qualifier)) { continue; }
else if (charat() == '@') {
if (!find_keywords(state, syn_java_at_comments, FLAG_ESCAPE, at_keyword_qualifier)) {
/* Paint the @ */
paint(1, FLAG_COMMENT);
if (match_and_paint(state, "@param", FLAG_ESCAPE, at_keyword_qualifier)) {
while (charat() == ' ') skip();
while (c_keyword_qualifier(charat())) paint(1, FLAG_TYPE);
} else {
/* Paint the @ */
paint(1, FLAG_COMMENT);
}
}
} else if (charat() == '{') {
/* see if this terminates */
@ -8608,6 +8617,200 @@ _leave_select_char:
redraw_all();
}
/**
* Read ctags file to find matches for a symbol
*/
int read_tags(uint32_t * comp, char *** matches, int * matches_count) {
int matches_len = 4;
*matches_count = 0;
*matches = malloc(sizeof(char *) * (matches_len));
FILE * tags = fopen("tags","r");
if (!tags) return 1;
char tmp[4096]; /* max line */
while (!feof(tags) && fgets(tmp, 4096, tags)) {
if (tmp[0] == '!') continue;
int i = 0;
while (comp[i] && comp[i] == (unsigned int)tmp[i]) i++;
if (comp[i] == '\0') {
int j = i;
while (tmp[j] != '\t' && tmp[j] != '\n' && tmp[j] != '\0') j++;
tmp[j] = '\0';
/* Dedup */
int match_found = 0;
for (int i = 0; i < *matches_count; ++i) {
if (!strcmp((*matches)[i], tmp)) {
match_found = 1;
break;
}
}
if (match_found) continue;
if (*matches_count == matches_len) {
matches_len *= 2;
*matches = realloc(*matches, sizeof(char *) * (matches_len));
}
(*matches)[*matches_count] = strdup(tmp);
(*matches_count)++;
}
}
fclose(tags);
return 0;
}
/**
* Draw an autocomplete popover with matches.
*/
void draw_completion_matches(uint32_t * tmp, char ** matches, int matches_count) {
int original_length = 0;
while (tmp[original_length]) original_length++;
int max_width = 0;
for (int i = 0; i < matches_count; ++i) {
/* TODO unicode width */
if (strlen(matches[i]) > (unsigned int)max_width) {
max_width = strlen(matches[i]);
}
}
/* Figure out how much space we have to display the window */
int cursor_y = env->line_no - env->offset + 1;
int max_y = global_config.term_height - 2 - cursor_y;
/* Find a good place to put the box horizontally */
int num_size = num_width() + 3;
int x = num_size + 1 - env->coffset;
/* Determine where the cursor is physically */
for (int i = 0; i < env->col_no - 1 - original_length; ++i) {
char_t * c = &env->lines[env->line_no-1]->text[i];
x += c->display_width;
}
int box_width = max_width;
int box_x = x;
int box_y = cursor_y+1;
if (max_width > env->width - num_width()) {
box_width = env->width - num_width();
box_x = 1;
} else if (env->width - x < max_width) {
box_width = max_width;
box_x = env->width - max_width;
}
int max_count = (max_y < matches_count) ? max_y - 1 : matches_count;
for (int i = 0; i < max_count; ++i) {
place_cursor(box_x, box_y+i);
set_colors(COLOR_KEYWORD, COLOR_STATUS_BG);
/* TODO wide characters */
int match_width = strlen(matches[i]);
for (int j = 0; j < box_width; ++j) {
if (j == original_length) set_colors(i == 0 ? COLOR_NUMERAL : COLOR_STATUS_FG, COLOR_STATUS_BG);
if (j < match_width) printf("%c", matches[i][j]);
else printf(" ");
}
}
if (max_count == 0) {
place_cursor(box_x, box_y);
set_colors(COLOR_STATUS_FG, COLOR_STATUS_BG);
printf(" (no matches) ");
} else if (max_count != matches_count) {
place_cursor(box_x, box_y+max_count);
set_colors(COLOR_STATUS_FG, COLOR_STATUS_BG);
printf(" (%d more) ", matches_count-max_count);
}
}
/**
* Autocomplete words (function/variable names, etc.) in input mode.
*/
int omni_complete(void) {
int c;
/* Pull the word from before the cursor */
int c_before = 0;
int i = env->col_no-1;
while (i > 0) {
if (!c_keyword_qualifier(env->lines[env->line_no-1]->text[i-1].codepoint)) break;
c_before++;
i--;
}
/* Populate with characters */
uint32_t * tmp = malloc(sizeof(uint32_t) * (c_before+1));
int j = 0;
while (c_before) {
tmp[j] = env->lines[env->line_no-1]->text[env->col_no-c_before-1].codepoint;
c_before--;
j++;
}
tmp[j] = 0;
/*
* TODO matches should probably be a struct with more data than just
* the matching string; maybe offset where the needle was found,
* class information, source file information - anything we can extract
* from ctags, but also other information for other sources of completion.
*/
char ** matches;
int matches_count;
/* TODO just reading ctags is rather mediocre; can we do something cool here? */
if (read_tags(tmp, &matches, &matches_count)) goto _completion_done;
/* Draw box with matches at cursor-width(tmp) */
draw_completion_matches(tmp, matches, matches_count);
int retval = 0;
_completion_done:
place_cursor_actual();
while (1) {
c = bim_getch();
if (c == -1) continue;
if (matches_count < 1) {
redraw_all();
break;
}
if (c == '\t') {
for (unsigned int i = j; i < strlen(matches[0]); ++i) {
insert_char(matches[0][i]);
}
set_preferred_column();
redraw_text();
place_cursor_actual();
goto _finish_completion;
} else if (isgraph(c) && c != '}') {
/* insert and continue matching */
insert_char(c);
set_preferred_column();
redraw_text();
place_cursor_actual();
retval = 1;
goto _finish_completion;
} else if (c == DELETE_KEY || c == BACKSPACE_KEY) {
delete_at_cursor();
set_preferred_column();
redraw_text();
place_cursor_actual();
retval = 1;
goto _finish_completion;
}
/* TODO: Keyboard navigation of the matches list would be nice */
redraw_all();
break;
}
bim_unget(c);
_finish_completion:
for (int i = 0; i < matches_count; ++i) {
free(matches[i]);
}
free(matches);
free(tmp);
return retval;
}
/**
* INSERT mode
*
@ -8663,7 +8866,6 @@ void insert_mode(void) {
for (i = 0; i < env->col_no-1; ++i) {
if (!is_whitespace(env->lines[env->line_no-1]->text[i].codepoint)) break;
}
render_commandline_message("i=%d, col_no-1=%d", i, env->col_no-1);
if (i == env->col_no-1) {
/* Backspace until aligned */
delete_at_cursor();
@ -8689,6 +8891,9 @@ void insert_mode(void) {
insert_line_feed();
redraw |= 2;
break;
case 15: /* ^O */
while (omni_complete() == 1);
break;
case 22: /* ^V */
/* Insert next byte raw */
{

View File

@ -4,6 +4,7 @@ Generates, from this source repository, a "tarramdisk" - a ustar archive
suitable for booting ToaruOS.
"""
import os
import tarfile
users = {
@ -54,6 +55,8 @@ with tarfile.open('fatbase/ramdisk.img','w') as ramdisk:
ramdisk.add('libc',arcname='/src/libc',filter=file_filter)
ramdisk.add('boot',arcname='/src/boot',filter=file_filter)
ramdisk.add('modules',arcname='/src/modules',filter=file_filter)
if os.path.exists('tags'):
ramdisk.add('tags',arcname='/src/tags',filter=file_filter)
ramdisk.add('util/build-the-world.py',arcname='/usr/bin/build-the-world.py',filter=file_filter)