Skip to content

Instantly share code, notes, and snippets.

@saitoha
Last active December 12, 2015 01:38
Show Gist options
  • Save saitoha/4692491 to your computer and use it in GitHub Desktop.
Save saitoha/4692491 to your computer and use it in GitHub Desktop.
Detect east-asian-ambiguous-width state of the terminal automatically (vim).
diff -cr vim.ba8835947b8b/runtime/doc/options.txt vim/runtime/doc/options.txt
*** vim.ba8835947b8b/runtime/doc/options.txt 2013-02-10 14:03:58.000000000 +0900
--- vim/runtime/doc/options.txt 2013-02-10 14:03:58.000000000 +0900
***************
*** 699,704 ****
--- 699,709 ----
when the system locale is set to one of CJK locales. See Unicode
Standard Annex #11 (http://www.unicode.org/reports/tr11).
+ Vim may set this option automatically at the startup time.
+ This only works when Vim is compiled with the |+termresponse|
+ feature and if |t_u7| is set to the sescape sequense to request
+ cursor position report.
+
*'antialias'* *'anti'* *'noantialias'* *'noanti'*
'antialias' 'anti' boolean (default: off)
global
diff -cr vim.ba8835947b8b/runtime/doc/tags vim/runtime/doc/tags
*** vim.ba8835947b8b/runtime/doc/tags 2013-02-10 14:03:58.000000000 +0900
--- vim/runtime/doc/tags 2013-02-10 14:03:58.000000000 +0900
***************
*** 964,969 ****
--- 964,970 ----
't_te' term.txt /*'t_te'*
't_ti' term.txt /*'t_ti'*
't_ts' term.txt /*'t_ts'*
+ 't_u7' term.txt /*'t_u7'*
't_ue' term.txt /*'t_ue'*
't_us' term.txt /*'t_us'*
't_ut' term.txt /*'t_ut'*
***************
*** 7972,7977 ****
--- 7973,7979 ----
t_tp version4.txt /*t_tp*
t_ts term.txt /*t_ts*
t_ts_old version4.txt /*t_ts_old*
+ t_u7 term.txt /*t_u7*
t_ue term.txt /*t_ue*
t_undo version4.txt /*t_undo*
t_us term.txt /*t_us*
diff -cr vim.ba8835947b8b/runtime/doc/term.txt vim/runtime/doc/term.txt
*** vim.ba8835947b8b/runtime/doc/term.txt 2013-02-10 14:03:58.000000000 +0900
--- vim/runtime/doc/term.txt 2013-02-10 14:03:58.000000000 +0900
***************
*** 294,299 ****
--- 294,301 ----
|termcap-cursor-shape|
t_RV request terminal version string (for xterm) *t_RV* *'t_RV'*
|xterm-8bit| |v:termresponse| |'ttymouse'| |xterm-codes|
+ t_u7 request cursor position (for xterm) *t_u7* *'t_u7'*
+ |ambiwidth|
KEY CODES
Note: Use the <> form if possible
diff -cr vim.ba8835947b8b/src/main.c vim/src/main.c
*** vim.ba8835947b8b/src/main.c 2013-02-10 14:03:58.000000000 +0900
--- vim/src/main.c 2013-02-10 14:03:58.000000000 +0900
***************
*** 804,809 ****
--- 804,812 ----
starttermcap(); /* start termcap if not done by wait_return() */
TIME_MSG("start termcap");
+ #if defined(FEAT_TERMRESPONSE) && defined(FEAT_MBYTE)
+ may_req_ambiguous_character_width();
+ #endif
#ifdef FEAT_MOUSE
setmouse(); /* may start using the mouse */
diff -cr vim.ba8835947b8b/src/option.c vim/src/option.c
*** vim.ba8835947b8b/src/option.c 2013-02-10 14:03:58.000000000 +0900
--- vim/src/option.c 2013-02-10 14:03:58.000000000 +0900
***************
*** 2900,2905 ****
--- 2900,2906 ----
p_term("t_op", T_OP)
p_term("t_RI", T_CRI)
p_term("t_RV", T_CRV)
+ p_term("t_u7", T_U7)
p_term("t_Sb", T_CSB)
p_term("t_Sf", T_CSF)
p_term("t_se", T_SE)
diff -cr vim.ba8835947b8b/src/term.c vim/src/term.c
*** vim.ba8835947b8b/src/term.c 2013-02-10 14:03:58.000000000 +0900
--- vim/src/term.c 2013-02-10 14:03:58.000000000 +0900
***************
*** 933,938 ****
--- 933,939 ----
{(int)KS_CWP, IF_EB("\033[3;%d;%dt", ESC_STR "[3;%d;%dt")},
# endif
{(int)KS_CRV, IF_EB("\033[>c", ESC_STR "[>c")},
+ {(int)KS_U7, IF_EB("\033[6n", ESC_STR "[6n")},
{K_UP, IF_EB("\033O*A", ESC_STR "O*A")},
{K_DOWN, IF_EB("\033O*B", ESC_STR "O*B")},
***************
*** 1221,1226 ****
--- 1222,1228 ----
{(int)KS_CWP, "[%dCWP%d]"},
# endif
{(int)KS_CRV, "[CRV]"},
+ {(int)KS_U7, "[U7]"},
{K_UP, "[KU]"},
{K_DOWN, "[KD]"},
{K_LEFT, "[KL]"},
***************
*** 1596,1601 ****
--- 1598,1604 ----
{KS_TS, "ts"}, {KS_FS, "fs"},
{KS_CWP, "WP"}, {KS_CWS, "WS"},
{KS_CSI, "SI"}, {KS_CEI, "EI"},
+ {KS_U7, "u7"},
{(enum SpecialKey)0, NULL}
};
***************
*** 3297,3302 ****
--- 3300,3344 ----
(void)vpeekc_nomap();
}
}
+
+ # ifdef FEAT_MBYTE
+ /* Check how the terminal treats ambiguous character width.
+ * First, we move the cursor to (0, 0) and print a test ambiguous character
+ * \u25bd (WHITE DOWN-POINTING TRIANGLE) and query current cursor position.
+ * If the terminal treats \u25bd as single width, the position is (0, 1),
+ * or if it is treated as double width, that will be (0, 2).
+ * This function has the side effect that changes cursor position, so
+ * it must be called immediately after entering termcap mode.
+ */
+ void
+ may_req_ambiguous_character_width()
+ {
+ if (crv_status == CRV_GET
+ && cur_tmode == TMODE_RAW
+ && termcap_active
+ && p_ek
+ # ifdef UNIX
+ && isatty(1)
+ && isatty(read_cmd_fd)
+ # endif
+ && *T_U7 != NUL
+ && !option_was_set("ambiwidth"))
+ {
+ char buf[16];
+ term_windgoto(0, 0);
+ buf[mb_char2bytes(0x25bd, buf)] = 0;
+ out_str(buf);
+ out_str(T_U7);
+ term_windgoto(0, 0);
+ out_str(" ");
+ term_windgoto(0, 0);
+ /* check for the characters now, otherwise they might be eaten by
+ * get_keystroke() */
+ out_flush();
+ (void)vpeekc_nomap();
+ }
+ }
+ # endif
#endif
/*
***************
*** 4048,4060 ****
|| key_name[0] == KS_URXVT_MOUSE
|| key_name[0] == KS_SGR_MOUSE)
{
! /* Check for xterm version string: "<Esc>[>{x};{vers};{y}c". Also
! * eat other possible responses to t_RV, rxvt returns
! * "<Esc>[?1;2c". Also accept CSI instead of <Esc>[.
! * mrxvt has been reported to have "+" in the version. Assume
! * the escape sequence ends with a letter or one of "{|}~". */
! if (*T_CRV != NUL && ((tp[0] == ESC && tp[1] == '[' && len >= 3)
! || (tp[0] == CSI && len >= 2)))
{
j = 0;
extra = 0;
--- 4090,4102 ----
|| key_name[0] == KS_URXVT_MOUSE
|| key_name[0] == KS_SGR_MOUSE)
{
! /* Check for some termcodes start with "<Esc>[" or CSI.
! * - DA2(secondary device attributes): <Esc>[>{x};{vers};{y}c
! * - CPR(cursor position report) <Esc>[{row};{col}R
! */
! if ((*T_CRV != NUL || *T_U7 != NUL)
! && (tp[0] == ESC && tp[1] == '[' && len >= 3)
! || (tp[0] == CSI && len >= 2))
{
j = 0;
extra = 0;
***************
*** 4066,4073 ****
if (i == len)
return -1; /* not enough characters */
/* eat it when at least one digit and ending in 'c' */
! if (i > 2 + (tp[0] != CSI) && tp[i] == 'c')
{
crv_status = CRV_GOT;
--- 4108,4135 ----
if (i == len)
return -1; /* not enough characters */
+ #ifdef FEAT_MBYTE
+ /* eat it when at least one digit and ending in 'R' */
+ if (*T_U7 != NUL && i > 2 + (tp[0] != CSI) && tp[i] == 'R')
+ {
+ if (extra == 2) {
+ p_ambw = "single";
+ } else if (extra == 3) {
+ p_ambw = "double";
+ }
+ key_name[0] = (int)KS_EXTRA;
+ key_name[1] = (int)KE_IGNORE;
+ slen = i + 1;
+ }
+ else
+ #endif
+ /* Check for xterm version string: "<Esc>[>{x};{vers};{y}c". Also
+ * eat other possible responses to t_RV, rxvt returns
+ * "<Esc>[?1;2c". Also accept CSI instead of <Esc>[.
+ * mrxvt has been reported to have "+" in the version. Assume
+ * the escape sequence ends with a letter or one of "{|}~". */
/* eat it when at least one digit and ending in 'c' */
! if (*T_CRV != NUL && i > 2 + (tp[0] != CSI) && tp[i] == 'c')
{
crv_status = CRV_GOT;
diff -cr vim.ba8835947b8b/src/term.h vim/src/term.h
*** vim.ba8835947b8b/src/term.h 2013-02-10 14:03:58.000000000 +0900
--- vim/src/term.h 2013-02-10 14:03:58.000000000 +0900
***************
*** 83,92 ****
#ifdef FEAT_VERTSPLIT
KS_CSV, /* scroll region vertical */
#endif
! KS_OP /* original color pair */
};
! #define KS_LAST KS_OP
/*
* the terminal capabilities are stored in this array
--- 83,93 ----
#ifdef FEAT_VERTSPLIT
KS_CSV, /* scroll region vertical */
#endif
! KS_OP, /* original color pair */
! KS_U7 /* request cursor position */
};
! #define KS_LAST KS_U7
/*
* the terminal capabilities are stored in this array
***************
*** 158,163 ****
--- 159,165 ----
#define T_CEI (term_str(KS_CEI)) /* end insert mode */
#define T_CRV (term_str(KS_CRV)) /* request version string */
#define T_OP (term_str(KS_OP)) /* original color pair */
+ #define T_U7 (term_str(KS_U7)) /* request cursor position */
#define TMODE_COOK 0 /* terminal mode for external cmds and Ex mode */
#define TMODE_SLEEP 1 /* terminal mode for sleeping (cooked but no echo) */
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment