Class: I3::IPC
- Inherits:
-
Object
- Object
- I3::IPC
- Defined in:
- lib/i3-ipc.rb
Defined Under Namespace
Classes: WrongMagicCode, WrongType
Constant Summary collapse
- MAGIC_STRING =
"i3-ipc"
- SOCKET_PATH =
File.("~/.i3/ipc.sock")
- MESSAGE_TYPE_COMMAND =
0
- MESSAGE_TYPE_GET_WORKSPACES =
1
- MESSAGE_TYPE_SUBSCRIBE =
2
- MESSAGE_TYPE_GET_OUTPUTS =
3
- MESSAGE_REPLY_COMMAND =
0
- MESSAGE_REPLY_GET_WORKSPACES =
1
- MESSAGE_REPLY_SUBSCRIBE =
2
- MESSAGE_REPLY_GET_OUTPUTS =
3
- EVENT_MASK =
(1 << 31)
- EVENT_WORKSPACE =
(EVENT_MASK | 0)
Class Method Summary collapse
-
.format(type, payload = nil) ⇒ Object
format the message a typical message looks like “i3-ipc” <message length> <message type> <payload>.
-
.parse_response(response) ⇒ Object
parse a full ipc response similar to handle_response, but parses full reply as received by EventMachine.
-
.subscribe(list, socket_path = SOCKET_PATH, &blk) ⇒ Object
shortcut.
Instance Method Summary collapse
-
#close ⇒ Object
closes the socket connection.
-
#closed? ⇒ Boolean
alias for @socket.closed? for easy access.
-
#command(payload) ⇒ Object
send a command to i3.
-
#connect ⇒ Object
connects to the given socket.
- #format(type, payload = nil) ⇒ Object
-
#get_outputs ⇒ Object
Gets the current outputs.
-
#get_workspaces ⇒ Object
gets the current workspaces.
-
#handle_response(type) ⇒ Object
reads the reply from the socket and parse the returned json into a ruby object.
-
#initialize(socket_path = SOCKET_PATH, force_connect = false) ⇒ IPC
constructor
connects to the given i3 ipc interface.
- #parse_response(response) ⇒ Object
- #read(len) ⇒ Object
-
#write(msg) ⇒ Object
writes message to the socket if socket is not connected, it connects first.
Constructor Details
#initialize(socket_path = SOCKET_PATH, force_connect = false) ⇒ IPC
connects to the given i3 ipc interface
32 33 34 35 |
# File 'lib/i3-ipc.rb', line 32 def initialize(socket_path=SOCKET_PATH, force_connect=false) @socket_path = socket_path connect if connect end |
Class Method Details
.format(type, payload = nil) ⇒ Object
format the message a typical message looks like
"i3-ipc" <message length> <message type> <payload>
97 98 99 100 101 102 |
# File 'lib/i3-ipc.rb', line 97 def self.format(type, payload=nil) size = payload ? payload.to_s.bytes.count : 0 msg = MAGIC_STRING + [size, type].pack("LL") msg << payload.to_s if payload msg end |
.parse_response(response) ⇒ Object
parse a full ipc response similar to handle_response, but parses full reply as received by EventMachine
returns an Array containing the reply type and the parsed data
114 115 116 117 118 119 120 121 122 123 |
# File 'lib/i3-ipc.rb', line 114 def self.parse_response(response) if response[0, (MAGIC_STRING.length)] != MAGIC_STRING raise WrongMagicCode end len, recv_type = response[6, 8].unpack("LL") answer = response[14, len] [recv_type, ::JSON.parse(answer)] end |
.subscribe(list, socket_path = SOCKET_PATH, &blk) ⇒ Object
shortcut
38 39 40 |
# File 'lib/i3-ipc.rb', line 38 def self.subscribe(list, socket_path=SOCKET_PATH, &blk) Subscription.subscribe(list, socket_path, &blk) end |
Instance Method Details
#close ⇒ Object
closes the socket connection
146 147 148 |
# File 'lib/i3-ipc.rb', line 146 def close @socket.close end |
#closed? ⇒ Boolean
alias for @socket.closed? for easy access
151 152 153 |
# File 'lib/i3-ipc.rb', line 151 def closed? @socket.closed? end |
#command(payload) ⇒ Object
send a command to i3
the payload is a command for i3 (like the commands you can bind to keys in the configuration file) and will be executed directly after receiving it.
returns { “success” => true } for now. i3 does send this reply without checks
50 51 52 53 |
# File 'lib/i3-ipc.rb', line 50 def command(payload) write format(MESSAGE_TYPE_COMMAND, payload) handle_response MESSAGE_TYPE_COMMAND end |
#connect ⇒ Object
connects to the given socket
141 142 143 |
# File 'lib/i3-ipc.rb', line 141 def connect @socket = UNIXSocket.new(@socket_path) end |
#format(type, payload = nil) ⇒ Object
104 105 106 |
# File 'lib/i3-ipc.rb', line 104 def format(type, payload=nil) self.class.format(type, payload) end |
#get_outputs ⇒ Object
Gets the current outputs. The reply will be a JSON-encoded list of outputs (see the reply section of i3 docu).
67 68 69 70 |
# File 'lib/i3-ipc.rb', line 67 def get_outputs write format(MESSAGE_TYPE_GET_OUTPUTS) handle_response MESSAGE_TYPE_GET_OUTPUTS end |
#get_workspaces ⇒ Object
gets the current workspaces. the reply will be the list of workspaces (see the reply section of i3 docu)
58 59 60 61 |
# File 'lib/i3-ipc.rb', line 58 def get_workspaces write format(MESSAGE_TYPE_GET_WORKSPACES) handle_response MESSAGE_TYPE_GET_WORKSPACES end |
#handle_response(type) ⇒ Object
reads the reply from the socket and parse the returned json into a ruby object
throws WrongMagicCode when magic word is wrong throws WrongType if returned type does not match expected
this is a bit duplicated code but I don’t know a way to read the full send reply without knowing its length
81 82 83 84 85 86 87 88 89 90 91 92 |
# File 'lib/i3-ipc.rb', line 81 def handle_response(type) # reads 14 bytes # length of "i3-ipc" + 4 bytes length + 4 bytes type buffer = read 14 raise WrongMagicCode unless buffer[0, (MAGIC_STRING.length)] == MAGIC_STRING len, recv_type = buffer[6..-1].unpack("LL") raise WrongType unless recv_type == type answer = read len ::JSON.parse(answer) end |
#parse_response(response) ⇒ Object
125 126 127 |
# File 'lib/i3-ipc.rb', line 125 def parse_response(response) self.class.parse_response(response) end |
#read(len) ⇒ Object
136 137 138 |
# File 'lib/i3-ipc.rb', line 136 def read(len) @socket.read(len) end |
#write(msg) ⇒ Object
writes message to the socket if socket is not connected, it connects first
131 132 133 134 |
# File 'lib/i3-ipc.rb', line 131 def write(msg) connect if @socket.nil? || closed? @last_write_length = @socket.write msg end |