testing stuff, finish text viewing basically
+ test.txt has tabstoppage to test rendering + home/end/status line
This commit is contained in:
parent
a38a4a72e2
commit
388af0ecc0
|
@ -22,5 +22,8 @@ run: $(BIN)
|
||||||
reset
|
reset
|
||||||
./$(BIN) notes.txt
|
./$(BIN) notes.txt
|
||||||
|
|
||||||
|
keypress: keypress.c
|
||||||
|
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ keypress.c
|
||||||
|
|
||||||
%.o: %.c
|
%.o: %.c
|
||||||
$(CC) $(CFLAGS) -c $@ $<
|
$(CC) $(CFLAGS) -c $@ $<
|
||||||
|
|
|
@ -21,3 +21,6 @@ l reset mode
|
||||||
~ special keys?
|
~ special keys?
|
||||||
5: pgup
|
5: pgup
|
||||||
6: pgdn
|
6: pgdn
|
||||||
|
m coloring
|
||||||
|
7m: inverted
|
||||||
|
default: normal
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <termios.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
|
||||||
|
struct termios orig_termios;
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
disableRawMode()
|
||||||
|
{
|
||||||
|
tcsetattr(STDIN_FILENO, TCSAFLUSH, &orig_termios);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
enableRawMode()
|
||||||
|
{
|
||||||
|
tcgetattr(STDIN_FILENO, &orig_termios);
|
||||||
|
atexit(disableRawMode);
|
||||||
|
|
||||||
|
struct termios raw = orig_termios;
|
||||||
|
raw.c_lflag &= ~(ECHO | ICANON);
|
||||||
|
|
||||||
|
tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
main()
|
||||||
|
{
|
||||||
|
enableRawMode();
|
||||||
|
|
||||||
|
char c;
|
||||||
|
while (read(STDIN_FILENO, &c, 1) == 1 && c != 'q') {
|
||||||
|
if (iscntrl(c)) {
|
||||||
|
printf("$%02x\n", c);
|
||||||
|
} else {
|
||||||
|
printf("$%02x ('%c')\n", c, c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
106
ke/main.c
106
ke/main.c
|
@ -7,10 +7,12 @@
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <stdarg.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <termios.h>
|
#include <termios.h>
|
||||||
|
#include <time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
|
||||||
|
@ -18,6 +20,7 @@
|
||||||
#define ESCSEQ "\x1b["
|
#define ESCSEQ "\x1b["
|
||||||
#define CTRL_KEY(key) ((key)&0x1f)
|
#define CTRL_KEY(key) ((key)&0x1f)
|
||||||
#define TAB_STOP 8
|
#define TAB_STOP 8
|
||||||
|
#define MSG_TIMEO 5
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* define the keyboard input modes
|
* define the keyboard input modes
|
||||||
|
@ -61,6 +64,9 @@ struct {
|
||||||
int nrows;
|
int nrows;
|
||||||
int rowoffs, coloffs;
|
int rowoffs, coloffs;
|
||||||
erow *row;
|
erow *row;
|
||||||
|
char *filename;
|
||||||
|
char msg[80];
|
||||||
|
time_t msgtm;
|
||||||
} editor;
|
} editor;
|
||||||
|
|
||||||
|
|
||||||
|
@ -207,6 +213,9 @@ open_file(const char *filename)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free(editor.filename);
|
||||||
|
editor.filename = strdup(filename);
|
||||||
|
|
||||||
free(line);
|
free(line);
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
}
|
}
|
||||||
|
@ -216,18 +225,20 @@ uint16_t
|
||||||
is_arrow_key(int16_t c)
|
is_arrow_key(int16_t c)
|
||||||
{
|
{
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case ARROW_UP:
|
|
||||||
case ARROW_DOWN:
|
case ARROW_DOWN:
|
||||||
case ARROW_LEFT:
|
case ARROW_LEFT:
|
||||||
case ARROW_RIGHT:
|
case ARROW_RIGHT:
|
||||||
|
case ARROW_UP:
|
||||||
case CTRL_KEY('p'):
|
case CTRL_KEY('p'):
|
||||||
case CTRL_KEY('n'):
|
case CTRL_KEY('n'):
|
||||||
case CTRL_KEY('f'):
|
case CTRL_KEY('f'):
|
||||||
case CTRL_KEY('b'):
|
case CTRL_KEY('b'):
|
||||||
case PG_UP:
|
case CTRL_KEY('a'):
|
||||||
case PG_DN:
|
case CTRL_KEY('e'):
|
||||||
case HOME_KEY:
|
|
||||||
case END_KEY:
|
case END_KEY:
|
||||||
|
case HOME_KEY:
|
||||||
|
case PG_DN:
|
||||||
|
case PG_UP:
|
||||||
return 1;
|
return 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -256,8 +267,9 @@ get_keypress()
|
||||||
if (seq[2] == '~') {
|
if (seq[2] == '~') {
|
||||||
switch (seq[1]) {
|
switch (seq[1]) {
|
||||||
case '1': return HOME_KEY;
|
case '1': return HOME_KEY;
|
||||||
case '2': return END_KEY;
|
case '2': return /* INS_KEY */ c;
|
||||||
case '3': return DEL_KEY;
|
case '3': return DEL_KEY;
|
||||||
|
case '4': return END_KEY;
|
||||||
case '5': return PG_UP;
|
case '5': return PG_UP;
|
||||||
case '6': return PG_DN;
|
case '6': return PG_DN;
|
||||||
case '7': return HOME_KEY;
|
case '7': return HOME_KEY;
|
||||||
|
@ -347,10 +359,12 @@ move_cursor(int16_t c)
|
||||||
}
|
}
|
||||||
|
|
||||||
case HOME_KEY:
|
case HOME_KEY:
|
||||||
|
case CTRL_KEY('a'):
|
||||||
editor.curx = 0;
|
editor.curx = 0;
|
||||||
break;
|
break;
|
||||||
case END_KEY:
|
case END_KEY:
|
||||||
editor.curx = editor.cols - 1;
|
case CTRL_KEY('e'):
|
||||||
|
editor.curx = editor.row[editor.cury].size;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -385,14 +399,14 @@ process_kcommand(int16_t c)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
int
|
||||||
process_keypress()
|
process_keypress()
|
||||||
{
|
{
|
||||||
int16_t c = get_keypress();
|
int16_t c = get_keypress();
|
||||||
|
|
||||||
/* we didn't actually read a key */
|
/* we didn't actually read a key */
|
||||||
if (c <= 0) {
|
if (c <= 0) {
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (editor.mode) {
|
switch (editor.mode) {
|
||||||
|
@ -407,8 +421,10 @@ process_keypress()
|
||||||
|
|
||||||
if (c == CTRL_KEY('k')) {
|
if (c == CTRL_KEY('k')) {
|
||||||
editor.mode = MODE_KCOMMAND;
|
editor.mode = MODE_KCOMMAND;
|
||||||
return;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -527,13 +543,55 @@ draw_rows(struct abuf *ab)
|
||||||
buflen);
|
buflen);
|
||||||
}
|
}
|
||||||
ab_append(ab, ESCSEQ "K", 3);
|
ab_append(ab, ESCSEQ "K", 3);
|
||||||
if (y < (editor.rows - 1)) {
|
|
||||||
ab_append(ab, "\r\n", 2);
|
ab_append(ab, "\r\n", 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
draw_status_bar(struct abuf *ab)
|
||||||
|
{
|
||||||
|
static int updates = 0;
|
||||||
|
char status[editor.cols];
|
||||||
|
char rstatus[editor.cols];
|
||||||
|
int len, rlen;
|
||||||
|
|
||||||
|
len = snprintf(status, sizeof(status), "%.20s - %d lines - %d updates",
|
||||||
|
editor.filename ? editor.filename : "[no file]",
|
||||||
|
editor.nrows, updates++);
|
||||||
|
rlen = snprintf(rstatus, sizeof(rstatus), "L%d/%d C%d",
|
||||||
|
editor.cury+1, editor.nrows, editor.curx+1);
|
||||||
|
|
||||||
|
ab_append(ab, ESCSEQ "7m", 4);
|
||||||
|
ab_append(ab, status, len);
|
||||||
|
while (len < editor.cols) {
|
||||||
|
if ((editor.cols - len) == rlen) {
|
||||||
|
ab_append(ab, rstatus, rlen);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ab_append(ab, " ", 1);
|
||||||
|
len++;
|
||||||
|
}
|
||||||
|
ab_append(ab, ESCSEQ "m", 3);
|
||||||
|
ab_append(ab, "\r\n", 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
draw_message_line(struct abuf *ab)
|
||||||
|
{
|
||||||
|
int len = strlen(editor.msg);
|
||||||
|
|
||||||
|
ab_append(ab, ESCSEQ "K", 3);
|
||||||
|
if (len > editor.cols) {
|
||||||
|
len = editor.cols;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len && ((time(NULL) - editor.msgtm) < MSG_TIMEO)) {
|
||||||
|
ab_append(ab, editor.msg, len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
row_render_to_cursor(erow *row, int cx)
|
row_render_to_cursor(erow *row, int cx)
|
||||||
|
@ -591,6 +649,8 @@ display_refresh()
|
||||||
display_clear(&ab);
|
display_clear(&ab);
|
||||||
|
|
||||||
draw_rows(&ab);
|
draw_rows(&ab);
|
||||||
|
draw_status_bar(&ab);
|
||||||
|
draw_message_line(&ab);
|
||||||
|
|
||||||
snprintf(buf, sizeof(buf), ESCSEQ "%d;%dH",
|
snprintf(buf, sizeof(buf), ESCSEQ "%d;%dH",
|
||||||
(editor.cury-editor.rowoffs)+1,
|
(editor.cury-editor.rowoffs)+1,
|
||||||
|
@ -604,12 +664,27 @@ display_refresh()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
editor_set_status(const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
va_start(ap, fmt);
|
||||||
|
vsnprintf(editor.msg, sizeof(editor.msg), fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
editor.msgtm = time(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
loop()
|
loop()
|
||||||
{
|
{
|
||||||
|
int up = 1;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
display_refresh();
|
if (up) display_refresh();
|
||||||
process_keypress();
|
up = process_keypress();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -623,6 +698,8 @@ init_editor()
|
||||||
if (get_winsz(&editor.rows, &editor.cols) == -1) {
|
if (get_winsz(&editor.rows, &editor.cols) == -1) {
|
||||||
die("can't get window size");
|
die("can't get window size");
|
||||||
}
|
}
|
||||||
|
editor.rows--; /* status bar */
|
||||||
|
editor.rows--; /* message line */
|
||||||
|
|
||||||
editor.curx = editor.cury = 0;
|
editor.curx = editor.cury = 0;
|
||||||
editor.rx = 0;
|
editor.rx = 0;
|
||||||
|
@ -630,6 +707,9 @@ init_editor()
|
||||||
editor.nrows = 0;
|
editor.nrows = 0;
|
||||||
editor.rowoffs = editor.coloffs = 0;
|
editor.rowoffs = editor.coloffs = 0;
|
||||||
editor.row = NULL;
|
editor.row = NULL;
|
||||||
|
|
||||||
|
editor.msg[0] = '\0';
|
||||||
|
editor.msgtm = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -643,6 +723,8 @@ main(int argc, char *argv[])
|
||||||
open_file(argv[1]);
|
open_file(argv[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
editor_set_status("C-k q to exit / C-k d to dump core");
|
||||||
|
|
||||||
display_clear(NULL);
|
display_clear(NULL);
|
||||||
loop();
|
loop();
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
hello world s ome tex t for you
|
Loading…
Reference in New Issue