Browse Source

feat(ui/tmux): 通过 tmux 来增强 UI,支持查看日志,支持显示角色信息

dzp 3 years ago
parent
commit
9822f77cc7
16 changed files with 360 additions and 29 deletions
  1. 2 0
      .dockerignore
  2. 14 0
      .gitignore
  3. 1 1
      .gitmodules
  4. 21 7
      Dockerfile
  5. 116 0
      bin/mtail
  6. 2 1
      bin/start
  7. 16 11
      bin/start-ui
  8. 74 0
      bin/tmux-ui
  9. 1 0
      framework/main.tin
  10. 1 1
      ids/EXAMPLE
  11. 65 0
      init.vim
  12. 6 0
      mud/pkuxkx/plugins/basic/char/score.tin
  13. 19 0
      plugins/lib/ui/tmux.tin
  14. 9 2
      profile.sh
  15. 1 1
      tintin
  16. 12 5
      tmux.conf

+ 2 - 0
.dockerignore

@@ -0,0 +1,2 @@
+**/.git
+**/*.log

+ 14 - 0
.gitignore

@@ -4,6 +4,13 @@
 .bash_profile
 .viminfo
 .tintin/*
+.local
+.cache
+
+bin/tt++
+bin/tt-*
+bin/tmux*
+!bin/tmux-ui
 
 log/*
 !log/.gitkeep
@@ -11,6 +18,8 @@ ids/*
 !ids/DEFAULT
 !ids/EXAMPLE
 
+tmux/*
+
 foo.tin
 bar.tin
 mwe.tin
@@ -18,6 +27,11 @@ bug.tin
 test.tin
 out
 out[1-9]
+*.out
+*.old
+*.bak
+*.jpg
+*.png
 
 var/*
 var

+ 1 - 1
.gitmodules

@@ -1,4 +1,4 @@
 [submodule "tintin"]
 	path = tintin
-	url = https://github.com/mudclient/tintin
+	url = https://github.com/mudclient/tintin.git
 	branch = beta-develop

+ 21 - 7
Dockerfile

@@ -3,9 +3,16 @@ FROM alpine:latest
 
 # 安装编译器和依赖包
 RUN    apk update \
-    && apk add --no-cache git gcc libc-dev zlib-dev zlib-static pcre-dev make
+    && apk add --no-cache git gcc libc-dev zlib-dev zlib-static pcre-dev make curl
 
-RUN git clone https://github.com/mudclient/tintin.git --branch beta-develop
+RUN git clone --depth 1 https://github.com/junegunn/vim-plug.git /vim-plug
+RUN git clone --depth 1 https://github.com/dzpao/vim-mbs.git /vim-mbs
+RUN git clone --depth 1 https://github.com/morhetz/gruvbox.git /gruvbox
+RUN git clone --depth 1 https://github.com/yegappan/mru.git /mru
+RUN git clone --depth 1 https://github.com/jlanzarotta/BufExplorer.git /BufExplorer
+RUN git clone --depth 1 https://github.com/mhinz/vim-startify.git /vim-startify
+
+RUN git clone --depth 1 https://github.com/mudclient/tintin.git --branch beta-develop
 WORKDIR /tintin/src/
 
 # 这里 hack 了一下 gcc,强制静态编译。
@@ -27,7 +34,7 @@ ENV LANG=zh_CN.UTF8     \
 WORKDIR /paotin/
 
 RUN    apk update \
-    && apk add --no-cache tmux bash
+    && apk add --no-cache tmux bash ncurses less neovim nano
 
 # 设置时区为上海
 RUN apk add --no-cache tzdata \
@@ -44,15 +51,22 @@ COPY docs               /paotin/docs/
 COPY etc                /paotin/etc/
 COPY framework          /paotin/framework/
 COPY plugins            /paotin/plugins/
+COPY mud                /paotin/mud/
 
 COPY ids/EXAMPLE        /paotin/ids/
 COPY ids/DEFAULT        /paotin/ids/
 
+COPY init.vim           /paotin/.config/nvim/
+
+COPY --from=0 /vim-plug/plug.vim    /paotin/.local/share/nvim/site/autoload/plug.vim
+COPY --from=0 /gruvbox      /paotin/.local/share/nvim/plugged/gruvbox/
+COPY --from=0 /vim-mbs      /paotin/.local/share/nvim/plugged/vim-mbs/
+COPY --from=0 /mru          /paotin/.local/share/nvim/plugged/mru/
+COPY --from=0 /BufExplorer  /paotin/.local/share/nvim/plugged/BufExplorer/
+COPY --from=0 /vim-startify /paotin/.local/share/nvim/plugged/BufExplorer/
+
 COPY --from=0 /tintin/src/tt++ /paotin/bin/
 
 RUN mkdir -p /paotin/log/
-RUN echo debug log > /paotin/log/debug.log
-RUN echo quest log > /paotin/log/quest.log
-RUN echo tt log > /paotin/log/tt.log
 
-ENTRYPOINT ["/bin/bash", "/paotin/bin/start-ui"]
+ENTRYPOINT ["/bin/bash", "-i", "/paotin/bin/start-ui"]

+ 116 - 0
bin/mtail

@@ -0,0 +1,116 @@
+#!/usr/bin/env bash
+
+#nop vim: set filetype=tt:;
+#nop {
+
+ID=$1
+LOGS="${*:2}"
+
+if [ "x$LOGS" == "x" ]; then
+    LOGS="chat qq jh helpme fullsk quest job tell"
+fi
+
+if [ "x$ID" == "x" ]; then
+    echo -e '用法: \x1b[1;32;92mmtail \x1b[1;33;93m<id>\x1b[0m [<log1> <log2>...]'
+    echo '日志名称不用加路径和 .log 后缀,只要文件名就好。'
+    echo "可以同时显示多个日志,默认显示日志: $LOGS"
+    echo '别忘了写 ID,加油!'
+    exit
+fi
+
+if [[ ! -d "var/log/$ID" && ! -d "log/$ID/" ]]; then
+    echo 没找到 $ID 的游戏日志。请先打开游戏再执行本操作。;
+    exit
+fi
+
+exec tt++ -G -t MLOG-$ID bin/mtail $ID $LOGS
+exit
+
+};
+
+#event {PROGRAM START} {
+    #if { "%0" == "" } {
+        #end {\};
+    };
+
+    disable-all-keys;
+    #alias {okLog}          {#0};
+    #alias {warnLog}        {#0};
+    #alias {prompt.Set}     {#0};
+    #alias {prompt.refresh} {#0};
+    #read plugins/lib/ui/mouse.tin;
+    #read plugins/lib/ui/beautify.tin;
+    #local _ {@lib_ui_beautify.Init{}};
+    monitor-log %0;
+};
+
+#alias {disable-all-keys} {
+    #local ch {};
+    #parse {abcdefghijklmnopqrstuvwxyz} {ch} {
+        #macro {\c$ch} {#0};
+        #macro {$ch} {#0};
+    };
+    #parse {ABCDEFGHIJKLMNOPQRSTUVWXYZ} {ch} {
+        #macro {$ch} {#0};
+    };
+    #parse {`1234567890-=~!@#$%^&*()_+} {ch} {
+        #macro {$ch} {#0};
+    };
+    #parse {,./<>?;':"[]\\|} {ch} {
+        #macro {$ch} {#0};
+    };
+    #macro {\x7B} {#0};
+    #macro {\x7D} {#0};
+
+    #macro {\cn}    {switch-log +};
+    #macro {\cp}    {switch-log -};
+
+    #var ctrl-c-pressed {false};
+    #macro {\cc} {
+        #if { "$ctrl-c-pressed" == "false" } {
+            #echo {如果你想要退出,请再按一次 Ctrl+C。};
+            #var ctrl-c-pressed {true};
+            #delay cancel {
+                #echo {等待超时,恢复正常。};
+                #var ctrl-c-pressed {false};
+            } {1.000};
+        };
+        #else {
+            #showme {\e]2;NOLOG\a\};
+            #end {\};
+        };
+    };
+};
+
+#alias {switch-log} {
+    #local dir {%1};
+    #if { "$dir" == "" } {
+        #local dir {+};
+    };
+    #session $dir;
+    #buffer end;
+    #script logname {echo $LOGNAME > tmux/$ID/log-name};
+    #showme {\e]2;MLOG-${ID}-${LOGNAME}\a\};
+};
+
+#alias {monitor-log%+1..s%+1..S{?:|\s+(.*)}$} {
+    #local  id      {%2};
+    #local  logs    {%3};
+
+    #local path {};
+    #script path {test -d var/log/$id/ && echo var/log/$id || echo log/$id};
+    #local path {$path[1]};
+    #list logs create $logs;
+    #local log {};
+    #foreach {$logs[]} {log} {
+        #local file {$path/${log}.log};
+        #script {tmp} {touch $file};
+        #run {log-$log} {tail -n 1000 -f $path/${log}.log};
+        #var LOGNAME {$log};
+        #var ID      {$id};
+    };
+
+    switch-log;
+};
+
+#event {SCREEN RESIZE} {#buffer end};

+ 2 - 1
bin/start

@@ -1,6 +1,7 @@
 #!/bin/sh
 
 TT=
+ID=$1
 START_FILE=$1
 
 ECHO="echo -e"
@@ -35,4 +36,4 @@ fi
 $ECHO "\x1b[1;32m启动 tintin...\x1b[0m"
 $ECHO "\x1b[1;32m$TT $START_FILE\x1b[0m"
 
-$TT $START_FILE
+$TT -G -t GAME-$ID $START_FILE

+ 16 - 11
bin/start-ui

@@ -7,32 +7,37 @@ if [ "x$MODE" == "xdaemon" ]; then
     exit
 fi
 
-if [ "x$MODE" == "xLOGO" ]; then
-    echo -e 'PaoTin++\n庖丁加加' | head -$(expr $(date '+%s') '/' 10 '%' 2 '+' 1) | tail -1
-    exit
-fi
-
 if [ "x$TMUXCMD" = "x" ]; then
     export TMUXCMD="tmux -L MUD"
 fi
 
 SESSION=MUD
 
+# 等待终端状态同步
+echo 正在打开终端...
+sleep 0.5;
+
+echo 正在连接 UI...
+
 # 优先连接到已有的会话,继续之前的状态
 $TMUXCMD attach-session -t $SESSION && exit
 
+echo 正在生成 UI...
+
+HEIGHT=$(tput lines || ( [[ "x$LINES" != "x" ]] && echo $LINES ) || echo 30)
+HEIGHT=$(expr $HEIGHT - 1 - 1 - 1 - 6)
+
 # 如果尚未创建会话,则创建一个标准会话
 $TMUXCMD new-session -d -s $SESSION
 $TMUXCMD new-window     -t $SESSION
-$TMUXCMD send-keys      -t $SESSION "touch log/debug.log && tail -f log/debug.log"
-$TMUXCMD send-keys      -t $SESSION Enter
-$TMUXCMD rename-window  -t $SESSION 调试日志
 $TMUXCMD select-window  -t $SESSION:0
-$TMUXCMD split-window   -t $SESSION -vbl 5
-$TMUXCMD send-keys      -t $SESSION "touch log/quest.log && tail -f log/quest.log"
+$TMUXCMD split-window   -t $SESSION -vb
+$TMUXCMD send-keys      -t $SESSION 'clear; echo "You could input \"mtail id\" to watch your game log."; mtail'
 $TMUXCMD send-keys      -t $SESSION Enter
 $TMUXCMD last-pane
-$TMUXCMD send-keys      -t $SESSION "doc HOW-TO-PLAY.md"
+$TMUXCMD send-keys      -t $SESSION "sleep 0.1; tmux resize-pane -y $HEIGHT; clear; doc HOW-TO-PLAY.md"
 $TMUXCMD send-keys      -t $SESSION Enter
 
+echo UI 已创建。
+
 exec $TMUXCMD attach-session -t $SESSION

+ 74 - 0
bin/tmux-ui

@@ -0,0 +1,74 @@
+#!/usr/bin/env bash
+
+#
+# 这是一堆乱七八糟的和 tmux UI 元素相关的小功能的集合。
+# 通过 ELEMENT 来区分想要的是哪个元素,目前支持的有 LOGO/WIN/PANE 三大类
+# LOGO: tmux 右下角的一个 LOGO 显示,计划将版本号也放进去
+# WIN:  tmux 状态栏中,窗口标题会显示角色 ID
+# PANE: 会在 tmux pane 上显示一些有用的信息,目前支持两种,用第二个参数 ARG 来控制
+#       ARG=GAME-id,表示这是游戏主面板,用来显示一些角色数据,约定存放在 tmux/ID/ 目录下
+#       ARG=MLOG-id,表示这是游戏日志监视器,会在 pane 边框线上显示日志名称
+#
+# 需要配合 tmux.conf 使用,将需要的参数特别是 ID 要传过来。
+#
+
+ELEMENT=$1
+ARG=$2
+ARG2=$3
+ARG3=$4
+ID=
+LOGNAME=
+
+if [[ "x$ARG" == xGAME-* ]]; then
+    ID=${ARG:5}
+    mkdir -p tmux/$ID
+    ARG=GAME
+fi
+
+if [[ "x$ARG" =~ xMLOG-(.*)-(.*) ]]; then
+    ID=${BASH_REMATCH[1]}
+    LOGNAME=${BASH_REMATCH[2]}
+    mkdir -p tmux/$ID
+    ARG=MLOG
+fi
+
+# 每隔十秒钟轮换显示英文和中文 LOGO
+if [ "x$ELEMENT" == "xLOGO" ]; then
+    echo -e 'PaoTin++\n庖丁加加' | head -$(expr $(date '+%s') '/' 10 '%' 2 '+' 1) | tail -1
+    exit
+fi
+
+if [ "x$ELEMENT" == "xWIN" ]; then
+    if [ "x$ID" != "x" ]; then
+        echo $ID
+    else
+        echo '#W'
+    fi
+    exit
+fi
+
+if [ "x$ELEMENT" == "xPANE" ]; then
+    if [ "x$ARG" == "xMLOG" ]; then
+        echo -n " 正在查看 #[bg=blue fg=brightyellow bold]$LOGNAME#[default] 日志"
+        if [ "x$ARG2" == "x1" ]; then
+            echo -n ",Ctrl+N/Ctrl+P 切换,Ctrl+CC 退出 "
+        else
+            echo -n " "
+        fi
+    elif [ "x$ARG" == "xGAME" ]; then
+        echo -n " $(cat tmux/$ID/char-data || echo 尚未找到 $ID 的角色数据,请检查机器人版本) "
+    else
+        WIDTH=${ARG3-0}
+        if [ $WIDTH -gt 100 ]; then
+            echo -n ' 终端: #{client_termname} 当前目录: #{pane_current_path} #[align=right] 尺寸: #{pane_width}x#{pane_height} '
+        elif [ $WIDTH -gt 80 ]; then
+            echo -n ' #{client_termname} #{pane_current_path} #[align=right] #{pane_width}x#{pane_height} '
+        elif [ $WIDTH -gt 40 ]; then
+            echo -n ' #{client_termname} #[align=right] #{pane_width}x#{pane_height} '
+        elif [ $WIDTH -gt 20 ]; then
+            echo -n '#[align=right] #{pane_width}x#{pane_height} '
+        else
+            echo -n ''
+        fi
+    fi
+fi

+ 1 - 0
framework/main.tin

@@ -42,6 +42,7 @@ PaoTin++ © 2020~2022 的所有版权均由担子炮(dzp <danzipao@gmail.com>) 
         load-module lib/event;
         load-module lib/ui/prompt;
         load-module lib/ui/beautify;
+        load-module lib/ui/tmux;
     };
 };
 

+ 1 - 1
ids/EXAMPLE

@@ -11,7 +11,7 @@ PaoTin++ © 2020~2022 的所有版权均由担子炮(dzp <danzipao@gmail.com>) 
 ===========
 */
 
-#nop 载入担子炮的 TinTin 脚本框架;
+#nop 载入 PaoTin++ 环境;
 #read {framework/main.tin};
 
 #nop 你要连哪个接入;

+ 65 - 0
init.vim

@@ -0,0 +1,65 @@
+silent! call plug#begin()
+Plug 'dzpao/vim-mbs'
+Plug 'morhetz/gruvbox'
+Plug 'yegappan/mru'
+Plug 'jlanzarotta/BufExplorer'
+call plug#end()
+
+" 不兼容 vi
+set nocompatible
+" 用空格代替 TAB
+set expandtab
+" 整体左移或者右移时,每次 4 个空格
+set shiftwidth=4
+" TAB 键按 4 空格对齐
+set tabstop=4
+set softtabstop=4
+set smarttab
+
+" 开启真彩色
+set termguicolors
+" 开启真彩色配色方案
+colorscheme gruvbox
+highlight Normal guibg=#1d2021
+" 显示行号
+set number
+" 显示相对行号
+set relativenumber
+" 显示光棒
+set cursorline
+" 80 列高亮,提醒边界线
+set colorcolumn=80
+
+" 文件写入成功后,不保留备份文件
+set nobackup
+" 直接写原文件,不先建立备份
+set nowritebackup
+" 不要交换文件
+set noswapfile
+
+" 开启鼠标支持
+set mouse=nvi
+
+" 开启自动缩进
+set cindent
+
+" 自动识别文件编码
+set fileencodings=utf8,gbk
+
+" 始终用 utf8 显示
+set encoding=utf8
+
+" 开启 modeline 支持
+set modeline
+
+" F 开启 Buffer Explorer
+nmap F :BufExplorer<CR>
+nnoremap <silent> ,F F
+nnoremap <silent> ,f F
+autocmd BufEnter \[BufExplorer\] nmap <buffer><silent> F q
+
+" M 开启/关闭 MRU
+nmap <silent> M :MRU<CR>
+nnoremap <silent> ,M M
+autocmd BufEnter __MRU_Files__ nnoremap <buffer><silent> M :q<CR>
+autocmd BufEnter -RecentFiles- nnoremap <buffer><silent> M :q<CR>

+ 6 - 0
mud/pkuxkx/plugins/basic/char/score.tin

@@ -146,6 +146,8 @@
         #class char-score-parser kill;
         #replace char[档案][年龄] {岁} {};
         #var char[档案][年龄] {@c2d{$char[档案][年龄]}};
+
+        event.Emit {char/status};
     };
 
     #class char-score-parser close;
@@ -153,4 +155,8 @@
     
 load-module {basic/title};
 
+load-lib event;
+
+event.Define {char/status} {无参} {$MODULE} {score 命令的数据解析成功时,发送本事件}
+
 score;

+ 19 - 0
plugins/lib/ui/tmux.tin

@@ -0,0 +1,19 @@
+#alias {tmux.UpdateCharData} {
+    #if { "$char[档案][账号]" == "" } {
+        #return;
+    };
+
+    #local id       {#[fg=brightwhite]$char[档案][账号]#[default]};
+    #local name     {#[fg=brightcyan]$char[档案][大名]#[default]};
+    #local title    {$char[档案][头衔]};
+    #replace title  {;} { };
+    #local title    {#[bold fg=red]$title#[default]};
+    #local file     {tmux/$char[档案][账号]/char-data};
+
+    #script {tmp} {echo "ID: [$id] 大名: [$name] 头衔: [$title]" > $file};
+    #script {tmp} {tmux refresh};
+};
+
+load-lib event;
+
+event.Handle {char/status} {tmux} {ui} {tmux.UpdateCharData};

+ 9 - 2
profile.sh

@@ -3,9 +3,16 @@
 export LANG=zh_CN.UTF8
 export TERM=xterm-256color
 
+export LESS="-r -f"
 export PATH=$HOME/bin:$PATH
 export PS1='\[\033[01;40;32m\]MUD\[\033[00m\]:\[\033[33m\]\w\[\033[00m\]\$ '
 
-alias ll='ls -l'
-alias vim=vi
 set -o vi
+
+bind '"\C-n": history-search-forward'
+bind '"\C-p": history-search-backward'
+
+alias ll='ls -l'
+alias l='ls -lah'
+alias vim=nvim
+alias vi=nvim

+ 1 - 1
tintin

@@ -1 +1 @@
-Subproject commit 5d6799643270350530c1f27e238eb5d91661a1da
+Subproject commit 1e33c9cb07b29f73d1f0eab83a9668894349df74

+ 12 - 5
tmux.conf

@@ -47,20 +47,27 @@ set -g status-justify left
 set -g status-bg blue
 # 状态栏左部最大长度不超过 32
 set -g status-left-length 32
-# 状态栏左部的格式: 红色的主机名(#h),然后是亮品红的日期时间
-set -g status-left "#[fg=magenta,bold]%m-%d %H:%M #[fg=brightyellow,bold]#{session_name} #[fg=red,bold]| "
+# 状态栏左部的格式: 亮品的日期时间,然后是亮黄色的主机名(#h)
+set -g status-left "#[fg=magenta,bold]%m-%d %H:%M #[fg=brightyellow,bold]#h #[fg=red,bold]| "
 # 状态栏右部最大长度不超过 32
 set -g status-right-length 32
 # 状态栏右部显示内容
-set -g status-right "#[fg=brightyellow]| #(~/bin/start-ui LOGO)#[default]"
+set -g status-right "#[fg=brightyellow]| #(tmux-ui LOGO)#[default]"
 # 状态栏窗口列表中,每个窗口的显示格式: 绿色的编号(#I)及窗口名称(#W)
-setw -g window-status-format '#[fg=green]#I-#W#[default]'
+setw -g window-status-format '#[fg=green]#I-#(tmux-ui WIN #{pane_title})#[default]'
 # 状态栏窗口列表中,当前窗口的显示格式: 黄色的编号(#I)及窗口名称(#W)
-setw -g window-status-current-format '#[fg=brightyellow]#I-#W#[default]'
+setw -g window-status-current-format '#[fg=brightyellow]#I-#(tmux-ui WIN #{pane_title})#[default]'
 # 状态栏窗口列表中,有事件的窗口的显示风格
 setw -g window-status-activity-style fg=red,bold,bg=default
 # 状态栏窗口列表中,有喇叭的窗口的显示风格
 setw -g window-status-bell-style fg=red,bold,bg=default
+# Pane 的边框格式
+set -g pane-border-format '#(tmux-ui PANE #{pane_title} #{pane_active} #{pane_width})'
+# 固定给每个 pane 顶部显示一个边框
+set -g pane-border-status top
+# 设置边框颜色
+set -g pane-active-border-style "bg=colour236,fg=cyan bold"
+set -g pane-border-style        "bg=colour234,fg=white"
 # tmux 的信息也会显示在状态栏,包括 tmux 的命令行
 set -g message-style fg=brightyellow,bold,bg=red
 # 设置信息显示时间