src/feature/editline/cli-el-backend.c (view raw)
1/* Copyright (c) 2013-2014 Jeffrey Pfau
2 *
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6#include "cli-el-backend.h"
7
8#include "core/version.h"
9
10#include <signal.h>
11
12static struct CLIDebugger* _activeDebugger;
13
14static char* _prompt(EditLine* el) {
15 UNUSED(el);
16 return "> ";
17}
18
19static void _breakIntoDefault(int signal) {
20 UNUSED(signal);
21 mDebuggerEnter(&_activeDebugger->d, DEBUGGER_ENTER_MANUAL, 0);
22}
23
24static unsigned char _tabComplete(EditLine* elstate, int ch) {
25 UNUSED(ch);
26 const LineInfo* li = el_line(elstate);
27 if (!li->buffer[0]) {
28 return CC_ERROR;
29 }
30
31 struct CLIDebuggerEditLineBackend* elbe;
32 el_get(elstate, EL_CLIENTDATA, &elbe);
33 // TODO: not always true
34 if (CLIDebuggerTabComplete(elbe->d.p, li->buffer, true, li->cursor - li->buffer)) {
35 return CC_REDISPLAY;
36 }
37 return CC_ERROR;
38}
39
40ATTRIBUTE_FORMAT(printf, 2, 3)
41void _CLIDebuggerEditLinePrintf(struct CLIDebuggerBackend* be, const char* fmt, ...) {
42 UNUSED(be);
43 va_list args;
44 va_start(args, fmt);
45 vprintf(fmt, args);
46 va_end(args);
47}
48
49void _CLIDebuggerEditLineInit(struct CLIDebuggerBackend* be) {
50 struct CLIDebuggerEditLineBackend* elbe = (struct CLIDebuggerEditLineBackend*) be;
51 // TODO: get argv[0]
52 elbe->elstate = el_init(binaryName, stdin, stdout, stderr);
53 el_set(elbe->elstate, EL_PROMPT, _prompt);
54 el_set(elbe->elstate, EL_EDITOR, "emacs");
55
56 el_set(elbe->elstate, EL_CLIENTDATA, elbe);
57 el_set(elbe->elstate, EL_ADDFN, "tab-complete", "Tab completion", _tabComplete);
58 el_set(elbe->elstate, EL_BIND, "\t", "tab-complete", 0);
59 elbe->histate = history_init();
60 HistEvent ev;
61 history(elbe->histate, &ev, H_SETSIZE, 200);
62 el_set(elbe->elstate, EL_HIST, history, elbe->histate);
63 _activeDebugger = be->p;
64 signal(SIGINT, _breakIntoDefault);
65}
66
67void _CLIDebuggerEditLineDeinit(struct CLIDebuggerBackend* be) {
68 struct CLIDebuggerEditLineBackend* elbe = (struct CLIDebuggerEditLineBackend*) be;
69 history_end(elbe->histate);
70 el_end(elbe->elstate);
71 free(elbe);
72}
73
74const char* _CLIDebuggerEditLineReadLine(struct CLIDebuggerBackend* be, size_t* len) {
75 struct CLIDebuggerEditLineBackend* elbe = (struct CLIDebuggerEditLineBackend*) be;
76 int count;
77 *len = 0;
78 const char* line = el_gets(elbe->elstate, &count);
79 if (line && count >= 1) {
80 // Crop off newline
81 *len = (size_t) count - 1;
82 }
83 return line;
84}
85void _CLIDebuggerEditLineLineAppend(struct CLIDebuggerBackend* be, const char* line) {
86 struct CLIDebuggerEditLineBackend* elbe = (struct CLIDebuggerEditLineBackend*) be;
87 el_insertstr(elbe->elstate, line);
88}
89
90const char* _CLIDebuggerEditLineHistoryLast(struct CLIDebuggerBackend* be, size_t* len) {
91 struct CLIDebuggerEditLineBackend* elbe = (struct CLIDebuggerEditLineBackend*) be;
92 HistEvent ev;
93 if (history(elbe->histate, &ev, H_FIRST) < 0) {
94 *len = 0;
95 return NULL;
96 }
97 const char* newline = strchr(ev.str, '\n');
98 if (!newline) {
99 *len = strlen(ev.str);
100 } else {
101 *len = newline - ev.str;
102 }
103
104 return ev.str;
105}
106
107void _CLIDebuggerEditLineHistoryAppend(struct CLIDebuggerBackend* be, const char* line) {
108 struct CLIDebuggerEditLineBackend* elbe = (struct CLIDebuggerEditLineBackend*) be;
109 HistEvent ev;
110 history(elbe->histate, &ev, H_ENTER, line);
111}
112
113struct CLIDebuggerBackend* CLIDebuggerEditLineBackendCreate(void) {
114 struct CLIDebuggerEditLineBackend* elbe = malloc(sizeof(*elbe));
115 elbe->d.printf = _CLIDebuggerEditLinePrintf;
116 elbe->d.init = _CLIDebuggerEditLineInit;
117 elbe->d.deinit = _CLIDebuggerEditLineDeinit;
118 elbe->d.readline = _CLIDebuggerEditLineReadLine;
119 elbe->d.lineAppend = _CLIDebuggerEditLineLineAppend;
120 elbe->d.historyLast = _CLIDebuggerEditLineHistoryLast;
121 elbe->d.historyAppend = _CLIDebuggerEditLineHistoryAppend;
122 return &elbe->d;
123}