ชื่อบานหน้าต่างใน Tmux


89

บนเครื่องโลคัลของฉันฉันมีอินสแตนซ์ 3 node.js ที่ทำงานพร้อมกัน แต่ละห้องมีบานหน้าต่างของตัวเองในหน้าต่าง tmux ที่เรียกว่า "servers" ปัญหาคือไม่ใช่เรื่องง่ายที่จะทราบว่าโหนดใดกำลังทำงานอยู่ในบานหน้าต่างใดเนื่องจากบันทึกของพวกเขาคล้ายกัน

สิ่งที่ฉันต้องการคือชื่อสำหรับทุกบาน อย่างที่ฉันได้รับ tmux เองไม่มีคุณสมบัติ: มีเฉพาะชื่อสำหรับ windows ไม่ใช่สำหรับบานหน้าต่าง การเรียกใช้เซสชัน tmux แยกกันภายในทุกบานหน้าต่างสำหรับทุกอินสแตนซ์ node.js ดูเหมือนโอเวอร์คิล

มีโปรแกรมขนาดเล็กบางโปรแกรมที่เรียกใช้คำสั่งโดยตัดเอาต์พุตด้วยแถบสถานะที่ระบุหรือไม่?

ขอบคุณล่วงหน้า


1
tmux ในเวอร์ชัน 2.3 รองรับชื่อบานหน้าต่างโปรดดูที่stackoverflow.com/a/37602055/266453
Dennis G

คำตอบ:


80

tmuxรองรับชื่อเรื่องต่อบานหน้าต่าง แต่ไม่ได้ระบุตำแหน่งต่อบานหน้าต่างเพื่อแสดงชื่อเรื่องเหล่านี้

คุณสามารถตั้งหัวเรื่องของบานหน้าต่างด้วยลำดับ ESC ]2;... ESC \(เช่นดูส่วนที่เรียกว่าชื่อและชื่อเรื่องในหน้าtmux manpage) คุณสามารถทำได้จากเปลือกเช่นนี้:

printf '\033]2;%s\033\\' 'title goes here'

หัวเรื่องของแต่ละบานจะมีค่าเริ่มต้นเป็นชื่อโฮสต์ของระบบ ตามค่าเริ่มต้นหัวเรื่องของบานหน้าต่างที่ใช้งานอยู่จะแสดงทางด้านขวาของบรรทัดสถานะtmux (ค่าส่วนกลางเริ่มต้นของตัวแปรเซสชันstatus-rightคือ"#22T" %H:%M %d-%b-%yซึ่งแสดงอักขระ 22 ตัวของหัวเรื่องของบานหน้าต่างเวลาและวันที่)

ดังนั้นตราบใดที่คุณพอใจกับความสามารถในการดูหัวเรื่องของบานหน้าต่างที่ใช้งานอยู่ (เช่นยินดีที่จะสลับบานหน้าต่างเพื่อดูชื่อของบานหน้าต่างที่ไม่ได้ใช้งาน) คุณสามารถใช้ฟังก์ชันเริ่มต้นได้ เพียงแค่ส่งลำดับการหลีกเลี่ยงการตั้งค่าหัวเรื่องที่เหมาะสมก่อนที่จะเริ่มคำสั่งหลักสำหรับแต่ละบานหน้าต่าง


หากคุณต้องการบรรทัดเฉพาะเพื่อแสดงข้อมูลต่อบานหน้าต่างเซสชันtmux ที่ซ้อนกันอาจไม่มาก (ไม่จำเป็น)“ overkill” อย่างที่คุณคิดในตอนแรก

ในกรณีทั่วไปในการระบุบรรทัดสถานะไม่ถูกละเมิดในเทอร์มินัลบางเครื่องคุณจะต้องมีตัวจำลองเทอร์มินัล (อีกครั้ง) แบบเต็มที่อยู่ระหว่างเทอร์มินัลเดิมและเทอร์มินัลใหม่ (หนึ่งบรรทัดมีน้อยกว่าหนึ่งบรรทัด) จำเป็นต้องมีการจำลอง (อีกครั้ง) เพื่อแปลลำดับการควบคุมที่ส่งไปยังเทอร์มินัลด้านในและแปลสำหรับเทอร์มินัลดั้งเดิม ตัวอย่างเช่นเพื่อรักษาบรรทัดสถานะที่ด้านล่างของเทอร์มินัลภายนอกให้ใช้คำสั่ง

ย้ายไปที่บรรทัดสุดท้าย

ส่งไปยังเทอร์มินัลด้านในจะต้องกลายเป็น

ย้ายไปที่ถัดจากบรรทัดสุดท้าย

เมื่อแปลและส่งไปยังเทอร์มินัลภายนอก ในทำนองเดียวกัน LF ที่ส่งไปยังเทอร์มินัลด้านในจะต้องกลายเป็น

หากเคอร์เซอร์อยู่ถัดจากบรรทัดสุดท้ายให้เลื่อนบรรทัดนี้และทุกบรรทัดที่อยู่ด้านบนขึ้นมาหนึ่งบรรทัดเพื่อให้เห็นบรรทัดถัดจากบรรทัดสุดท้ายที่ชัดเจน (ป้องกันบรรทัดสถานะในบรรทัดสุดท้าย) มิฉะนั้นให้ส่ง LF

ในขั้วด้านนอก

โปรแกรมเช่นtmuxและหน้าจอเป็นเพียงตัวเลียนแบบเทอร์มินัลเท่านั้น แน่นอนว่ามีฟังก์ชั่นอื่น ๆ อีกมากมายที่ล้อมรอบตัวจำลองเทอร์มินัล แต่คุณจะต้องมีโค้ดจำลองเทอร์มินัลจำนวนมากเพื่อให้บรรทัดสถานะที่เชื่อถือได้


อย่างไรก็ตามมีวิธีแก้ปัญหาที่มีน้ำหนักเบาตราบเท่าที่

  1. โปรแกรมของคุณ ( อินสแตนซ์Node.js ) มีการโต้ตอบเทอร์มินัลที่ จำกัด กับบานหน้าต่างที่กำลังทำงานอยู่ (เช่นไม่มีการวางตำแหน่งเคอร์เซอร์) และ
  2. คุณไม่ได้ปรับขนาดบานหน้าต่างในขณะที่โปรแกรมของคุณกำลังทำงานอยู่

เช่นเดียวกับตัวจำลองเทอร์มินัลหลาย ๆ ตัวtmuxสนับสนุนคำสั่งควบคุมเทอร์มินัล“ set scrolling region” ในบานหน้าต่าง คุณสามารถใช้คำสั่งนี้เพื่อ จำกัด ขอบเขตการเลื่อนไปที่บรรทัด N-1 บนสุด (หรือล่างสุด) ของเทอร์มินัลและเขียนข้อความระบุอินสแตนซ์บางประเภทลงในบรรทัดที่ไม่เลื่อน

ข้อ จำกัด (ไม่อนุญาตให้ใช้คำสั่งการเคลื่อนย้ายเคอร์เซอร์ไม่ต้องปรับขนาด) เนื่องจากโปรแกรมที่สร้างเอาต์พุต (เช่นอินสแตนซ์Node.js ) ไม่มีความคิดว่าการเลื่อนถูก จำกัด ไว้ที่พื้นที่ใดพื้นที่หนึ่ง หากโปรแกรมสร้างเอาต์พุตเกิดเลื่อนเคอร์เซอร์ไปนอกขอบเขตการเลื่อนผลลัพธ์อาจอ่านไม่ออก ในทำนองเดียวกันโปรแกรมจำลองเทอร์มินัลอาจรีเซ็ตพื้นที่การเลื่อนโดยอัตโนมัติเมื่อมีการปรับขนาดเทอร์มินัล (ดังนั้น "เส้นที่ไม่เลื่อน" อาจสิ้นสุดลงด้วยการเลื่อนออกไป)

ฉันเขียนสคริปต์ที่ใช้tputในการสร้างลำดับการควบคุมที่เหมาะสมเขียนลงในบรรทัดที่ไม่เลื่อนและเรียกใช้โปรแกรมหลังจากย้ายเคอร์เซอร์ไปที่ขอบเขตการเลื่อน:

#!/bin/sh

# usage: no_scroll_line top|bottom 'non-scrolling line content' command to run with args
#
#     Set up a non-scrolling line at the top (or the bottom) of the
#     terminal, write the given text into it, then (in the scrolling
#     region) run the given command with its arguments. When the
#     command has finished, pause with a prompt and reset the
#     scrolling region.

get_size() {
    set -- $(stty size)
    LINES=$1
    COLUMNS=$2
}
set_nonscrolling_line() {
    get_size
    case "$1" in
        t|to|top)
            non_scroll_line=0
            first_scrolling_line=1
            scroll_region="1 $(($LINES - 1))"
            ;;
        b|bo|bot|bott|botto|bottom)
            first_scrolling_line=0
            scroll_region="0 $(($LINES - 2))"
            non_scroll_line="$(($LINES - 1))"
            ;;
        *)
            echo 'error: first argument must be "top" or "bottom"'
            exit 1
            ;;
    esac
    clear
    tput csr $scroll_region
    tput cup "$non_scroll_line" 0
    printf %s "$2"
    tput cup "$first_scrolling_line" 0
}
reset_scrolling() {
    get_size
    clear
    tput csr 0 $(($LINES - 1))
}

# Set up the scrolling region and write into the non-scrolling line
set_nonscrolling_line "$1" "$2"
shift 2

# Run something that writes into the scolling region
"$@"
ec=$?

# Reset the scrolling region
printf %s 'Press ENTER to reset scrolling (will clear screen)'
read a_line
reset_scrolling

exit "$ec"

คุณอาจใช้สิ่งนี้:

tmux split-window '/path/to/no_scroll_line bottom "Node instance foo" node foo.js'
tmux split-window '/path/to/no_scroll_line bottom "Node instance bar" node bar.js'
tmux split-window '/path/to/no_scroll_line bottom "Node instance quux" node quux.js'

สคริปต์ควรทำงานนอกtmuxด้วยตราบเท่าที่เทอร์มินัลรองรับและเผยแพร่ความสามารถของมันcsrและcupterminfo


สคริปต์ของคุณทำงานได้ตามที่ฉันคาดไว้ คำถามเดียว: Google จะกำหนดสีของ "non_scroll_line" ได้อย่างไร
Andrey Lushnikov

1
อาจจะเป็น "ความสามารถของ terminfo สีพื้นหลังเบื้องหน้า" (เช่นอ่านเกี่ยวกับสีใน terminfo manpage) คุณสามารถใช้tputเพื่อรวมลำดับการควบคุมที่เหมาะสมในอาร์กิวเมนต์ "เนื้อหาบรรทัด" กับขั้วมากที่สุดคุณสามารถทำให้เส้นเป็น“สีฟ้า (6) และสีเขียว (3) ในสีม่วงแดง (5)” no_scroll_line top "$(tput setaf 6; tput setab 5)Node: $(tput setaf 3)foo$(tput op)" node foo.jsกับ setafตั้งค่าพื้นหน้าsetabตั้งพื้นหลังopรีเซ็ตเป็นสีเริ่มต้นของเทอร์มินัล ความสามารถของสีจะใช้ตัวเลขตั้งแต่ 0–7, 0–15, 0–87 หรือ 0–255 ขึ้นอยู่กับการจำลองเทอร์มินัลของคุณ
Chris Johnsen

ตอนนี้เราออก pymux ซึ่งจะแสดงแถบหัวเรื่อง: github.com/jonathanslenders/pymux
Jonathan Slenders

ดูเหมือนว่าลักษณะการทำงานคือชื่อบานหน้าต่างถูกตั้งค่าเป็นคำสั่งที่รันในเชลล์ ดังนั้นมันจะไม่ "ติด" เว้นแต่ว่าเราจะใช้กระบวนการที่ใช้งานมานานกระบวนการหนึ่ง (ซึ่งยังรู้วิธีส่งออกลำดับการหลีกเลี่ยงการตั้งค่าหัวเรื่อง) ภายใน
Steven Lu

4
โปรดดูคำตอบเพิ่มเติมด้านล่าง: stackoverflow.com/a/37602055/266453 tmux สำหรับเวอร์ชัน 2.3 รองรับชื่อเรื่องในกรอบบานหน้าต่าง
Dennis G

78

ฟังก์ชันนี้ถูกเพิ่มลงใน tmux ในคอมมิตนี้ มันไม่ได้อยู่ในเวอร์ชัน 2.2 แต่ดูเหมือนว่ามันจะอยู่ใน 2.3

ในการเปิดใช้งาน:

tmux set -g pane-border-status top

หรือหากคุณต้องการ:

tmux set -g pane-border-status bottom

ในการตั้งค่าข้อความที่กำหนดเองเป็นบรรทัดสถานะเส้นขอบบานหน้าต่างของคุณคุณสามารถใช้ประโยชน์pane-border-formatได้เช่น:

tmux set -g pane-border-format "#{pane_index} #{pane_current_command}"

1
นี่แสดงหมายเลขของบานหน้าต่างและหัวเรื่องเริ่มต้น คุณจะเปลี่ยนความคิดได้อย่างไร?
ADN

ฉันไม่แน่ใจเกี่ยวกับหมายเลขบานหน้าต่าง แต่มันตอบสนองเหมือนชื่อหน้าต่าง xterm เพื่อหลีกเลี่ยงลำดับ ตัวอย่างเช่น bash ฉันได้ตั้งค่า PS1 = '[\ e] 0; \ u @ \ h: \ w \ a] $' เพื่อรับ "user @ host: working dir /"
kevmitch

เท่าที่ฉันเข้าใจคุณกำหนดลำดับนั้นไว้ก่อนมือ แต่ไม่มีคีย์ลัดหรือคีย์ผสมที่เปลี่ยนแปลงได้ ดังนั้นtmuxคุณต้องมีคำสั่งภายนอกtmuxเพื่อเปลี่ยนแปลง ขวา? หรือมีลำดับอะไรข้างในที่อัพเดทได้ไหม?
ADN

ใช่คุณเพิ่งตั้งค่าตัวแปรในเชลล์ที่กำลังทำงานอยู่และจะอัปเดตเมื่อมีการดึงพรอมต์ถัดไป สำหรับฉันดูเหมือนว่า tmux จะเป็นภาพร่างเล็กน้อยและจะอัปเดตเมื่อคุณเปลี่ยนไปใช้บานหน้าต่างอื่นเท่านั้น
kevmitch

คุณสามารถใช้pane-border-formatเพื่อตั้งค่าสตริงรูปแบบที่กำหนดเองสำหรับบานหน้าต่างที่จะแสดง ( #{...}รูปแบบปกติ) ฉันได้แก้ไขคำตอบของคุณเพื่อรวมสิ่งนี้
Dennis G

35

เนื่องจากtmux 2.6คุณสามารถทำได้:

$ tmux select-pane -t {pane} -T {title}

# Examples:
$ tmux select-pane -T title1          # Change title of current pane
$ tmux select-pane -t 1 -T title2     # Change title of pane 1 in current window
$ tmux select-pane -t 2.1 -T title3   # Change title of pane 1 in window 2

คุณสามารถดูชื่อเรื่องต่อบานหน้าต่างในแถบสถานะด้วย:

$ tmux set pane-border-status bottom      # For current window
$ tmux set -g pane-border-status bottom   # For all windows

ปิดใช้งานแถบสถานะด้วย:

$ tmux set pane-border-status off       # For current window
$ tmux set -g pane-border-status off    # For all windows

คุณรู้หรือไม่ว่ามีวิธีใดบ้างที่จะป้องกันไม่ให้ tmux เปลี่ยนชื่อออกจากตัวคุณ? ตัวอย่างเช่นถ้าฉันตั้งชื่อเรื่องของบานหน้าต่างแล้วทำอะไรบางอย่างในบานหน้าต่างนั้นเช่นcd $HOMEชื่อเรื่องจะเปลี่ยนเป็นค่าของ$HOME. (ฉันเห็นสิ่งนี้ใน tmux 2.8)
pdoherty926

1
@ pdoherty926 บางทีคุณอาจจะได้คำตอบแล้ว แต่ลองดูset-window-option automatic-rename offสิ
noname

ฉันมีset-option -g allow-rename offอยู่ใน.tmux.confไฟล์ของฉัน
Eyal Levin

1
ขอบคุณสำหรับคำแนะนำ ฉันใช้pane-border-formatและผู้ใช้ให้ตัวแปร (ฉันไม่แน่ใจว่ามีชื่ออย่างเป็นทางการสำหรับคุณสมบัตินี้หรือไม่) เพื่อควบคุมสิ่งที่แสดง นี่คือตัวอย่าง
pdoherty926

14

ฉันกำลังทำงานกับแถบสถานะบานหน้าต่างสำหรับ tmux - ticket สามารถดูสาขาการพัฒนาของฉันได้ที่ github: https://github.com/jonathanslenders/tmux

ตอนนี้สิ่งนี้ได้เพิ่มคำสั่งเปลี่ยนชื่อบานหน้าต่างที่ใช้งานได้แล้ว ยังคงมีข้อบกพร่องบางอย่างและ API จะปรับปรุง แนวคิดคือการสร้างแถบสถานะต่อบานหน้าต่างซึ่งอาจมีการจัดรูปแบบบางอย่างเช่นแถบสถานะเซสชัน เช่นเดียวกับ tmux ที่เหลือทุกอย่างควรเป็นแบบสคริปต์และปรับแต่งได้ เมื่อเสร็จสิ้นและเสถียรมันอาจจะรวมอยู่ใน tmux อย่างเป็นทางการ


ในขณะที่คุณอยู่ที่นั่นคุณสามารถทำให้ชื่อบานหน้าต่างกลายเป็นชื่อหน้าต่างเริ่มต้นระหว่างบานหน้าต่างแบ่งได้ไหม
djsadinoff

สาขานี้ไม่เคยรวมเข้ากับ tmux แต่ฉันสร้าง pymux แทนซึ่งมีแถบชื่อเรื่อง: github.com/jonathanslenders/pymux
Jonathan Slenders

คำสั่งนี้ใช้ไม่ได้กับบิลด์ล่าสุด (คอมมิต a24260)
ADN

14

ฉันใช้ tmux เวอร์ชัน 2.3 ฉันคิดว่ารูปแบบเส้นขอบไม่รองรับในเวอร์ชันก่อนหน้า นี่คือสิ่งที่ใช้ได้ผลสำหรับฉัน:

สำหรับแต่ละบานหน้าต่างให้ตั้งชื่อเรื่อง:

printf '\033]2;My Pane Title\033\\'

จากนั้น:

tmux set -g pane-border-format "#{pane_index} #T"

9
อย่างน้อยล่าสุดเป็น tmux 2.6 คุณสามารถเปลี่ยนชื่อบานหน้าต่างภายใน tmux: select-pane -T "my title"ทำสิ่งนี้ คุณสามารถตั้งค่าการผูกคีย์ได้ดังนั้นคุณเพียงแค่ใส่ชื่อ:bind-key T command-prompt -p "New title:" 'select-pane -T "%%"'
lucasem

3
@lucasem อาจจะไม่ได้ติดตามกระทู้นี้ แต่ดูเหมือนว่าจะได้คำตอบ
icicleking

@lucasem ฉันไม่แน่ใจ 100% แต่ฉันเชื่อว่าวิธีการของคุณ (IMO ใดดีที่สุดและง่ายที่สุดในเธรดทั้งหมดนี้สำหรับ tmux เวอร์ชันล่าสุด) จะใช้งานได้pane-border-statusก็ต่อเมื่อตั้งค่าตัวเลือกเป็นบางอย่าง ( topหรือbottom)
cjauvin

11

GIF มีค่าหนึ่งพันคำ (ที่มา )

tmux-xpanesเป็นตัวแบ่งเทอร์มินัลที่ใช้ tmux ซึ่งรองรับการแสดงหัวเรื่องสำหรับแต่ละบานหน้าต่างผ่าน-tตัวเลือกที่เพิ่มใหม่


1
gif มีค่าหนึ่งพันคำ แต่ถ้ามันเชื่อมโยงกันมันไม่คุ้มค่าเลย
คดีของ Fund Monica

7

ใช่มีคำสั่งดังกล่าว: tmux. ตั้งชื่อเซสชันของคุณและจะแสดงในแถบสถานะด้านใน:

TMUX=0 tmux new-session -s my-new-session

2
ใช่ขอบคุณสำหรับคำตอบ! แต่ฉันจะต้องเปิดเซสชัน tmux ใหม่ในทุกบานหน้าต่างสำหรับหนึ่งชื่อที่ด้านล่างของมัน - ประเภท overkill ใช่มั้ย?
Andrey Lushnikov

ฉันไม่รู้ ใช่ไหม? คุณลองแล้วหรือยัง? เซสชั่นพิเศษใช้หน่วยความจำพิเศษเท่าใด
event_jr

ใช่ฉันใช้เซสชัน tmux ที่ซ้อนกันมาจนถึงวันนี้ ฉันไม่แน่ใจเกี่ยวกับการใช้หน่วยความจำและสิ่งต่างๆเช่นนี้ - ฉันไม่ชอบแนวคิดของตัวเองเพราะมันไม่บริสุทธิ์
Andrey Lushnikov

4

สิ่งนี้ไม่เป็นประโยชน์ในระยะสั้น แต่มีการร้องขอคุณสมบัติสำหรับชื่อเรื่องต่อบานหน้าต่างใน tmux: http://sourceforge.net/tracker/?func=detail&aid=3495916&group_id=200378&atid=973265#

ในขณะเดียวกันดังที่คนอื่น ๆ กล่าวถึงการซ้อน tmux จะทำงานได้ดี


0

TL; ดร

เพิ่มการกำหนดค่าต่อไปนี้ในไฟล์กำหนดค่า tmux ของคุณ (ในกรณีของฉันคือ~/.tmux.conf.local)

# dispaly pane_current_path as the pane title
set -g pane-border-status top
set -g pane-border-format "#{pane_index} #{pane_current_path}"

จากนั้นเรียกใช้:

tmux source-file ~/.tmux.con

สนุกกับมัน

ขอบคุณข้อมูลhttps://stackoverflow.com/a/37602055/5121972

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.