当前位置:首页 > 编程笔记 > 正文
已解决

kilo TextEditor-4

来自网友在路上 165865提问 提问时间:2023-11-08 05:51:56阅读次数: 65

最佳答案 问答题库658位专家为你答疑解惑

文章目录

    • 语法高亮显示
      • 数字的颜色
      • 重构语法高亮显示
      • 搜索结果添加颜色
      • 搜索后恢复高亮
      • 多彩的数字
      • 检测文件类型
      • 有颜色的字符串
      • 有颜色的单行注释
      • 有颜色的关键字
      • 不可打印的字符
      • 有颜色的多行注释

语法高亮显示

数字的颜色

void editorDrawRows(struct abuf *ab) {int y;for (y = 0; y < E.screenrows; y++) {int filerow = y + E.rowoff;if (filerow >= E.numrows) {if (E.numrows == 0 && y == E.screenrows / 3) {char welcome[80];int welcomelen = snprintf(welcome, sizeof(welcome),"Kilo editor -- version %s", KILO_VERSION);if (welcomelen > E.screencols) welcomelen = E.screencols;int padding = (E.screencols - welcomelen) / 2;if (padding) {abAppend(ab, "~", 1);padding--;}while (padding--) abAppend(ab, " ", 1);abAppend(ab, welcome, welcomelen);} else {abAppend(ab, "~", 1);}} else {int len = E.row[filerow].rsize - E.coloff;if (len < 0) len = 0;if (len > E.screencols) len = E.screencols;char *c = &E.row[filerow].render[E.coloff];int j;for (j = 0; j < len; j++) {if (isdigit(c[j])) {//如果是数字就先调整文本颜色再写入数字,之后调整回来abAppend(ab, "\x1b[31m", 5);abAppend(ab, &c[j], 1);abAppend(ab, "\x1b[39m", 5);} else {abAppend(ab, &c[j], 1);}}}abAppend(ab, "\x1b[K", 3);abAppend(ab, "\r\n", 2);}
}

重构语法高亮显示

typedef struct erow {int size;int rsize;char *chars;char *render;unsigned char *hl;//render中字符的高亮标记,每个元素对应同样下标的render中的字符
} erow;void editorInsertRow(int at, char *s, size_t len) {if (at < 0 || at > E.numrows) return;E.row = realloc(E.row, sizeof(erow) * (E.numrows + 1));memmove(&E.row[at + 1], &E.row[at], sizeof(erow) * (E.numrows - at));E.row[at].size = len;E.row[at].chars = malloc(len + 1);memcpy(E.row[at].chars, s, len);E.row[at].chars[len] = '\0';E.row[at].rsize = 0;E.row[at].render = NULL;E.row[at].hl = NULL;editorUpdateRow(&E.row[at]);E.numrows++;E.dirty++;
}void editorFreeRow(erow *row) {free(row->render);free(row->chars);free(row->hl);
}
enum editorHighlight {HL_NORMAL = 0,HL_NUMBER//专注于高亮数字
};

填充hlrender对应的字符的高亮标记

void editorUpdateSyntax(erow *row) {row->hl = realloc(row->hl, row->rsize);memset(row->hl, HL_NORMAL, row->rsize);int i;for (i = 0; i < row->rsize; i++) {if (isdigit(row->render[i])) {row->hl[i] = HL_NUMBER;}}
}void editorUpdateRow(erow *row) {int tabs = 0;int j;for (j = 0; j < row->size; j++)if (row->chars[j] == '\t') tabs++;free(row->render);row->render = malloc(row->size + tabs*(KILO_TAB_STOP - 1) + 1);int idx = 0;for (j = 0; j < row->size; j++) {if (row->chars[j] == '\t') {row->render[idx++] = ' ';while (idx % KILO_TAB_STOP != 0) row->render[idx++] = ' ';} else {row->render[idx++] = row->chars[j];}}row->render[idx] = '\0';row->rsize = idx;editorUpdateSyntax(row);
}

将枚举类映射到对应ANSI颜色代码

int editorSyntaxToColor(int hl) {switch (hl) {case HL_NUMBER: return 31;default: return 37;}
}

最终通过hl获得高亮信息,然后显示

void editorDrawRows(struct abuf *ab) {int y;for (y = 0; y < E.screenrows; y++) {int filerow = y + E.rowoff;if (filerow >= E.numrows) {if (E.numrows == 0 && y == E.screenrows / 3) {char welcome[80];int welcomelen = snprintf(welcome, sizeof(welcome),"Kilo editor -- version %s", KILO_VERSION);if (welcomelen > E.screencols) welcomelen = E.screencols;int padding = (E.screencols - welcomelen) / 2;if (padding) {abAppend(ab, "~", 1);padding--;}while (padding--) abAppend(ab, " ", 1);abAppend(ab, welcome, welcomelen);} else {abAppend(ab, "~", 1);}} else {int len = E.row[filerow].rsize - E.coloff;if (len < 0) len = 0;if (len > E.screencols) len = E.screencols;char *c = &E.row[filerow].render[E.coloff];//获取高亮信息unsigned char *hl = &E.row[filerow].hl[E.coloff];int current_color = -1;//通过记录过去的颜色来省去重复设置颜色int j;for (j = 0; j < len; j++) {if (hl[j] == HL_NORMAL) {if (current_color != -1) {abAppend(ab, "\x1b[39m", 5);current_color = -1;}abAppend(ab, &c[j], 1);} else {//转换为颜色码int color = editorSyntaxToColor(hl[j]);if (color != current_color) {current_color = color;char buf[16];int clen = snprintf(buf, sizeof(buf), "\x1b[%dm", color);abAppend(ab, buf, clen);}abAppend(ab, &c[j], 1);}}abAppend(ab, "\x1b[39m", 5);}abAppend(ab, "\x1b[K", 3);abAppend(ab, "\r\n", 2);}
}

搜索结果添加颜色

enum editorHighlight {HL_NORMAL = 0,HL_NUMBER,HL_MATCH
};int editorSyntaxToColor(int hl) {switch (hl) {case HL_NUMBER: return 31;case HL_MATCH: return 34;default: return 37;}
}
void editorFindCallback(char *query, int key) {static int last_match = -1;static int direction = 1;if (key == '\r' || key == '\x1b') {last_match = -1;direction = 1;return;} else if (key == ARROW_RIGHT || key == ARROW_DOWN) {direction = 1;} else if (key == ARROW_LEFT || key == ARROW_UP) {direction = -1;} else {last_match = -1;direction = 1;}if (last_match == -1) direction = 1;int current = last_match;int i;for (i = 0; i < E.numrows; i++) {current += direction;if (current == -1) current = E.numrows - 1;else if (current == E.numrows) current = 0;erow *row = &E.row[current];char *match = strstr(row->render, query);if (match) {last_match = current;E.cy = current;E.cx = editorRowRxToCx(row, match - row->render);E.rowoff = E.numrows;//填充对应字符的高亮信息memset(&row->hl[match - row->render], HL_MATCH, strlen(query));break;}}
}

搜索后恢复高亮

void editorFindCallback(char *query, int key) {static int last_match = -1;static int direction = 1;static int saved_hl_line;static char *saved_hl = NULL;if (saved_hl) {//如果有保存着的(上个查询的)高亮信息,就把对应的行恢复memcpy(E.row[saved_hl_line].hl, saved_hl, E.row[saved_hl_line].rsize);free(saved_hl);saved_hl = NULL;}if (key == '\r' || key == '\x1b') {last_match = -1;direction = 1;return;} else if (key == ARROW_RIGHT || key == ARROW_DOWN) {direction = 1;} else if (key == ARROW_LEFT || key == ARROW_UP) {direction = -1;} else {last_match = -1;direction = 1;}if (last_match == -1) direction = 1;int current = last_match;int i;for (i = 0; i < E.numrows; i++) {current += direction;if (current == -1) current = E.numrows - 1;else if (current == E.numrows) current = 0;erow *row = &E.row[current];char *match = strstr(row->render, query);if (match) {last_match = current;E.cy = current;E.cx = editorRowRxToCx(row, match - row->render);E.rowoff = E.numrows;//高亮前保存高亮信息saved_hl_line = current;saved_hl = malloc(row->rsize);memcpy(saved_hl, row->hl, row->rsize);memset(&row->hl[match - row->render], HL_MATCH, strlen(query));break;}}
}

多彩的数字

void editorUpdateSyntax(erow *row) {row->hl = realloc(row->hl, row->rsize);memset(row->hl, HL_NORMAL, row->rsize);int i = 0;while (i < row->rsize) {char c = row->render[i];if (isdigit(c)) {row->hl[i] = HL_NUMBER;}i++;}
}

判断间隔符

int is_separator(int c) {return isspace(c) || c == '\0' || strchr(",.()+-/*=~%<>[];", c) != NULL;
}
void editorUpdateSyntax(erow *row) {row->hl = realloc(row->hl, row->rsize);memset(row->hl, HL_NORMAL, row->rsize);int prev_sep = 1;int i = 0;while (i < row->rsize) {char c = row->render[i];unsigned char prev_hl = (i > 0) ? row->hl[i - 1] : HL_NORMAL;if (isdigit(c) && (prev_sep || prev_hl == HL_NUMBER)) {row->hl[i] = HL_NUMBER;i++;prev_sep = 0;continue;}//判断前一个字符是否是间隔符prev_sep = is_separator(c);i++;}
}

支持高亮小数点

void editorUpdateSyntax(erow *row) {row->hl = realloc(row->hl, row->rsize);memset(row->hl, HL_NORMAL, row->rsize);int prev_sep = 1;int i = 0;while (i < row->rsize) {char c = row->render[i];unsigned char prev_hl = (i > 0) ? row->hl[i - 1] : HL_NORMAL;//兼容小数点if ((isdigit(c) && (prev_sep || prev_hl == HL_NUMBER)) ||(c == '.' && prev_hl == HL_NUMBER)) {row->hl[i] = HL_NUMBER;i++;prev_sep = 0;continue;}prev_sep = is_separator(c);i++;}
}

检测文件类型

#define HL_HIGHLIGHT_NUMBERS (1<<0)struct editorSyntax {char *filetype;char **filematch;int flags;
};char *C_HL_extensions[] = { ".c", ".h", ".cpp", NULL };
struct editorSyntax HLDB[] = {{"c",C_HL_extensions,HL_HIGHLIGHT_NUMBERS},
};
#define HLDB_ENTRIES (sizeof(HLDB) / sizeof(HLDB[0]))
struct editorConfig {int cx, cy;int rx;int rowoff;int coloff;int screenrows;int screencols;int numrows;erow *row;int dirty;char *filename;char statusmsg[80];time_t statusmsg_time;struct editorSyntax *syntax;//struct termios orig_termios;
};void initEditor() {E.cx = 0;E.cy = 0;E.rx = 0;E.rowoff = 0;E.coloff = 0;E.numrows = 0;E.row = NULL;E.dirty = 0;E.filename = NULL;E.statusmsg[0] = '\0';E.statusmsg_time = 0;E.syntax = NULL;if (getWindowSize(&E.screenrows, &E.screencols) == -1) die("getWindowSize");E.screenrows -= 2;
}

在状态栏中显示文件类型

void editorDrawStatusBar(struct abuf *ab) {abAppend(ab, "\x1b[7m", 4);char status[80], rstatus[80];//文件名+总行数int len = snprintf(status, sizeof(status), "%.20s - %d lines %s",E.filename ? E.filename : "[No Name]", E.numrows,E.dirty ? "(modified)" : "");//文件类型+当前行数/总行数int rlen = snprintf(rstatus, sizeof(rstatus), "%s | %d/%d",E.syntax ? E.syntax->filetype : "no ft", E.cy + 1, E.numrows);if (len > E.screencols) len = E.screencols;abAppend(ab, status, len);while (len < E.screencols) {if (E.screencols - len == rlen) {abAppend(ab, rstatus, rlen);break;} else {abAppend(ab, " ", 1);len++;}}abAppend(ab, "\x1b[m", 3);abAppend(ab, "\r\n", 2);
}

应用文件类型检测

void editorUpdateSyntax(erow *row) {row->hl = realloc(row->hl, row->rsize);memset(row->hl, HL_NORMAL, row->rsize);//未知文件类型,不设置高亮if (E.syntax == NULL) return;int prev_sep = 1;int i = 0;while (i < row->rsize) {char c = row->render[i];unsigned char prev_hl = (i > 0) ? row->hl[i - 1] : HL_NORMAL;//if (E.syntax->flags & HL_HIGHLIGHT_NUMBERS) {if ((isdigit(c) && (prev_sep || prev_hl == HL_NUMBER)) ||(c == '.' && prev_hl == HL_NUMBER)) {row->hl[i] = HL_NUMBER;i++;prev_sep = 0;continue;}}prev_sep = is_separator(c);i++;}
}
void editorSelectSyntaxHighlight() {E.syntax = NULL;if (E.filename == NULL) return;char *ext = strrchr(E.filename, '.');for (unsigned int j = 0; j < HLDB_ENTRIES; j++) {struct editorSyntax *s = &HLDB[j];unsigned int i = 0;while (s->filematch[i]) {int is_ext = (s->filematch[i][0] == '.');if ((is_ext && ext && !strcmp(ext, s->filematch[i])) ||(!is_ext && strstr(E.filename, s->filematch[i]))) {E.syntax = s;int filerow;for (filerow = 0; filerow < E.numrows; filerow++) {//从头开始更新文件高亮editorUpdateSyntax(&E.row[filerow]);}return;}i++;}}
}

调用检测文件类型函数

void editorOpen(char *filename) {free(E.filename);E.filename = strdup(filename);//解析文件类型,设置高亮信息editorSelectSyntaxHighlight();FILE *fp = fopen(filename, "r");if (!fp) die("fopen");char *line = NULL;size_t linecap = 0;ssize_t linelen;while ((linelen = getline(&line, &linecap, fp)) != -1) {while (linelen > 0 && (line[linelen - 1] == '\n' ||line[linelen - 1] == '\r'))linelen--;editorInsertRow(E.numrows, line, linelen);}free(line);fclose(fp);E.dirty = 0;
}
void editorSave() {if (E.filename == NULL) {E.filename = editorPrompt("Save as: %s (ESC to cancel)", NULL);if (E.filename == NULL) {editorSetStatusMessage("Save aborted");return;}//解析文件类型,设置高亮信息editorSelectSyntaxHighlight();}int len;char *buf = editorRowsToString(&len);int fd = open(E.filename, O_RDWR | O_CREAT, 0644);if (fd != -1) {if (ftruncate(fd, len) != -1) {if (write(fd, buf, len) == len) {close(fd);free(buf);E.dirty = 0;editorSetStatusMessage("%d bytes written to disk", len);return;}}close(fd);}free(buf);editorSetStatusMessage("Can't save! I/O error: %s", strerror(errno));
}

有颜色的字符串

enum editorHighlight {HL_NORMAL = 0,HL_STRING,HL_NUMBER,HL_MATCH
};int editorSyntaxToColor(int hl) {switch (hl) {case HL_STRING: return 35;case HL_NUMBER: return 31;case HL_MATCH: return 34;default: return 37;}
}
#define HL_HIGHLIGHT_STRINGS (1<<1)struct editorSyntax HLDB[] = {{"c",C_HL_extensions,HL_HIGHLIGHT_NUMBERS | HL_HIGHLIGHT_STRINGS},
};
void editorUpdateSyntax(erow *row) {row->hl = realloc(row->hl, row->rsize);memset(row->hl, HL_NORMAL, row->rsize);if (E.syntax == NULL) return;int prev_sep = 1;int in_string = 0;//当前字符在字符串里int i = 0;while (i < row->rsize) {char c = row->render[i];unsigned char prev_hl = (i > 0) ? row->hl[i - 1] : HL_NORMAL;if (E.syntax->flags & HL_HIGHLIGHT_STRINGS) {if (in_string) {row->hl[i] = HL_STRING;//转义符不会关闭字符串if (c == '\\' && i + 1 < row->rsize) {row->hl[i + 1] = HL_STRING;i += 2;continue;}//离开字符串if (c == in_string) in_string = 0;i++;prev_sep = 1;continue;} else {if (c == '"' || c == '\'') {in_string = c;row->hl[i] = HL_STRING;i++;continue;}}}if (E.syntax->flags & HL_HIGHLIGHT_NUMBERS) {if ((isdigit(c) && (prev_sep || prev_hl == HL_NUMBER)) ||(c == '.' && prev_hl == HL_NUMBER)) {row->hl[i] = HL_NUMBER;i++;prev_sep = 0;continue;}}prev_sep = is_separator(c);i++;}
}

有颜色的单行注释

enum editorHighlight {HL_NORMAL = 0,HL_COMMENT,HL_STRING,HL_NUMBER,HL_MATCH
};int editorSyntaxToColor(int hl) {switch (hl) {case HL_COMMENT: return 36;case HL_STRING: return 35;case HL_NUMBER: return 31;case HL_MATCH: return 34;default: return 37;}
}
struct editorSyntax {char *filetype;char **filematch;char *singleline_comment_start;//单行注释开始int flags;
};char *C_HL_extensions[] = { ".c", ".h", ".cpp", NULL };
struct editorSyntax HLDB[] = {{"c",C_HL_extensions,"//",HL_HIGHLIGHT_NUMBERS | HL_HIGHLIGHT_STRINGS},
};

更新高亮代码

void editorUpdateSyntax(erow *row) {row->hl = realloc(row->hl, row->rsize);memset(row->hl, HL_NORMAL, row->rsize);if (E.syntax == NULL) return;char *scs = E.syntax->singleline_comment_start;int scs_len = scs ? strlen(scs) : 0;//注释部分的长度int prev_sep = 1;int in_string = 0;int i = 0;while (i < row->rsize) {char c = row->render[i];unsigned char prev_hl = (i > 0) ? row->hl[i - 1] : HL_NORMAL;//设置注释高亮if (scs_len && !in_string) {if (!strncmp(&row->render[i], scs, scs_len)) {memset(&row->hl[i], HL_COMMENT, row->rsize - i);break;}}if (E.syntax->flags & HL_HIGHLIGHT_STRINGS) {if (in_string) {row->hl[i] = HL_STRING;if (c == '\\' && i + 1 < row->rsize) {row->hl[i + 1] = HL_STRING;i += 2;continue;}if (c == in_string) in_string = 0;i++;prev_sep = 1;continue;} else {if (c == '"' || c == '\'') {in_string = c;row->hl[i] = HL_STRING;i++;continue;}}}if (E.syntax->flags & HL_HIGHLIGHT_NUMBERS) {if ((isdigit(c) && (prev_sep || prev_hl == HL_NUMBER)) ||(c == '.' && prev_hl == HL_NUMBER)) {row->hl[i] = HL_NUMBER;i++;prev_sep = 0;continue;}}prev_sep = is_separator(c);i++;}
}

有颜色的关键字

enum editorHighlight {HL_NORMAL = 0,HL_COMMENT,HL_KEYWORD1,HL_KEYWORD2,HL_STRING,HL_NUMBER,HL_MATCH
};int editorSyntaxToColor(int hl) {switch (hl) {case HL_COMMENT: return 36;case HL_KEYWORD1: return 33;case HL_KEYWORD2: return 32;case HL_STRING: return 35;case HL_NUMBER: return 31;case HL_MATCH: return 34;default: return 37;}
}
struct editorSyntax {char *filetype;char **filematch;char **keywords;char *singleline_comment_start;int flags;
};
char *C_HL_keywords[] = {"switch", "if", "while", "for", "break", "continue", "return", "else","struct", "union", "typedef", "static", "enum", "class", "case","int|", "long|", "double|", "float|", "char|", "unsigned|", "signed|","void|", NULL
};
struct editorSyntax HLDB[] = {{"c",C_HL_extensions,C_HL_keywords,"//",HL_HIGHLIGHT_NUMBERS | HL_HIGHLIGHT_STRINGS},
};
void editorUpdateSyntax(erow *row) {row->hl = realloc(row->hl, row->rsize);memset(row->hl, HL_NORMAL, row->rsize);if (E.syntax == NULL) return;//别名char **keywords = E.syntax->keywords;char *scs = E.syntax->singleline_comment_start;int scs_len = scs ? strlen(scs) : 0;int prev_sep = 1;int in_string = 0;int i = 0;while (i < row->rsize) {char c = row->render[i];unsigned char prev_hl = (i > 0) ? row->hl[i - 1] : HL_NORMAL;if (scs_len && !in_string) {if (!strncmp(&row->render[i], scs, scs_len)) {memset(&row->hl[i], HL_COMMENT, row->rsize - i);break;}}if (E.syntax->flags & HL_HIGHLIGHT_STRINGS) {if (in_string) {row->hl[i] = HL_STRING;if (c == '\\' && i + 1 < row->rsize) {row->hl[i + 1] = HL_STRING;i += 2;continue;}if (c == in_string) in_string = 0;i++;prev_sep = 1;continue;} else {if (c == '"' || c == '\'') {in_string = c;row->hl[i] = HL_STRING;i++;continue;}}}if (E.syntax->flags & HL_HIGHLIGHT_NUMBERS) {if ((isdigit(c) && (prev_sep || prev_hl == HL_NUMBER)) ||(c == '.' && prev_hl == HL_NUMBER)) {row->hl[i] = HL_NUMBER;i++;prev_sep = 0;continue;}}if (prev_sep) {int j;for (j = 0; keywords[j]; j++) {int klen = strlen(keywords[j]);int kw2 = keywords[j][klen - 1] == '|';if (kw2) klen--;if (!strncmp(&row->render[i], keywords[j], klen) &&is_separator(row->render[i + klen])) {//匹配到关键字memset(&row->hl[i], kw2 ? HL_KEYWORD2 : HL_KEYWORD1, klen);i += klen;break;}}if (keywords[j] != NULL) {prev_sep = 0;continue;}}prev_sep = is_separator(c);i++;}
}

不可打印的字符

即黑块/菱形问号等字符

void editorDrawRows(struct abuf *ab) {int y;for (y = 0; y < E.screenrows; y++) {int filerow = y + E.rowoff;if (filerow >= E.numrows) {if (E.numrows == 0 && y == E.screenrows / 3) {char welcome[80];int welcomelen = snprintf(welcome, sizeof(welcome),"Kilo editor -- version %s", KILO_VERSION);if (welcomelen > E.screencols) welcomelen = E.screencols;int padding = (E.screencols - welcomelen) / 2;if (padding) {abAppend(ab, "~", 1);padding--;}while (padding--) abAppend(ab, " ", 1);abAppend(ab, welcome, welcomelen);} else {abAppend(ab, "~", 1);}} else {int len = E.row[filerow].rsize - E.coloff;if (len < 0) len = 0;if (len > E.screencols) len = E.screencols;char *c = &E.row[filerow].render[E.coloff];unsigned char *hl = &E.row[filerow].hl[E.coloff];int current_color = -1;int j;for (j = 0; j < len; j++) {if (iscntrl(c[j])) {char sym = (c[j] <= 26) ? '@' + c[j] : '?';//反转颜色abAppend(ab, "\x1b[7m", 4);abAppend(ab, &sym, 1);abAppend(ab, "\x1b[m", 3);//恢复当前颜色if (current_color != -1) {char buf[16];int clen = snprintf(buf, sizeof(buf), "\x1b[%dm", current_color);abAppend(ab, buf, clen);}} else if (hl[j] == HL_NORMAL) {if (current_color != -1) {abAppend(ab, "\x1b[39m", 5);current_color = -1;}abAppend(ab, &c[j], 1);} else {int color = editorSyntaxToColor(hl[j]);if (color != current_color) {current_color = color;char buf[16];int clen = snprintf(buf, sizeof(buf), "\x1b[%dm", color);abAppend(ab, buf, clen);}abAppend(ab, &c[j], 1);}}abAppend(ab, "\x1b[39m", 5);}abAppend(ab, "\x1b[K", 3);abAppend(ab, "\r\n", 2);}
}

有颜色的多行注释

enum editorHighlight {HL_NORMAL = 0,HL_COMMENT,HL_MLCOMMENT,HL_KEYWORD1,HL_KEYWORD2,HL_STRING,HL_NUMBER,HL_MATCH
};int editorSyntaxToColor(int hl) {switch (hl) {case HL_COMMENT:case HL_MLCOMMENT: return 36;case HL_KEYWORD1: return 33;case HL_KEYWORD2: return 32;case HL_STRING: return 35;case HL_NUMBER: return 31;case HL_MATCH: return 34;default: return 37;}
}
struct editorSyntax {char *filetype;char **filematch;char **keywords;char *singleline_comment_start;char *multiline_comment_start;char *multiline_comment_end;int flags;
};struct editorSyntax HLDB[] = {{"c",C_HL_extensions,C_HL_keywords,"//", "/*", "*/",HL_HIGHLIGHT_NUMBERS | HL_HIGHLIGHT_STRINGS},
};
void editorUpdateSyntax(erow *row) {row->hl = realloc(row->hl, row->rsize);memset(row->hl, HL_NORMAL, row->rsize);if (E.syntax == NULL) return;char **keywords = E.syntax->keywords;char *scs = E.syntax->singleline_comment_start;char *mcs = E.syntax->multiline_comment_start;char *mce = E.syntax->multiline_comment_end;int scs_len = scs ? strlen(scs) : 0;int mcs_len = mcs ? strlen(mcs) : 0;int mce_len = mce ? strlen(mce) : 0;int prev_sep = 1;int in_string = 0;int in_comment = 0;int i = 0;while (i < row->rsize) {char c = row->render[i];unsigned char prev_hl = (i > 0) ? row->hl[i - 1] : HL_NORMAL;if (scs_len && !in_string && !in_comment) {//不应在多行注释中检测单行注释if (!strncmp(&row->render[i], scs, scs_len)) {memset(&row->hl[i], HL_COMMENT, row->rsize - i);break;}}if (mcs_len && mce_len && !in_string) {//在多行注释中if (in_comment) {row->hl[i] = HL_MLCOMMENT;if (!strncmp(&row->render[i], mce, mce_len)) {memset(&row->hl[i], HL_MLCOMMENT, mce_len);i += mce_len;in_comment = 0;prev_sep = 1;continue;} else {i++;continue;}} else if (!strncmp(&row->render[i], mcs, mcs_len)) {memset(&row->hl[i], HL_MLCOMMENT, mcs_len);i += mcs_len;in_comment = 1;continue;}}if (E.syntax->flags & HL_HIGHLIGHT_STRINGS) {if (in_string) {row->hl[i] = HL_STRING;if (c == '\\' && i + 1 < row->rsize) {row->hl[i + 1] = HL_STRING;i += 2;continue;}if (c == in_string) in_string = 0;i++;prev_sep = 1;continue;} else {if (c == '"' || c == '\'') {in_string = c;row->hl[i] = HL_STRING;i++;continue;}}}if (E.syntax->flags & HL_HIGHLIGHT_NUMBERS) {if ((isdigit(c) && (prev_sep || prev_hl == HL_NUMBER)) ||(c == '.' && prev_hl == HL_NUMBER)) {row->hl[i] = HL_NUMBER;i++;prev_sep = 0;continue;}}if (prev_sep) {int j;for (j = 0; keywords[j]; j++) {int klen = strlen(keywords[j]);int kw2 = keywords[j][klen - 1] == '|';if (kw2) klen--;if (!strncmp(&row->render[i], keywords[j], klen) &&is_separator(row->render[i + klen])) {memset(&row->hl[i], kw2 ? HL_KEYWORD2 : HL_KEYWORD1, klen);i += klen;break;}}if (keywords[j] != NULL) {prev_sep = 0;continue;}}prev_sep = is_separator(c);i++;}
}
typedef struct erow {int idx;//行的索引int size;int rsize;char *chars;char *render;unsigned char *hl;int hl_open_comment;
} erow;void editorInsertRow(int at, char *s, size_t len) {if (at < 0 || at > E.numrows) return;E.row = realloc(E.row, sizeof(erow) * (E.numrows + 1));memmove(&E.row[at + 1], &E.row[at], sizeof(erow) * (E.numrows - at));//插入一行增加索引for (int j = at + 1; j <= E.numrows; j++) E.row[j].idx++;E.row[at].idx = at;E.row[at].size = len;E.row[at].chars = malloc(len + 1);memcpy(E.row[at].chars, s, len);E.row[at].chars[len] = '\0';E.row[at].rsize = 0;E.row[at].render = NULL;E.row[at].hl = NULL;E.row[at].hl_open_comment = 0;editorUpdateRow(&E.row[at]);E.numrows++;E.dirty++;
}void editorDelRow(int at) {if (at < 0 || at >= E.numrows) return;editorFreeRow(&E.row[at]);memmove(&E.row[at], &E.row[at + 1], sizeof(erow) * (E.numrows - at - 1));for (int j = at; j < E.numrows - 1; j++) E.row[j].idx--;E.numrows--;E.dirty++;
}
void editorUpdateSyntax(erow *row) {row->hl = realloc(row->hl, row->rsize);memset(row->hl, HL_NORMAL, row->rsize);if (E.syntax == NULL) return;char **keywords = E.syntax->keywords;char *scs = E.syntax->singleline_comment_start;char *mcs = E.syntax->multiline_comment_start;char *mce = E.syntax->multiline_comment_end;int scs_len = scs ? strlen(scs) : 0;int mcs_len = mcs ? strlen(mcs) : 0;int mce_len = mce ? strlen(mce) : 0;int prev_sep = 1;int in_string = 0;int in_comment = (row->idx > 0 && E.row[row->idx - 1].hl_open_comment);int i = 0;while (i < row->rsize) {char c = row->render[i];unsigned char prev_hl = (i > 0) ? row->hl[i - 1] : HL_NORMAL;if (scs_len && !in_string && !in_comment) {if (!strncmp(&row->render[i], scs, scs_len)) {memset(&row->hl[i], HL_COMMENT, row->rsize - i);break;}}if (mcs_len && mce_len && !in_string) {if (in_comment) {row->hl[i] = HL_MLCOMMENT;if (!strncmp(&row->render[i], mce, mce_len)) {memset(&row->hl[i], HL_MLCOMMENT, mce_len);i += mce_len;in_comment = 0;prev_sep = 1;continue;} else {i++;continue;}} else if (!strncmp(&row->render[i], mcs, mcs_len)) {memset(&row->hl[i], HL_MLCOMMENT, mcs_len);i += mcs_len;in_comment = 1;continue;}}if (E.syntax->flags & HL_HIGHLIGHT_STRINGS) {if (in_string) {row->hl[i] = HL_STRING;if (c == '\\' && i + 1 < row->rsize) {row->hl[i + 1] = HL_STRING;i += 2;continue;}if (c == in_string) in_string = 0;i++;prev_sep = 1;continue;} else {if (c == '"' || c == '\'') {in_string = c;row->hl[i] = HL_STRING;i++;continue;}}}if (E.syntax->flags & HL_HIGHLIGHT_NUMBERS) {if ((isdigit(c) && (prev_sep || prev_hl == HL_NUMBER)) ||(c == '.' && prev_hl == HL_NUMBER)) {row->hl[i] = HL_NUMBER;i++;prev_sep = 0;continue;}}if (prev_sep) {int j;for (j = 0; keywords[j]; j++) {int klen = strlen(keywords[j]);int kw2 = keywords[j][klen - 1] == '|';if (kw2) klen--;if (!strncmp(&row->render[i], keywords[j], klen) &&is_separator(row->render[i + klen])) {memset(&row->hl[i], kw2 ? HL_KEYWORD2 : HL_KEYWORD1, klen);i += klen;break;}}if (keywords[j] != NULL) {prev_sep = 0;continue;}}prev_sep = is_separator(c);i++;}int changed = (row->hl_open_comment != in_comment);row->hl_open_comment = in_comment;if (changed && row->idx + 1 < E.numrows)editorUpdateSyntax(&E.row[row->idx + 1]);
}

简单升级了下:

char** row_find_offset = NULL;//一行中查找到的词的char*
void editorFindCallback(char *query, int key)
{static int last_match = -1;static int direction = 1;static int current_offset = 0;//当前光标指向的row_find_offset里的下标static int row_find_count = 0;//当前行找到的个数static int saved_hl_line;static char *saved_hl = NULL;if (saved_hl) {//如果有保存着的(上个查询的)高亮信息,就把对应的行恢复memcpy(E.row[saved_hl_line].hl, saved_hl, E.row[saved_hl_line].rsize);free(saved_hl);saved_hl = NULL;}if (key == '\r' || key == '\x1b'){last_match = -1;direction = 1;current_offset = 0;free(row_find_offset);row_find_offset = NULL;row_find_count = 0;return;}else if (key == ARROW_RIGHT || key == ARROW_DOWN){//按右/下键向后搜索direction = 1;}else if (key == ARROW_LEFT || key == ARROW_UP){//按左/上键向前搜索direction = -1;}else{last_match = -1;direction = 1;current_offset = 0;free(row_find_offset);row_find_offset = NULL;row_find_count = 0;}if (last_match == -1) direction = 1;//当前行恢复为上一个匹配行int current = last_match;int i;for (i = 0; i < E.numrows; i++){erow *row = &E.row[current];if(key == ARROW_LEFT && current_offset > 0){current_offset--;}else if(key == ARROW_RIGHT && current_offset != row_find_count - 1 && row_find_count != 0){current_offset++;}else{//当前行不断向上/向下//新的一行current += direction;if (current == -1) current = E.numrows - 1;else if (current == E.numrows) current = 0;row = &E.row[current];current_offset = 0;if(row_find_offset){free(row_find_offset);row_find_offset = NULL;}row_find_count = 0;if(strstr(row->render, query)){//直接分配rsize个row_find_offset = (char**)malloc(sizeof(char*) * row->rsize);row_find_count = getSubStr(row->render, query, row_find_offset);}else{continue;}}char* match = row_find_offset[current_offset];if (match){//上一个匹配行 = 当前行last_match = current;E.cy = current;E.cx = editorRowRxToCx(row, match - row->render);E.rowoff = E.numrows;saved_hl_line = current;saved_hl = malloc(row->rsize);memcpy(saved_hl, row->hl, row->rsize);memset(&row->hl[match - row->render], HL_MATCH, strlen(query));break;}}
}int getSubStr(char* src, char* sub, char** offset)
{char* match = src;int i = 0;while(match){match = strstr(match, sub);if(!match){break;}offset[i++] = match;if(strlen(match) >= strlen(sub)){match += strlen(sub);}}return i;
}
查看全文

99%的人还看了

猜你感兴趣

版权申明

本文"kilo TextEditor-4":http://eshow365.cn/6-35066-0.html 内容来自互联网,请自行判断内容的正确性。如有侵权请联系我们,立即删除!