如何在ncurses中处理复制粘贴?

时间:2014-12-10 17:32:32

标签: paste ncurses

似乎ncurses通过从粘贴的文本一次插入一个字符来处理粘贴(来自复制粘贴),如果每个字符的处理程序很慢,这可能会很慢。 我喜欢自己处理粘贴事件,当一个方括号粘贴'检测序列,从ESC [200~(http://www.xfree86.org/current/ctlseqs.html#Bracketed%20Paste%20Mode)开始。

2 个答案:

答案 0 :(得分:1)

我认为在启用括号粘贴模式后它可以工作,但这需要使用原始终端序列,因为ncurses本身并不提供支持。

答案 1 :(得分:0)

这里有一些代码说明了“括号粘贴模式”(使用 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()