this repo has no description
at fix-build 4.6 kB view raw
1// OCaml declarations 2#include <caml/alloc.h> 3#include <caml/memory.h> 4#include <caml/callback.h> 5#include <caml/fail.h> 6#include <caml/threads.h> 7 8#include <errno.h> 9#include <assert.h> 10 11#include "linenoise_src.h" 12 13// Ripped from ctypes 14#define Val_none Val_int(0) 15#define Some_val(v) Field(v, 0) 16 17static value Val_some(value v) 18{ 19 CAMLparam1(v); 20 CAMLlocal1(some); 21 some = caml_alloc(1, 0); 22 Store_field(some, 0, v); 23 CAMLreturn(some); 24} 25 26/* if true, raise Sys.Break on ctrl-c */ 27static int raise_sys_break = 0; 28 29CAMLprim value ml_catch_break(value flag) 30{ 31 CAMLparam1(flag); 32 raise_sys_break = Bool_val(flag); 33 CAMLreturn(Val_unit); 34} 35 36CAMLprim value ml_add_completion(value completions, value new_completion) 37{ 38 CAMLparam2(completions, new_completion); 39 char* c_new_completion = caml_stat_strdup(String_val(new_completion)); 40 linenoiseAddCompletion((linenoiseCompletions *)completions, c_new_completion); 41 caml_stat_free(c_new_completion); 42 CAMLreturn(Val_unit); 43} 44 45// this bridge runs with the runtime lock acquired 46static void completion_bridge_inner(const char *buf, linenoiseCompletions *lc) 47{ 48 CAMLparam0(); 49 CAMLlocal1(str_copy); 50 str_copy = caml_copy_string(buf); 51 caml_callback2(*caml_named_value("lnoise_completion_cb"), str_copy, (value)lc); 52 CAMLreturn0; 53} 54 55static void completion_bridge(const char *buf, linenoiseCompletions *lc) 56{ 57 caml_acquire_runtime_system(); 58 completion_bridge_inner(buf, lc); 59 caml_release_runtime_system(); 60} 61 62static char *hints_bridge_inner(const char *buf, int *color, int *bold) 63{ 64 CAMLparam0(); 65 CAMLlocal2(str_copy, cb_result); 66 67 str_copy = caml_copy_string(buf); 68 69 cb_result = caml_callback(*caml_named_value("lnoise_hints_cb"), str_copy); 70 if (cb_result == Val_none) { 71 CAMLreturnT(char *,NULL); 72 } else { 73 char* msg = caml_stat_strdup(String_val(Field(Field(cb_result, 0), 0))); 74 *color = Int_val(Field(Field(cb_result, 0), 1)) + 31; 75 *bold = Bool_val(Field(Field(cb_result, 0), 2)); 76 CAMLreturnT(char *,msg); 77 } 78} 79 80static char *hints_bridge(const char *buf, int *color, int *bold) 81{ 82 caml_acquire_runtime_system(); 83 char* res = hints_bridge_inner(buf, color, bold); 84 caml_release_runtime_system(); 85 return res; 86} 87 88 89static void free_hints_bridge(void* data) { 90 caml_acquire_runtime_system(); 91 caml_stat_free(data); 92 caml_release_runtime_system(); 93} 94 95__attribute__((constructor)) 96void set_free_hints(void) { linenoiseSetFreeHintsCallback(free); } 97 98CAMLprim value ml_setup_bridges(value unit) { 99 CAMLparam1(unit); 100 linenoiseSetCompletionCallback(completion_bridge); 101 linenoiseSetHintsCallback(hints_bridge); 102 linenoiseSetFreeHintsCallback(free_hints_bridge); 103 CAMLreturn(Val_unit); 104} 105 106CAMLprim value ml_linenoise(value prompt) 107{ 108 CAMLparam1(prompt); 109 CAMLlocal1(lnoise_result); 110 111 linenoiseWasInterrupted = 0; // reset 112 char* c_prompt = caml_stat_strdup(String_val(prompt)); 113 114 caml_release_runtime_system(); 115 const char *result = linenoise(c_prompt); 116 caml_acquire_runtime_system(); 117 118 caml_stat_free(c_prompt); 119 if (!result) { 120 if (linenoiseWasInterrupted && raise_sys_break) { 121 caml_raise_constant(*caml_named_value("sys_break")); 122 } else { 123 CAMLreturn(Val_none); 124 } 125 } 126 lnoise_result = caml_copy_string(result); 127 linenoiseFree((void*)result); 128 CAMLreturn(Val_some(lnoise_result)); 129} 130 131CAMLprim value ml_history_add(value line) 132{ 133 CAMLparam1(line); 134 char* c_line = caml_stat_strdup(String_val(line)); 135 int res = linenoiseHistoryAdd(c_line); 136 caml_stat_free(c_line); 137 CAMLreturn(Val_int(res)); 138} 139 140CAMLprim value ml_history_set_maxlen(value max) 141{ 142 CAMLparam1(max); 143 CAMLreturn(Val_int(linenoiseHistorySetMaxLen(Int_val(max)))); 144} 145 146CAMLprim value ml_history_save(value filename) 147{ 148 CAMLparam1(filename); 149 char* c_filename = caml_stat_strdup(String_val(filename)); 150 int res = linenoiseHistorySave(c_filename); 151 caml_stat_free(c_filename); 152 CAMLreturn(Val_int(res)); 153} 154 155CAMLprim value ml_history_load(value filename) 156{ 157 CAMLparam1(filename); 158 char* c_filename= caml_stat_strdup(String_val(filename)); 159 int res = linenoiseHistoryLoad(c_filename); 160 caml_stat_free(c_filename); 161 CAMLreturn(Val_int(res)); 162} 163 164CAMLprim value ml_clearscreen(__attribute__((unused))value unit) 165{ 166 CAMLparam0(); 167 linenoiseClearScreen(); 168 CAMLreturn(Val_unit); 169} 170 171CAMLprim value ml_set_multiline(value use_multiline) 172{ 173 CAMLparam1(use_multiline); 174 linenoiseSetMultiLine(Bool_val(use_multiline)); 175 CAMLreturn(Val_unit); 176} 177 178CAMLprim value ml_printkeycodes(void) 179{ 180 CAMLparam0(); 181 linenoisePrintKeyCodes(); 182 CAMLreturn(Val_unit); 183}