diff --git a/.gitignore b/.gitignore index 470cc81..4906ab9 100644 --- a/.gitignore +++ b/.gitignore @@ -13,4 +13,8 @@ doc/html/ *_stub.h *.lock history.txt -isocline.debug.txt \ No newline at end of file +isocline.debug.txt +.gdb_history +history* +src/cscope.out +test/example_rc.c diff --git a/include/isocline.h b/include/isocline.h index 0d46cf3..b1e10a3 100644 --- a/include/isocline.h +++ b/include/isocline.h @@ -330,6 +330,10 @@ const char* ic_get_prompt_marker(void); /// Get the current continuation prompt marker. const char* ic_get_continuation_prompt_marker(void); +/// Disable or enable printing marker on a separate line (disabled by default). +/// Returns the previous setting. +bool ic_enable_twoline_prompt(bool enable); + /// Disable or enable multi-line input (enabled by default). /// Returns the previous setting. bool ic_enable_multiline( bool enable ); diff --git a/src/editline.c b/src/editline.c index 270c42d..bd0d3ed 100644 --- a/src/editline.c +++ b/src/editline.c @@ -126,8 +126,7 @@ static bool editor_pos_is_at_end(editor_t* eb ) { // Row/Column width and positioning //------------------------------------------------------------- - -static void edit_get_prompt_width( ic_env_t* env, editor_t* eb, bool in_extra, ssize_t* promptw, ssize_t* cpromptw ) { +static void edit_get_prompt_width( ic_env_t* env, editor_t* eb, bool in_extra, ssize_t* promptw, ssize_t* cpromptw) { if (in_extra) { *promptw = 0; *cpromptw = 0; @@ -137,7 +136,8 @@ static void edit_get_prompt_width( ic_env_t* env, editor_t* eb, bool in_extra, s ssize_t textw = bbcode_column_width(env->bbcode, eb->prompt_text); ssize_t markerw = bbcode_column_width(env->bbcode, env->prompt_marker); ssize_t cmarkerw = bbcode_column_width(env->bbcode, env->cprompt_marker); - *promptw = markerw + textw; + *promptw = markerw; + if (!env->twoline_prompt) *promptw += textw; *cpromptw = (env->no_multiline_indent || *promptw < cmarkerw ? cmarkerw : *promptw); } } @@ -163,12 +163,14 @@ static bool edit_pos_is_at_row_end( ic_env_t* env, editor_t* eb ) { return rc.last_on_row; } -static void edit_write_prompt( ic_env_t* env, editor_t* eb, ssize_t row, bool in_extra ) { +static void edit_write_prompt( ic_env_t* env, editor_t* eb, ssize_t row, bool in_extra, bool marker_only) { if (in_extra) return; + if (!env->twoline_prompt) marker_only = false; bbcode_style_open(env->bbcode, "ic-prompt"); - if (row==0) { + if (!marker_only && row==0) { // regular prompt text bbcode_print( env->bbcode, eb->prompt_text ); + if (env->twoline_prompt) term_writeln(env->term,""); } else if (!env->no_multiline_indent) { // multiline continuation indentation @@ -176,7 +178,7 @@ static void edit_write_prompt( ic_env_t* env, editor_t* eb, ssize_t row, bool in ssize_t textw = bbcode_column_width(env->bbcode, eb->prompt_text ); ssize_t markerw = bbcode_column_width(env->bbcode, env->prompt_marker); ssize_t cmarkerw = bbcode_column_width(env->bbcode, env->cprompt_marker); - if (cmarkerw < markerw + textw) { + if (!marker_only && cmarkerw < markerw + textw) { term_write_repeat(env->term, " ", markerw + textw - cmarkerw ); } } @@ -212,7 +214,7 @@ static bool edit_refresh_rows_iter( if (row > info->last_row) return true; // should not occur // term_clear_line(term); - edit_write_prompt(info->env, info->eb, row, info->in_extra); + edit_write_prompt(info->env, info->eb, row, info->in_extra, true); //' write output if (info->attrs == NULL || (info->env->no_highlight && info->env->no_bracematch)) { @@ -387,6 +389,7 @@ static void edit_clear(ic_env_t* env, editor_t* eb ) { static void edit_clear_screen(ic_env_t* env, editor_t* eb ) { ssize_t cur_rows = eb->cur_rows; eb->cur_rows = term_get_height(env->term) - 1; + if (env->twoline_prompt) eb->cur_rows--; edit_clear(env,eb); eb->cur_rows = cur_rows; edit_refresh(env,eb); @@ -873,7 +876,7 @@ static char* edit_line( ic_env_t* env, const char* prompt_text ) } // show prompt - edit_write_prompt(env, &eb, 0, false); + edit_write_prompt(env, &eb, 0, false, false); // always a history entry for the current input history_push(env->history, ""); diff --git a/src/editline_completion.c b/src/editline_completion.c index 1734ef3..759e7d8 100644 --- a/src/editline_completion.c +++ b/src/editline_completion.c @@ -223,7 +223,7 @@ static void edit_completion_menu(ic_env_t* env, editor_t* eb, bool more_availabl rowcol_t rc; edit_get_rowcol(env,eb,&rc); edit_clear(env,eb); - edit_write_prompt(env,eb,0,false); + edit_write_prompt(env,eb,0,false, true); term_writeln(env->term, ""); for(ssize_t i = 0; i < count; i++) { const char* display = completions_get_display(env->completions, i, NULL); diff --git a/src/env.h b/src/env.h index edfc100..85f3df2 100644 --- a/src/env.h +++ b/src/env.h @@ -22,33 +22,34 @@ //------------------------------------------------------------- struct ic_env_s { - alloc_t* mem; // potential custom allocator - ic_env_t* next; // next environment (used for proper deallocation) - term_t* term; // terminal - tty_t* tty; // keyboard (NULL if stdin is a pipe, file, etc) - completions_t* completions; // current completions - history_t* history; // edit history - bbcode_t* bbcode; // print with bbcodes - const char* prompt_marker; // the prompt marker (defaults to "> ") - const char* cprompt_marker; // prompt marker for continuation lines (defaults to `prompt_marker`) - ic_highlight_fun_t* highlighter; // highlight callback - void* highlighter_arg; // user state for the highlighter. - const char* match_braces; // matching braces, e.g "()[]{}" - const char* auto_braces; // auto insertion braces, e.g "()[]{}\"\"''" - char multiline_eol; // character used for multiline input ("\") (set to 0 to disable) - bool initialized; // are we initialized? - bool noedit; // is rich editing possible (tty != NULL) - bool singleline_only; // allow only single line editing? - bool complete_nopreview; // do not show completion preview for each selection in the completion menu? - bool complete_autotab; // try to keep completing after a completion? + alloc_t* mem; // potential custom allocator + ic_env_t* next; // next environment (used for proper deallocation) + term_t* term; // terminal + tty_t* tty; // keyboard (NULL if stdin is a pipe, file, etc) + completions_t* completions; // current completions + history_t* history; // edit history + bbcode_t* bbcode; // print with bbcodes + const char* prompt_marker; // the prompt marker (defaults to "> ") + const char* cprompt_marker; // prompt marker for continuation lines (defaults to `prompt_marker`) + ic_highlight_fun_t* highlighter; // highlight callback + void* highlighter_arg; // user state for the highlighter. + const char* match_braces; // matching braces, e.g "()[]{}" + const char* auto_braces; // auto insertion braces, e.g "()[]{}\"\"''" + char multiline_eol; // character used for multiline input ("\") (set to 0 to disable) + bool initialized; // are we initialized? + bool noedit; // is rich editing possible (tty != NULL) + bool twoline_prompt; // print marker on a separate line + bool singleline_only; // allow only single line editing? + bool complete_nopreview; // do not show completion preview for each selection in the completion menu? + bool complete_autotab; // try to keep completing after a completion? bool no_multiline_indent; // indent continuation lines to line up under the initial prompt - bool no_help; // show short help line for history search etc. - bool no_hint; // allow hinting? - bool no_highlight; // enable highlighting? - bool no_bracematch; // enable brace matching? - bool no_autobrace; // enable automatic brace insertion? - bool no_lscolors; // use LSCOLORS/LS_COLORS to colorize file name completions? - long hint_delay; // delay before displaying a hint in milliseconds + bool no_help; // show short help line for history search etc. + bool no_hint; // allow hinting? + bool no_highlight; // enable highlighting? + bool no_bracematch; // enable brace matching? + bool no_autobrace; // enable automatic brace insertion? + bool no_lscolors; // use LSCOLORS/LS_COLORS to colorize file name completions? + long hint_delay; // delay before displaying a hint in milliseconds }; ic_private char* ic_editline(ic_env_t* env, const char* prompt_text); diff --git a/src/isocline.c b/src/isocline.c index 8b6055c..35231c4 100644 --- a/src/isocline.c +++ b/src/isocline.c @@ -180,6 +180,13 @@ ic_public void ic_set_prompt_marker( const char* prompt_marker, const char* cpro set_prompt_marker(env, prompt_marker, cprompt_marker); } +ic_public bool ic_enable_twoline_prompt( bool enable ) { + ic_env_t* env = ic_get_env(); if (env==NULL) return false; + bool prev = env->twoline_prompt; + env->twoline_prompt = enable; + return !prev; +} + ic_public bool ic_enable_multiline( bool enable ) { ic_env_t* env = ic_get_env(); if (env==NULL) return false; bool prev = env->singleline_only; diff --git a/test/example.c b/test/example.c index cdd76d4..6782cdd 100644 --- a/test/example.c +++ b/test/example.c @@ -51,6 +51,9 @@ int main() // inline hinting is enabled by default // ic_enable_hint(false); + // enable printing prompt and marker on separate lines + ic_enable_twoline_prompt(true); + // run until empty input char* input; while((input = ic_readline("isoclinε")) != NULL) // ctrl-d returns NULL (as well as errors)