update PROMPT_SP heuristic

Update our implementation of the PROMPT_SP heuristic to match current
zsh behavior. This makes it behave better on terminals like ConEmu and
the native MS Windows console which automatically insert a newline when
writing to the last column of the line.

Fixes #789
This commit is contained in:
Kurtis Rader 2016-12-23 13:08:45 -08:00
parent 01dbfb0a3f
commit 58347d494a
3 changed files with 26 additions and 5 deletions

View file

@ -14,6 +14,13 @@
#include <time.h>
#include <unistd.h>
#include <wchar.h>
#if HAVE_TERM_H
#include <term.h>
#elif HAVE_NCURSES_TERM_H
#include <ncurses/term.h>
#endif
#include <algorithm>
#include <map>
#include <set>
@ -50,6 +57,9 @@ extern char **environ;
bool g_use_posix_spawn = false; // will usually be set to true
/// Does the terminal have the "eat_newline_glitch".
bool term_has_xn = false;
/// Struct representing one level in the function variable stack.
struct env_node_t {
/// Variable table.
@ -245,6 +255,7 @@ static void handle_curses(const wchar_t *env_var_name) {
// changed. At the present time it can be called just once. Also, we should really only do this
// if the TERM var is set.
// input_init();
term_has_xn = tgetflag((char *)"xn") == 1; // does terminal have the eat_newline_glitch
}
/// React to modifying the given variable.

View file

@ -184,4 +184,6 @@ struct var_entry_t {
};
typedef std::map<wcstring, var_entry_t> var_table_t;
extern bool term_has_xn; // does the terminal have the "eat_newline_glitch"
#endif

View file

@ -31,6 +31,7 @@
#include <vector>
#include "common.h"
#include "env.h"
#include "fallback.h" // IWYU pragma: keep
#include "highlight.h"
#include "output.h"
@ -1194,7 +1195,8 @@ void s_reset(screen_t *s, screen_reset_mode_t mode) {
// Don't need to check for fish_wcwidth errors; this is done when setting up
// omitted_newline_char in common.cpp.
int non_space_width = fish_wcwidth(omitted_newline_char);
if (screen_width >= non_space_width) {
// We do `>` rather than `>=` because the code below might require one extra space.
if (screen_width > non_space_width) {
bool justgrey = true;
if (enter_dim_mode) {
std::string dim = tparm(enter_dim_mode);
@ -1224,16 +1226,22 @@ void s_reset(screen_t *s, screen_reset_mode_t mode) {
abandon_line_string.append(
str2wcstring(tparm(exit_attribute_mode))); // normal text ANSI escape sequence
}
abandon_line_string.append(screen_width - non_space_width, L' ');
int newline_glitch_width = term_has_xn ? 0 : 1;
abandon_line_string.append(screen_width - non_space_width - newline_glitch_width, L' ');
}
abandon_line_string.push_back(L'\r');
abandon_line_string.push_back(omitted_newline_char);
// Now we are certainly on a new line. But we may have dropped the omitted newline char on
// it. So append enough spaces to overwrite the omitted newline char, and then clear all the
// spaces from the new line
// spaces from the new line.
abandon_line_string.append(non_space_width, L' ');
abandon_line_string.push_back(L'\r');
// clear entire line - el2
abandon_line_string.append(L"\x1b[2K");
// Clear entire line. Zsh doesn't do this. Fish added this with commit 4417a6ee: If you have
// a prompt preceded by a new line, you'll get a line full of spaces instead of an empty
// line above your prompt. This doesn't make a difference in normal usage, but copying and
// pasting your terminal log becomes a pain. This commit clears that line, making it an
// actual empty line.
abandon_line_string.append(L"\e[2K");
const std::string narrow_abandon_line_string = wcs2string(abandon_line_string);
write_loop(STDOUT_FILENO, narrow_abandon_line_string.c_str(),