Как работать с копировальной пастой в ncurses?
Кажется, ncurses обрабатывает вставку (из копии, вставляет), вставляя по одному символу за раз из текста, который был вставлен, что может быть медленным, если обработчик для каждого символа медленный. Я бы хотел обрабатывать события вставки самостоятельно, когда обнаружена последовательность вставки в скобках, начиная с ESC [200 ~ ( http://www.xfree86.org/current/ctlseqs.html).
2 ответа
Я подумал, что это работает после включения режима вставки в скобках, но это нужно делать с необработанными терминальными последовательностями, так как ncurses не предоставляет поддержки для этого сам по себе.
Вот код, иллюстрирующий «режим вставки в скобках» (с использованием проклятий Ruby).
Есть только три ключевых момента:
0.) Убедитесь, что ваш терминал поддерживает режим вставки в скобках (например, терминал Windows 10 примерно с 1 месяца, см. Https://github.com/microsoft/terminal/releases/tag/v1.7.572.0 )
1.) Включите режим вставки в скобках в терминале, отправив
?2004h
CSI.
print("\x1b[?2004h")
2.) Когда происходит паста, узнайте, что вы получили
\x1b[200~
чтобы начать разбор вставленного текста и
\x1b[201~
чтобы распознать, что вставленный текст закончен.
# /usr/bin/ruby2.7
require "curses"
include Curses
def main_loop
init_screen
noecho # Disable Echoing of character presses
# Switch on braketed paste mode
print("\x1b[?2004h")
addstr("Please paste something into this terminal (make sure it supports braketed paste!) or press 'q' to quit.\n")
loop do
c = get_char2
case c
in 'q' # use q to quit
return
in csi: "200~" # Bracketed paste started
pasted = ""
loop do
d = get_char2
case d
in csi: "201~" # Bracketed paste ended
break
else
pasted += d
end
end
addstr("You pasted: #{pasted.inspect}\n")
else
addstr("You didn't paste something, you entered: #{c.inspect} #{c.class.name}\n")
end
end
ensure
close_screen
end
#
# For CSI, or "Control Sequence Introducer" commands,
# the ESC [ is followed by
# 1.) any number (including none) of "parameter bytes" in the range
# 0x30–0x3F (ASCII 0–9:;<=>?), then by
# 2.) any number of "intermediate bytes" in the range
# 0x20–0x2F (ASCII space and !"#$%&'()*+,-./), then finally by
# 3.) a single "final byte" in the range
# 0x40–0x7E (ASCII @A–Z[\]^_`a–z{|}~).
#
# From: https://handwiki.org/wiki/ANSI_escape_code
def get_csi
result = ""
loop do
c = get_char
result += c
if c.ord >= 0x40 && c.ord <= 0x7E
return result
end
end
end
# Just like get_char, but will read \x1b[<csi> and return it as a hash { csi: ... }, everything else is just returned as-is
def get_char2
c = get_char
case c
when "\e" # ESC
case get_char
when '['
return { csi: get_csi }
else
raise "¯\_(ツ)_/¯"
end
else
return c
end
end
main_loop()