Terminal 生活


Related Index Debian

始めに

普段の生活環境(?)であるターミナルの設定アレコレ.

現状は rxvt-unicode-256color をメインで利用中. 驚きの軽さが理由の全てかな.

EAW 対応: ロケールの入れ替え

EAW については

などを参照.

手元の環境では East Asian Ambiguous Char と絵文字の文字幅を強制的に "2" とする 修正ロケールを使っている.

微妙に間違っている気もしないではないが, まあ良いか, 的な.

UNICODE の Box drawing char は "1" にした方が良いかなぁ…

自作合成フォント:

「プログラミング」とか「等幅」とかで検索すると イロイロな合成フォントが見つかりますが, いまいち気にいるフォントが無かったので, 自作することにしました.

現状はとりあえずこれで良しとする感じ.

tmux

以前は GNU screen を使っていたのだけれども, 接続先の環境の多くが UTF-8 をサポートしてくれたので, tmux に移行した.

設定は以下の通り.

# -*- mode: conf; coding: utf-8-unix; indent-tabs-mode: nil -*-
#
# Author: Youhei SASAKI <uwabami@gfd-dennou.org>
# $Lastupdate: 22021-09-14 17:43:54$
# License: Public domain.

## general
# ESC での遅延解消: don't wait
set -sg escape-time 0
# Window を 0,  Pane を 1 始まりに
set -g base-index 0
set -g pane-base-index 0
# mouse 操作を無効化
setw -g mouse off
# disable bell action
set -g bell-action none
# Window renmae enabled
setw -g automatic-rename off
# default で起動するコマンド: zsh
set -g default-command zsh
# prefix の有効時間: no wait
set-option -g repeat-time 0

## display
# TERM等の設定
# set-option -ga terminal-overrides ",rxvt-256-color:Tc"
set-option -ga terminal-overrides ",rxvt-*:Tc,xterm-*:Tc"
# set -g default-terminal "screen-256color"
set -g default-terminal "screen-256color"
# set -g default-terminal tmux-direct
set-environment -g NCURSES_NO_UTF8_ACS 0
# 罫線素片の扱い: rxvt ならコレで良いのだが...
# set -ag terminal-overrides ',*:U8=0'
# 罫線素片の扱い: VTE 系はわざわざ Unicode に置き換える, ので ASCII で描画する
# set-option -g pane-border-ascii 0  # ←あてて build してある場合は不要
# set-environment -g VTE_CJK_WIDTH 1 # ←最近ちゃんと効いてない気がする.
# メッセージ表示時間(既定値は1000?)
set -g display-time 4000
# 後方スクロール行数(既定値は2000)
set -g history-limit 8192
setw -g pane-active-border-style "fg=#ff5252,bg=default"
setw -g pane-border-style "fg=#64FCDA,bg=default"
# don't show other activity
set -g monitor-activity off
set -g visual-activity off
set -g allow-rename on
# pane number display
set -g display-panes-time 4000

set -g status-style "bg=default,fg=#888888"
# set -g status-interval 1
setw -g window-status-current-style "fg=#ff5252,bg=default"
setw -g message-style "fg=#242424,bg=#ffd740,bright"
setw -g status-left-length 25
setw -g status-right-length 15
setw -g status-left "#[fg=#4c4cff][#[fg=#f6f3e8]#h#[fg=#4c4cff]]#[default] "
setw -g status-right "#[fg=#4c4cff]|#[fg=#f6f3e8]#(date +%y/%m/%d)#[fg=#4c4cff]|#[default]"

## keybind
# prefix:
unbind C-b                 # 既定のPrefixキー(Ctrl+b)の割り当てを解除
set -g prefix C-t          # Ctrl+tをPrefixキーにする
bind C-t send-prefix       # prefix-key の入力を渡す
# reload
bind r source-file ~/.tmux.conf \; display "Reload config file"
# コピーモードで vi + emacs 風
setw -g mode-keys vi
bind -T copy-mode-vi C-a send-keys -X start-of-line
bind -T copy-mode-vi C-e send-keys -X end-of-line
bind -T copy-mode-vi v send-keys -X begin-selection
bind -T copy-mode-vi y send-keys -X copy-pipe-and-cancel 'xclip -in -selection clipboard >/dev/null'
bind -T copy-mode-vi NPage send-keys -X page-down
bind -T copy-mode-vi PPage send-keys -X page-up
unbind ]
bind ] run-shell "xclip -o -selection clipboard | tmux load-buffer - && tmux paste-buffer"
unbind %
unbind '"'
# bind-key          z resize-pane -Z
unbind z
# bind-key        C-z suspend-client
unbind C-z
unbind Z
unbind s
bind s split-window -v
unbind |
bind | split-window -h
unbind o
bind o display-pane

unbind C-c
bind C-c new-window
unbind C-p
bind C-p previous-window
unbind C-n
bind C-n next-window

## Custom command
unbind-key -
# bind - run-shell ~/.config/tmux/weechat-toggle.sh
# unbind-key b
# bind-key b split-window 'tmux lsw | peco | cut -d":" -f 1 | xargs tmux select-window -t'

unbind C-Up
unbind C-Down
unbind C-Left
unbind C-Right
unbind M-Up
unbind M-Down
unbind M-Left
unbind M-Right

weechat を常に下に表示させておきたいので C-t - でトグルできるように 以下の weechat-toggle.sh を割り当てている.

#!/bin/sh
tmp=$HOME/.tmux.d/weechat.tmp
current_weechat_window=`tmux lsp -a -F "#I: #T" | grep WeeChat | cut -d":" -f 1`
current_weechat_pane=`tmux lsp -a -F "#P: #T" | grep WeeChat | cut -d":" -f 1`
# current_weechat_window=`tmux lsp -a -F "#I: #T" | grep screen | cut -d":" -f 1`
# current_weechat_pane=`tmux lsp -a -F "#P: #T" | grep screen | cut -d":" -f 1`
current_active_window=`tmux lsw | grep active | cut -d":" -f 1`
current_active_pane=`tmux lsp | grep active | cut -d":" -f 1`

if [ ${current_weechat_window} -ne ${current_active_window} ] ; then
    tmux join-pane -l 10 -s :${current_weechat_window}.${current_weechat_pane} -t :${current_active_window}
    tmux select-pane -t 0
else
    if [ -e $tmp ] ; then
        tmux resize-pane -t ${current_weechat_pane} -Z
        rm -f $tmp
    else
        tmux resize-pane -t ${current_weechat_pane} -Z
        tmux select-pane -t 0
        touch $tmp
    fi
fi

…weechat 自体にはイロイロと表示しているので, 気がちってしょうがない, かもしれない(笑)

obsolete

以下は最近やってないこと.

rxvt-unicode の patch 当て

Obsolete 合成フォントを自作するようになったので最近はここまで凝ったことしてないです.

Debian では configure オプションの変えた urxvt のパッケージが提供されていた. (256色が使いたいので rxvt-unicode-256color を使っていた). 最近はこれらは dummy になっていて, rxvt-unicode を入れれば良い模様

% apt-cache search rxvt-unicode
aterm - dummy transitional package for rxvt-unicode
aterm-ml - dummy transitional package for rxvt-unicode
rxvt - dummy transitional package for rxvt-unicode
rxvt-ml - dummy transitional package for rxvt-unicode
rxvt-unicode - RXVT-like terminal emulator with Unicode and 256-color support
rxvt-unicode-256color - dummy transitional package for rxvt-unicode
rxvt-unicode-lite - dummy transitional package for rxvt-unicode

ただ, フォント表示に関して幾つか気になるところがある. 詳細はrxvt-unicodeのフォントレンダリングを改善する - emonkak's Blog

パッチは以下. これに Debian パッケージをこのパッチを当てて rebuild して使っている.

diff --git a/src/rxvtfont.C b/src/rxvtfont.C
index 1914539..4c0189e 100644
--- a/src/rxvtfont.C
+++ b/src/rxvtfont.C
@@ -1223,92 +1223,63 @@ rxvt_font_xft::load (const rxvt_fontprop &prop, bool force_prop)
     return false;

   int ftheight = 0;
-  bool success = true;
-
-  for (;;)
-    {
-      p = FcPatternDuplicate (match);
-      f = XftFontOpenPattern (disp, p);
-
-      if (!f)
-        {
-          FcPatternDestroy (p);
-          success = false;
-          break;
-        }
-
-      FT_Face face = XftLockFace (f);
-
-      ascent  = (face->size->metrics.ascender + 63) >> 6;
-      descent = (-face->size->metrics.descender + 63) >> 6;
-      height  = max (ascent + descent, (face->size->metrics.height + 63) >> 6);
-      width   = 0;
-
-      bool scalable = face->face_flags & FT_FACE_FLAG_SCALABLE;

-      XftUnlockFace (f);
+  p = FcPatternDuplicate (match);
+  f = XftFontOpenPattern (disp, p);

-      int glheight = height;
+  if (!f)
+    {
+      FcPatternDestroy (p);
+      return false;
+    }

-      for (uint16_t *t = extent_test_chars; t < extent_test_chars + ecb_array_length (extent_test_chars); t++)
-        {
-          FcChar16 ch = *t;
+  FT_Face face = XftLockFace (f);

-          if (cs != CS_UNICODE
-              && ch > 0x100
-              && FROM_UNICODE (cs, ch) == NOCHAR)
-            continue;
+  ascent  = f->ascent;
+  descent = f->descent;
+  height  = max (ascent + descent, f->height);
+  width   = 0;

-          // ignore characters we wouldn't use anyways
-          bool careful;
-          if (!has_char (*t, &prop, careful))
-            continue;
+  bool scalable = face->face_flags & FT_FACE_FLAG_SCALABLE;

-          XGlyphInfo g;
-          XftTextExtents16 (disp, f, &ch, 1, &g);
+  XftUnlockFace (f);

-          g.width -= g.x;
+  for (uint16_t *t = extent_test_chars; t < extent_test_chars + ecb_array_length (extent_test_chars); t++)
+    {
+      FcChar16 ch = *t;

-          int wcw = WCWIDTH (ch);
-          if (wcw > 0) g.width = (g.width + wcw - 1) / wcw;
+      if (cs != CS_UNICODE
+          && ch > 0x100
+          && FROM_UNICODE (cs, ch) == NOCHAR)
+        continue;

-          if (width    < g.width       ) width    = g.width;
-          if (height   < g.height      ) height   = g.height;
-          if (glheight < g.height - g.y) glheight = g.height - g.y;
-        }
+      // ignore characters we wouldn't use anyways
+      bool careful;
+      if (!has_char (*t, &prop, careful))
+        continue;

-      if (!width)
-        {
-          rxvt_warn ("unable to calculate font width for '%s', ignoring.\n", name);
+      XGlyphInfo g;
+      XftTextExtents16 (disp, f, &ch, 1, &g);

-          XftFontClose (disp, f);
-          f = 0;
+      g.width -= g.x;

-          success = false;
-          break;
-        }
+      int wcw = WCWIDTH (ch);
+      if (wcw > 1) g.xOff = g.xOff / wcw;

-      if (prop.height == rxvt_fontprop::unset
-          || (height <= prop.height && glheight <= prop.height)
-          || height <= 2
-          || !scalable)
-        break;
+      if (width    < g.xOff  ) width    = g.xOff;
+      if (height   < g.height) height   = g.height;
+    }

-      if (ftheight)
-        {
-          // take smaller steps near the end
-          if (height > prop.height + 1) ftheight++;
-          if (height > prop.height + 2) ftheight++;
-          if (height > prop.height + 3) ftheight++;
+  bool success = true;

-          ftheight -= height - prop.height;
-        }
-      else
-        ftheight = prop.height - 1;
+  if (!width)
+    {
+      rxvt_warn ("unable to calculate font width for '%s', ignoring.\n", name);

       XftFontClose (disp, f);
-      FcPatternDel (match, FC_PIXEL_SIZE);
-      FcPatternAddInteger (match, FC_PIXEL_SIZE, ftheight);
+      f = 0;
+
+      success = false;
     }

   FcPatternDestroy (match);
@@ -1395,7 +1366,7 @@ rxvt_font_xft::draw (rxvt_drawable &d, int x, int y,

           ep->glyph = glyph;
           ep->x = x_ + (cwidth - extents.xOff >> 1);
-          ep->y = y_ + ascent;
+          ep->y = y_ + term->fbase + (term->lineSpace >> 1);

           if (extents.xOff == 0)
             ep->x = x_ + cwidth;
diff --git a/src/screen.C b/src/screen.C
index 9eb375a..7b3cdbf 100644
--- a/src/screen.C
+++ b/src/screen.C
@@ -2432,8 +2432,8 @@ rxvt_term::scr_refresh () NOTHROW
                 XSetForeground (dpy, gc, pix_colors[fore]);

               XDrawLine (dpy, vt, gc,
-                         xpixel, ypixel + font->ascent + 1,
-                         xpixel + Width2Pixel (count) - 1, ypixel + font->ascent + 1);
+                         xpixel, ypixel + Height2Pixel (1) - 1,
+                         xpixel + Width2Pixel (count) - 1, ypixel + Height2Pixel (1) - 1);
             }
         }                     /* for (col....) */
     }                         /* for (row....) */
diff --git a/src/table/jis0208_1990_0.h b/src/table/jis0208_1990_0.h
index b23378f..0febcd3 100644
--- a/src/table/jis0208_1990_0.h
+++ b/src/table/jis0208_1990_0.h
@@ -2241,6 +2241,7 @@ const uint16_t *jis0208_1990_0_f_i[] = {

 static uint32_t cs_jis0208_1990_0_from_unicode (unicode_t unicode) {
     if (unicode == 0x2312) return 0x225e;
+    if (unicode == 0xff5e) return 0x2141;
     uint8_t  l = unicode;
     uint16_t h = unicode >> 8;
     if (0x00 <= h && h <= 0xff

tmux の EAW 対応 patch

Obsolete EAW対応としてロケールを入れ替えるようになったので, 最近は patch はあててないです.

tmux EAW 文字幅問題の扱いに多少(?)不満があるので, 以下二つのパッチを当てて rebuild して使っている.

一つ目は pane-border 等、全て ASCII で描くパッチ.

From: Youhei SASAKI <uwabami@gfd-dennou.org>
Date: Sat, 4 Feb 2017 03:29:22 +0900
Subject: Use box drawing DECSP or ASCII with option 'pane-border-ascii'

Signed-off-by: Youhei SASAKI <uwabami@gfd-dennou.org>
---
 options-table.c |  5 +++++
 tty-acs.c       | 68 ++++++++++++++++++++++++++++-----------------------------
 2 files changed, 39 insertions(+), 34 deletions(-)

--- a/options-table.c
+++ b/options-table.c
@@ -293,6 +293,12 @@
 	  .default_num = 0
 	},

+	{ .name = "pane-border-ascii",
+	  .type = OPTIONS_TABLE_FLAG,
+	  .scope = OPTIONS_TABLE_SESSION,
+	  .default_num = 1
+	},
+
 	{ .name = "prefix",
 	  .type = OPTIONS_TABLE_KEY,
 	  .scope = OPTIONS_TABLE_SESSION,
--- a/tty-acs.c
+++ b/tty-acs.c
@@ -30,38 +30,38 @@
 	const char	*string;
 };
 const struct tty_acs_entry tty_acs_table[] = {
-	{ '+', "\342\206\222" },	/* arrow pointing right */
-	{ ',', "\342\206\220" },	/* arrow pointing left */
-	{ '-', "\342\206\221" },	/* arrow pointing up */
-	{ '.', "\342\206\223" },	/* arrow pointing down */
-	{ '0', "\342\226\256" },	/* solid square block */
-	{ '`', "\342\227\206" },	/* diamond */
-	{ 'a', "\342\226\222" },	/* checker board (stipple) */
-	{ 'f', "\302\260" },		/* degree symbol */
-	{ 'g', "\302\261" },		/* plus/minus */
-	{ 'h', "\342\226\222" },	/* board of squares */
-	{ 'i', "\342\230\203" },	/* lantern symbol */
-	{ 'j', "\342\224\230" },	/* lower right corner */
-	{ 'k', "\342\224\220" },	/* upper right corner */
-	{ 'l', "\342\224\214" },	/* upper left corner */
-	{ 'm', "\342\224\224" },	/* lower left corner */
-	{ 'n', "\342\224\274" },	/* large plus or crossover */
-	{ 'o', "\342\216\272" },	/* scan line 1 */
-	{ 'p', "\342\216\273" },	/* scan line 3 */
-	{ 'q', "\342\224\200" },	/* horizontal line */
-	{ 'r', "\342\216\274" },	/* scan line 7 */
-	{ 's', "\342\216\275" },	/* scan line 9 */
-	{ 't', "\342\224\234" },	/* tee pointing right */
-	{ 'u', "\342\224\244" },	/* tee pointing left */
-	{ 'v', "\342\224\264" },	/* tee pointing up */
-	{ 'w', "\342\224\254" },	/* tee pointing down */
-	{ 'x', "\342\224\202" },	/* vertical line */
-	{ 'y', "\342\211\244" },	/* less-than-or-equal-to */
-	{ 'z', "\342\211\245" },	/* greater-than-or-equal-to */
-	{ '{', "\317\200" },   		/* greek pi */
-	{ '|', "\342\211\240" },	/* not-equal */
-	{ '}', "\302\243" },		/* UK pound sign */
-	{ '~', "\302\267" }		/* bullet */
+	{ '+', ">" },	/* arrow pointing right */
+	{ ',', "<" },	/* arrow pointing left */
+	{ '-', "^" },	/* arrow pointing up */
+	{ '.', "." },	/* arrow pointing down */
+	{ '0', "#" },	/* solid square block */
+	{ '`', "#" },	/* diamond */
+	{ 'a', "#" },	/* checker board (stipple) */
+	{ 'f', "#" },	/* degree symbol */
+	{ 'g', "#" },	/* plus/minus */
+	{ 'h', "#" },	/* board of squares */
+	{ 'i', "#" },	/* lantern symbol */
+	{ 'j', "+" },	/* lower right corner */
+	{ 'k', "+" },	/* upper right corner */
+	{ 'l', "+" },	/* upper left corner */
+	{ 'm', "+" },	/* lower left corner */
+	{ 'n', "+" },	/* large plus or crossover */
+	{ 'o', "_" },	/* scan line 1 */
+	{ 'p', "_" },	/* scan line 3 */
+	{ 'q', "-" },	/* horizontal line */
+	{ 'r', "_" },	/* scan line 7 */
+	{ 's', "_" },	/* scan line 9 */
+	{ 't', "+" },	/* tee pointing right */
+	{ 'u', "+" },	/* tee pointing left */
+	{ 'v', "+" },	/* tee pointing up */
+	{ 'w', "+" },	/* tee pointing down */
+	{ 'x', "|" },	/* vertical line */
+	{ 'y', "#" },	/* less-than-or-equal-to */
+	{ 'z', "#" },	/* greater-than-or-equal-to */
+	{ '{', "#" },	/* greek pi */
+	{ '|', "#" },	/* not-equal */
+	{ '}', "#" },	/* UK pound sign */
+	{ '~', "*" }	/* bullet */
 };

 int
@@ -80,8 +80,8 @@
 {
 	struct tty_acs_entry *entry;

-	/* If not a UTF-8 terminal, use the ACS set. */
-	if (tty != NULL && !(tty->flags & TTY_UTF8)) {
+	/* If pane-border-ascii */
+	if ( options_get_number(global_s_options, "pane-border-ascii") != 0 ) {
 		if (tty->term->acs[ch][0] == '\0')
 			return (NULL);
 		return (&tty->term->acs[ch][0]);
--- a/tty.c
+++ b/tty.c
@@ -58,7 +58,7 @@
 void	tty_default_colours(struct grid_cell *, const struct window_pane *);

 #define tty_use_acs(tty) \
-	(tty_term_has((tty)->term, TTYC_ACSC) && !((tty)->flags & TTY_UTF8))
+	(tty_term_has((tty)->term, TTYC_ACSC) && (options_get_number(global_s_options, "pane-border-ascii") != 0 ))

 #define tty_pane_full_width(tty, ctx) \
 	((ctx)->xoff == 0 && screen_size_x((ctx)->wp->screen) >= (tty)->sx)

二つ目は en_US.UTF-8 決め打ちを止めるパッチ.

From: Youhei SASAKI <uwabami@gfd-dennou.org>
Date: Sat, 4 Feb 2017 03:30:21 +0900
Subject: Unse locale as en_US.UTF-8

Signed-off-by: Youhei SASAKI <uwabami@gfd-dennou.org>
---
 tmux.c | 12 +++++-------
 1 file changed, 5 insertions(+), 7 deletions(-)

--- a/tmux.c
+++ b/tmux.c
@@ -188,13 +188,11 @@
 	const char	*s;
 	int		 opt, flags, keys;

-	if (setlocale(LC_CTYPE, "en_US.UTF-8") == NULL) {
-		if (setlocale(LC_CTYPE, "") == NULL)
-			errx(1, "invalid LC_ALL, LC_CTYPE or LANG");
-		s = nl_langinfo(CODESET);
-		if (strcasecmp(s, "UTF-8") != 0 && strcasecmp(s, "UTF8") != 0)
-			errx(1, "need UTF-8 locale (LC_CTYPE) but have %s", s);
-	}
+	if (setlocale(LC_CTYPE, "") == NULL)
+		errx(1, "invalid LC_ALL, LC_CTYPE or LANG");
+	s = nl_langinfo(CODESET);
+	if (strcasecmp(s, "UTF-8") != 0 && strcasecmp(s, "UTF8") != 0)
+		errx(1, "need UTF-8 locale (LC_CTYPE) but have %s", s);

 	setlocale(LC_TIME, "");
 	tzset();

これらのパッチを当てた Debian パッケージを作成し, tmux.conf にて set-option -g pane-border-ascii 0 を指定している.