module Curses::WindowExtensions

Public Instance Methods

addstr_with_cursor(line, cursor_x) click to toggle source
# File lib/rodo/curses_util.rb, line 72
def addstr_with_cursor(line, cursor_x)
  line = line + " "

  Curses.debug "Before Cursor: '#{line[...cursor_x]}'"
  Curses.debug "Cursor_x: '#{cursor_x}'"

  cursor_x = 0 if cursor_x < 0
  cursor_x = line.size - 1 if cursor_x >= line.size

  addstr line[...cursor_x] if cursor_x > 0
  attron(Curses::A_REVERSE)
  addstr line[cursor_x]
  attroff(Curses::A_REVERSE)
  addstr(line[(cursor_x+1)..]) if cursor_x < line.size
  addstr("\n")
end
box(*args) click to toggle source

Override box() to call box(0, 0)

Calls superclass method
# File lib/rodo/curses_util.rb, line 42
def box(*args)
  if args.size == 0
    super(0, 0)
  else
    super(*args)
  end
end
caption(string) click to toggle source

Add the given string to the top left borner of a box window

# File lib/rodo/curses_util.rb, line 65
def caption(string)
  p = getyx
  setpos(0,1)
  addstr(string)
  setpos(*p)
end
get_char2() click to toggle source

Just like get_char, but will read x1b[<csi> return it as a hash { csi: … }, everything else is just returned as-is

# File lib/rodo/curses_util.rb, line 138
def get_char2
  c = get_char
  case c
  when "\e" # ESC
    d = get_char
    case d
    when '['
      return { csi: get_csi }
    else
      Curses.unget_char(d)
      return "\e"
      # Curses.abort("Unhandled command sequence")
      # raise "¯\_(ツ)_/¯"
    end
  else
    return c
  end
end
get_char3() click to toggle source

Just like get_char2, but will read csi: “200~” as bracketed paste and return it as a hash { paste: <text> }, everything else is just returned as from get_char2

# File lib/rodo/curses_util.rb, line 160
def get_char3
  c = get_char2
  case c
  in csi: "200~" # Bracketed paste started
    return { paste: get_paste_text }
  else
    return c
  end
end
get_csi() click to toggle source

Reads a Control Sequence Introducer (CSI) from `get_char`

Requires that ANSI Control Sequence “x1b[” has already been consumed.

Assumes that there are no errors in the CSI.

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: handwiki.org/wiki/ANSI_escape_code

# File lib/rodo/curses_util.rb, line 122
def get_csi

  result = "".dup
  loop do
    c = get_char
    result += c
    if c.ord >= 0x40 && c.ord <= 0x7E
      return result
    end
  end

end
get_paste_text() click to toggle source

Will read until the end of a bracketed paste marker “x1b[201~” Requires that the “x1b[200~” start marker has already been processed. The returned text does NOT include the end marker “200~”

# File lib/rodo/curses_util.rb, line 92
def get_paste_text
  pasted = ""
  loop do
    d = get_char2
    case d
    in csi: "201~" # Bracketed paste ended
      break
    else
      pasted += d
    end
  end
  return pasted
end
gets(start_string) { |line| ... } click to toggle source

Will take care of reading a string from the user, given the start_string

# File lib/rodo/curses_util.rb, line 171
def gets(start_string)

  line = start_string
  cursor_x = line.length
  start_pos = getyx

  loop do

    clear
    setpos(*start_pos)
    addstr_with_cursor(line, cursor_x)

    yield line

    char = get_char
    case char

    when CTRLC, CTRLC.chr, ESC, ESC.chr
      return :close

    when "\u0001" # CTRL+A
      cursor_x = 0

    when "\u0005" # CTRL+E
      cursor_x = line.length

    when Curses::KEY_LEFT
      cursor_x -= 1 if cursor_x > 0

    when Curses::KEY_RIGHT
      cursor_x += 1 if cursor_x < line.length - 1

    when Curses::KEY_DC, "\u0004" # DEL, CTRL+D
      if cursor_x < line.size
        line.slice!(cursor_x)
      end

    when Curses::KEY_BACKSPACE
      if cursor_x > 0
        line.slice!(cursor_x - 1)
        cursor_x -= 1
      end

    when ENTER, ENTER.chr
      return line

    when /[[:print:]]/

      line.insert(cursor_x, char)
      cursor_x += 1

    else
      Curses.debug "Char not handled: " + Curses::char_info(char)
    end

  end

end
getyx() click to toggle source

Return the current coordinates of the cursor [y,x]

# File lib/rodo/curses_util.rb, line 60
def getyx
  return [cury(), curx()]
end
inset(n=1) click to toggle source

Create a subwindow inside this window which is padded by the given number n (lines and characters)

# File lib/rodo/curses_util.rb, line 37
def inset(n=1)
  subwin(maxy - 2 * n, maxx - 2 * n, begy + n, begx + n)
end
puts(string) click to toggle source

Add the given string to this window and put the cursor on the next line

# File lib/rodo/curses_util.rb, line 51
def puts(string)
  if maxx - curx == string.length
    addstr(string)
  else
    addstr(string + "\n")
  end
end