Skip to content

Instantly share code, notes, and snippets.

@SamSirry
Forked from mvidner/sendkeys
Last active March 26, 2025 14:27
Show Gist options
  • Select an option

  • Save SamSirry/8d178da919cc8760a00bb1590a1ea870 to your computer and use it in GitHub Desktop.

Select an option

Save SamSirry/8d178da919cc8760a00bb1590a1ea870 to your computer and use it in GitHub Desktop.

Revisions

  1. @mvidner mvidner revised this gist Feb 11, 2014. 1 changed file with 1 addition and 0 deletions.
    1 change: 1 addition & 0 deletions sendkeys
    Original file line number Diff line number Diff line change
    @@ -35,6 +35,7 @@ require "optparse"

    # incomplete! only what I need now.
    KEYS = {
    "%" => "shift-5",
    "/" => "slash",
    ":" => "shift-semicolon",
    "=" => "equal",
  2. @mvidner mvidner created this gist Feb 11, 2014.
    104 changes: 104 additions & 0 deletions sendkeys
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,104 @@
    #!/usr/bin/env ruby
    # Translate a string to "sendkey" commands for QEMU.
    # Martin Vidner, MIT License

    # https://en.wikibooks.org/wiki/QEMU/Monitor#sendkey_keys
    # sendkey keys
    #
    # You can emulate keyboard events through sendkey command. The syntax is: sendkey keys. To get a list of keys, type sendkey [tab]. Examples:
    #
    # sendkey a
    # sendkey shift-a
    # sendkey ctrl-u
    # sendkey ctrl-alt-f1
    #
    # As of QEMU 0.12.5 there are:
    # shift shift_r alt alt_r altgr altgr_r
    # ctrl ctrl_r menu esc 1 2
    # 3 4 5 6 7 8
    # 9 0 minus equal backspace tab
    # q w e r t y
    # u i o p ret a
    # s d f g h j
    # k l z x c v
    # b n m comma dot slash
    # asterisk spc caps_lock f1 f2 f3
    # f4 f5 f6 f7 f8 f9
    # f10 num_lock scroll_lock kp_divide kp_multiply kp_subtract
    # kp_add kp_enter kp_decimal sysrq kp_0 kp_1
    # kp_2 kp_3 kp_4 kp_5 kp_6 kp_7
    # kp_8 kp_9 < f11 f12 print
    # home pgup pgdn end left up
    # down right insert delete

    require "optparse"

    # incomplete! only what I need now.
    KEYS = {
    "/" => "slash",
    ":" => "shift-semicolon",
    "=" => "equal",
    "." => "dot",
    " " => "spc"
    }

    class Main
    attr_accessor :command
    attr_accessor :delay_s
    attr_accessor :keystring

    def initialize
    self.command = nil
    self.delay_s = 0.1

    OptionParser.new do |opts|
    opts.banner = "Usage: sendkeys [-c command_to_pipe_to] STRING\n" +
    "Where STRING can be 'ls<enter>ls<gt>/dev/null<enter>'"

    opts.on("-c", "--command COMMAND",
    "Pipe sendkeys to this commands, individually") do |v|
    self.command = v
    end
    opts.on("-d", "--delay SECONDS", Float,
    "Delay SECONDS after each key (default: 0.1)") do |v|
    self.delay_s = v
    end
    end.parse!
    self.keystring = ARGV[0]
    end

    def sendkey(qemu_key_name)
    qemu_cmd = "sendkey #{qemu_key_name}"
    if command
    system "echo '#{qemu_cmd}' | #{command}"
    else
    puts qemu_cmd
    $stdout.flush # important when we are piped
    end
    sleep delay_s
    end

    PATTERN = /
    \G # where last match ended
    < [^>]+ >
    |
    \G
    .
    /x
    def run
    keystring.scan(PATTERN) do |match|
    if match[0] == "<"
    key_name = match.slice(1..-2)
    sendkey case key_name
    when "lt" then "shift-comma"
    when "gt" then "shift-dot"
    else key_name
    end
    else
    sendkey KEYS.fetch(match, match)
    end
    end
    end
    end

    Main.new.run