Escape sequences ในเอาต์พุตของสคริปต์ที่เรียกจากแอ็พพลิเคชัน ncurses


14

ขณะนี้ฉันกำลังเรียกใช้ mcabber เป็นลูกค้า Jabber ของฉัน (ซึ่งใช้ ncurses) ในเซสชั่น tmux บน homeserver ของฉัน ในพื้นที่ฉันเรียกใช้ iTerm2 เป็นเทอร์มินัลอีมูเลเตอร์ซึ่งรองรับการกระตุ้นการแจ้งเตือนคำรามผ่านลำดับการหลีกเลี่ยงตัวละคร

หมายเหตุ: ทั้งหมดechoในคำถามนี้ทำงานเหมือนprintf %bหรือecho -eในทุบตีและ echoGNU

เช่นecho "\e]9;foobar\007"ทำให้ iTerm2 ส่งข้อความคำรามด้วยข้อความ "foobar"

อย่างไรก็ตามเมื่ออยู่ในเซสชั่น tmux ลำดับการหลีกเลี่ยงจะถูกทำลาย ดังนั้นการใช้ลำดับ escape character ที่เป็นกรรมสิทธิ์\Ptmuxสามารถใช้ดังนี้:

echo "\ePtmux;\e\e]9;foobar\007\e\\"

สิ่งนี้ทริกเกอร์ข้อความคำรามจากภายในเซสชัน tmux

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

ฉันคิดว่าสิ่งนี้เกี่ยวข้องกับ mcabber ซึ่งเรียกสคริปต์ว่าเป็นแอปพลิเคชัน ncurses ดังนั้นผลลัพธ์จากสคริปต์ทุบตีปกติของฉันจะหายไปและ iTerm 2 ไม่เคยเห็นเลย

ฉันพยายามโทร smcup โดยไม่ประสบความสำเร็จก่อนที่จะสะท้อนความคิดบางอย่างที่ฉันค้นพบ

tput smcup
echo "\ePtmux;\e\e]9;$FROM: $MSG\007\e\\"
tput rmcup

ฉันคิดว่าสิ่งนี้ไม่ทำงานเนื่องจากปัญหาไม่ได้เปลี่ยนกลับไปเป็น "หน้าต่างเทอร์มินัลจริง" แต่ให้นำผลลัพธ์ไปที่หน้าต่าง ncurses มากขึ้น

ความคิดใด ๆ เกี่ยวกับเรื่องนี้?

คำตอบ:


1

สาเหตุที่สคริปต์เหตุการณ์ล้มเหลวในการส่งข้อความ "ผู้ปลูก" คือการmcabberปิดอินพุตอินพุตเอาต์พุตและสตรีมข้อผิดพลาดมาตรฐานเมื่อรันคำสั่งเหตุการณ์ คุณสามารถเห็นสิ่งนี้ในhooks.c:

  if ((pid=fork()) == -1) {
    scr_LogPrint(LPRINT_LOGNORM, "Fork error, cannot launch external command.");
    g_free(datafname);
    return;   
  }    
  if (pid == 0) { // child
    // Close standard file descriptors
    close(STDIN_FILENO);
    close(STDOUT_FILENO);
    close(STDERR_FILENO);
    if (execl(extcmd, extcmd, arg_type, arg_info, bjid, arg_data,
              (char *)NULL) == -1) {
      // scr_LogPrint(LPRINT_LOGNORM, "Cannot execute external command.");
      exit(1);
    }
  }
  g_free(datafname);

mcabberที่ทำให้การทำงานสคริปต์เหตุการณ์โดยไม่รบกวนกับกระแสที่ใช้โดย

ไม่มีโหมด ncurses พิเศษ intercepting ข้อความ (หลังจากทั้งหมดเป็นtmuxเป็นแล้วทำงานเป็นโปรแกรม terminfo ก) คุณสามารถแก้ไขปัญหาได้โดยเปลี่ยนเส้นทางของคุณecho(ดีกว่าprintf) ไปที่/dev/ttyเช่น

#!/bin/sh
printf '\033Ptmux;\033\033]9;foobar\007\033\\' >/dev/tty

0

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


0

ถ้าคุณใส่อะไรลงไป ...

export "PTTY=$(tty)"

... ใน/etc/profileตอนนั้นสำหรับ-lเชลล์ ogin ใหม่ทุกตัวที่คุณจะเรียกใช้(ซึ่งเป็นสิ่งที่เกิดขึ้นโดยทั่วไปเมื่อคุณเปิดหน้าต่างเทอร์มินัลใหม่)ว่าตัวแปรสภาพแวดล้อมจะพร้อมใช้งานสำหรับกระบวนการลูกทั้งหมด - ซึ่งควรรวมtmuxและลูก ๆ ทั้งหมด .

สิ่งนี้จะช่วยให้คุณทำ ...

printf '\033]9;foobar\007' >"$PTTY"

... และข้ามผ่านptyเลเยอร์ใด ๆที่อาจมีอยู่ระหว่างเชลล์ปัจจุบันและเทอร์มินัลอีมูเลเตอร์ที่คุณใช้อยู่


0

หากปัญหาคือว่าผลลัพธ์จากสคริปต์ทุบตีของคุณกำลังสูญหายคุณสามารถชนะการต่อสู้ด้วยการเปลี่ยนเส้นทาง:

echo "\ ePtmux; \ e \ e] 9; foobar \ 007 \ e \"> / dev / tty

อย่างไรก็ตามฉันสงสัยว่าปัญหาจริงคือคุณควรใช้echo -eเพื่อให้ bash ประมวลผลลำดับ escape ในสตริงของคุณ

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