i3-ipc 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Jan-Erik Rediger
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,45 @@
1
+ i3-ipc
2
+ ======
3
+
4
+ inter-process communication with [i3][], the improved tiling window manager.
5
+
6
+ Installation
7
+ ------------
8
+
9
+ RubyGem:
10
+
11
+ gem install i3-ipc
12
+
13
+ Old school:
14
+
15
+ curl -s http://github.com/badboy/i3-ipc/raw/master/i3-ipc > i3-ipc &&
16
+ chmod 755 i3-ipc &&
17
+ mv i3-ipc /usr/local/bin/i3-ipc
18
+
19
+ Use
20
+ ---
21
+
22
+ i3-ipc -t 1
23
+ i3-ipc -t 1 -p
24
+ i3-ipc -t 1 -j
25
+ i3-ipc "exec xterm"
26
+
27
+ Contributing
28
+ ------------
29
+
30
+ Once you've made your great commits:
31
+
32
+ 1. [Fork][0] the project.
33
+ 2. Create a topic branch - `git checkout -b my_branch`
34
+ 3. Push to your branch - `git push origin my_branch`
35
+ 4. Create an [Issue][1] with a link to your branch
36
+ 5. That's it!
37
+
38
+ Copyright
39
+ ---------
40
+
41
+ Copyright (c) 2010 Jan-Erik Rediger. See LICENSE for details.
42
+
43
+ [i3]: http://i3.zekjur.net/
44
+ [0]: http://help.github.com/forking/
45
+ [1]: http://github.com/badboy/i3-ipc/issues
@@ -0,0 +1,50 @@
1
+ begin
2
+ require 'mg'
3
+ MG.new("i3-ipc.gemspec")
4
+ rescue LoadError
5
+ nil
6
+ end
7
+
8
+ desc "Build standalone script"
9
+ task :build => [ :standalone, :build_man ]
10
+
11
+ desc "Build standalone script"
12
+ task :standalone => :load_i3_ipc do
13
+ require 'i3-ipc/standalone'
14
+ I3::Standalone.save('i3-ipc')
15
+ end
16
+
17
+ desc "Build i3-ipc manual"
18
+ task :build_man do
19
+ sh "ronn -br5 --organization=badboy --manual='i3-ipc Manual' man/*.ronn"
20
+ end
21
+
22
+ desc "Show i3-ipc manual"
23
+ task :man => :build_man do
24
+ exec "man man/i3-ipc.1"
25
+ end
26
+
27
+ task :load_i3_ipc do
28
+ $LOAD_PATH.unshift 'lib'
29
+ require 'i3-ipc'
30
+ end
31
+
32
+ Rake::TaskManager.class_eval do
33
+ def remove_task(task_name)
34
+ @tasks.delete(task_name.to_s)
35
+ end
36
+ end
37
+
38
+ # Remove mg's install task
39
+ Rake.application.remove_task(:install)
40
+
41
+ desc "Install standalone script and man pages"
42
+ task :install => :standalone do
43
+ prefix = ENV['PREFIX'] || ENV['prefix'] || '/usr/local'
44
+
45
+ FileUtils.mkdir_p "#{prefix}/bin"
46
+ FileUtils.cp "i3-ipc", "#{prefix}/bin"
47
+
48
+ FileUtils.mkdir_p "#{prefix}/share/man/man1"
49
+ FileUtils.cp "man/i3-ipc.1", "#{prefix}/share/man/man1"
50
+ end
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: utf-8
3
+
4
+ require 'i3-ipc'
5
+ I3::Runner.execute(*ARGV)
@@ -0,0 +1,93 @@
1
+ require 'socket'
2
+ require 'json'
3
+ require 'i3-ipc/runner'
4
+ require 'i3-ipc/manpage'
5
+ require 'i3-ipc/version'
6
+
7
+ module I3
8
+ class IPC
9
+ MAGIC_STRING = "i3-ipc"
10
+
11
+ class WrongAnswer < RuntimeError; end # :nodoc:
12
+ class WrongType < RuntimeError; end # :nodoc:
13
+
14
+ # connects to the given i3 ipc interface
15
+ # @param socket_path String the path to i3's socket
16
+ # @param force_connect Boolean connects to the socket if true
17
+ def initialize(socket_path="/tmp/i3-ipc.sock", force_connect=false)
18
+ @socket_path = socket_path
19
+ connect if connect
20
+ end
21
+
22
+ # send a message to i3
23
+ #
24
+ # the message is a command for i3
25
+ # (like the commands you can bind to keys in the configuration file)
26
+ # and will be executed directly after receiving it.
27
+ #
28
+ # returns { "success" => true }
29
+ def message(payload)
30
+ write format(0, payload)
31
+ handle_response 0
32
+ end
33
+
34
+ # gets the current workspaces.
35
+ # the reply will be the JSON-encoded list of workspaces
36
+ # (see the reply section of i3 docu)
37
+ def get_workspace
38
+ write format(1)
39
+ handle_response 1
40
+ end
41
+
42
+ # reads the reply from the socket
43
+ # and parse the returned json into a ruby object
44
+ #
45
+ # throws WrongAnswer when magic word is wrong
46
+ # throws WrongType if returned type does not match expected
47
+ def handle_response(type)
48
+ # reads 14 bytes
49
+ # length of "i3-ipc" + 4 bytes length + 4 bytes type
50
+ buffer = @socket.read 14
51
+ raise WrongAnswer unless buffer[0, ("i3-ipc".length)]
52
+
53
+ len, recv_type = buffer[6..-1].unpack("LL")
54
+ raise WrongType unless recv_type == type
55
+
56
+ answer = @socket.read(len)
57
+ ::JSON.parse(answer)
58
+ end
59
+
60
+ # format the message
61
+ # a typical message looks like
62
+ # "i3-ipc" <message length> <message type> <payload>
63
+ def format(type, payload=nil)
64
+ size = payload ? payload.to_s.bytes.count : 0
65
+ msg = "i3-ipc%s" % [size, type].pack("LL")
66
+ msg << payload.to_s if payload
67
+ msg
68
+ end
69
+
70
+ # writes message to the socket
71
+ # if socket is not connected, it calls conenct
72
+ def write(msg)
73
+ connect if @socket.nil? || closed?
74
+ @last_write_length = @socket.write msg
75
+ end
76
+
77
+ # connects to the given socket
78
+ def connect
79
+ @socket = UNIXSocket.new(@socket_path)
80
+ end
81
+
82
+ # closes the socket connection
83
+ def close
84
+ @socket.close
85
+ end
86
+
87
+ # alias for @socket.closed? for easy access
88
+ def closed?
89
+ @socket.closed?
90
+ end
91
+ end
92
+ end
93
+
@@ -0,0 +1,90 @@
1
+ module I3
2
+ module Manpage
3
+ extend self
4
+
5
+ # Prints a manpage, all pretty and paged.
6
+ def display(name)
7
+ puts manpage(name)
8
+ end
9
+
10
+ # Returns the terminal-formatted manpage, ready to be printed to
11
+ # the screen.
12
+ def manpage(name)
13
+ return "** Can't find groff(1)" unless groff?
14
+
15
+ require 'open3'
16
+ out = nil
17
+ Open3.popen3(groff_command) do |stdin, stdout, _|
18
+ stdin.puts raw_manpage(name)
19
+ stdin.close
20
+ out = stdout.read.strip
21
+ end
22
+ out
23
+ end
24
+
25
+ # Returns the raw manpage. If we're not running in standalone
26
+ # mode, it's a file sitting at the root under the `man`
27
+ # directory.
28
+ #
29
+ # If we are running in standalone mode the manpage will be
30
+ # included after the __END__ of the file so we can grab it using
31
+ # DATA.
32
+ def raw_manpage(name)
33
+ if File.exists? file = File.dirname(__FILE__) + "/../../man/#{name}.1"
34
+ File.read(file)
35
+ else
36
+ DATA.read
37
+ end
38
+ end
39
+
40
+ # Returns true if groff is installed and in our path, false if
41
+ # not.
42
+ def groff?
43
+ system("which groff > /dev/null")
44
+ end
45
+
46
+ # The groff command complete with crazy arguments we need to run
47
+ # in order to turn our raw roff (manpage markup) into something
48
+ # readable on the terminal.
49
+ def groff_command
50
+ "groff -Wall -mtty-char -mandoc -Tascii"
51
+ end
52
+
53
+ # All calls to `puts` are paged, git-style.
54
+ def puts(*args)
55
+ page_stdout
56
+ super
57
+ end
58
+
59
+ # http://nex-3.com/posts/73-git-style-automatic-paging-in-ruby
60
+ def page_stdout
61
+ return unless $stdout.tty?
62
+
63
+ read, write = IO.pipe
64
+
65
+ if Kernel.fork
66
+ # Parent process, become pager
67
+ $stdin.reopen(read)
68
+ read.close
69
+ write.close
70
+
71
+ # Don't page if the input is short enough
72
+ ENV['LESS'] = 'FSRX'
73
+
74
+ # Wait until we have input before we start the pager
75
+ Kernel.select [STDIN]
76
+
77
+ pager = ENV['PAGER'] || 'less -isr'
78
+ pager = 'cat' if pager.empty?
79
+
80
+ exec pager rescue exec "/bin/sh", "-c", pager
81
+ else
82
+ # Child process
83
+ $stdout.reopen(write)
84
+ $stderr.reopen(write) if $stderr.tty?
85
+ read.close
86
+ write.close
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,76 @@
1
+ require 'optparse'
2
+
3
+ module I3
4
+ module Runner
5
+ extend self
6
+
7
+ def execute(*args)
8
+ socket_file = '/tmp/i3-ipc.sock'
9
+ type = 0
10
+ quiet = false
11
+ output = :default
12
+
13
+ opts = OptionParser.new do |opts|
14
+ opts.banner = "Usage: i3-ipc [options] [message]"
15
+
16
+ s_desc = 'Set socket file, defaults to /tmp/i3-ipc.sock'
17
+ opts.on('-s', '--socket', s_desc) do |s|
18
+ socket_file = s
19
+ end
20
+
21
+ t_desc = 'Set type, 0 = command, 1 = workspace list, defaults to 0'
22
+ opts.on('-tTYPE', '--type TYPE', Integer, t_desc) do |t|
23
+ type = t
24
+ end
25
+
26
+ opts.on('-p', '--pretty-print', 'Pretty print reply') do |p|
27
+ output = :pretty_print
28
+ end
29
+
30
+ opts.on('-j', '--json', 'Output raw json') do |p|
31
+ output = :json
32
+ end
33
+
34
+ opts.on('-q', '--quiet', %(Don't show reply)) do |q|
35
+ quiet = q
36
+ end
37
+
38
+ opts.on('-m', '--man', 'Print manual') do
39
+ I3::Manpage.display("i3-ipc")
40
+ end
41
+
42
+ opts.on('-h', '--help', 'Display this screen') do
43
+ puts opts
44
+ exit
45
+ end
46
+ end
47
+
48
+ opts.parse!(args)
49
+
50
+ s = I3::IPC.new(socket_file)
51
+
52
+ if type == 0
53
+ if args.empty?
54
+ abort "error: message type needs a message"
55
+ end
56
+
57
+ payload = args.shift
58
+
59
+ puts s.message(payload) unless quiet
60
+ elsif type == 1
61
+ workspaces = s.get_workspace
62
+ if output == :pretty_print
63
+ require 'pp'
64
+ pp workspaces
65
+ elsif output == :json
66
+ require 'json'
67
+ puts workspaces.to_json
68
+ else
69
+ p workspaces
70
+ end
71
+ else
72
+ abort "error: type #{type} not yet implemented"
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,53 @@
1
+ module I3
2
+ module Standalone
3
+ extend self
4
+
5
+ PREAMBLE = <<-preamble
6
+ #!/usr/bin/env ruby
7
+ #
8
+ # This file, gist, is generated code.
9
+ # Please DO NOT EDIT or send patches for it.
10
+ #
11
+ # Please take a look at the source from
12
+ # http://github.com/badboy/i3-ipc
13
+ # and submit patches against the individual files
14
+ # that build gist.
15
+ #
16
+
17
+ preamble
18
+
19
+ POSTAMBLE = "I3::Runner.execute(*ARGV)\n"
20
+ __DIR__ = File.dirname(__FILE__)
21
+ MANPAGE = "__END__\n#{File.read(__DIR__ + '/../../man/i3-ipc.1')}"
22
+
23
+ def save(filename, path = '.')
24
+ target = File.join(File.expand_path(path), filename)
25
+ File.open(target, 'w') do |f|
26
+ f.puts build
27
+ f.chmod 0755
28
+ end
29
+ end
30
+
31
+ def build
32
+ root = File.dirname(__FILE__)
33
+
34
+ standalone = ''
35
+ standalone << PREAMBLE
36
+
37
+ Dir["#{root}/../**/*.rb"].each do |file|
38
+ # skip standalone.rb
39
+ next if File.expand_path(file) == File.expand_path(__FILE__)
40
+
41
+ File.readlines(file).each do |line|
42
+ next if line =~ /^\s*#/
43
+ next if line =~ /^require 'i3-ipc/
44
+ standalone << line
45
+ end
46
+ end
47
+
48
+ standalone << POSTAMBLE
49
+ standalone << MANPAGE
50
+ standalone
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,3 @@
1
+ module I3
2
+ Version = '0.0.2'
3
+ end
metadata ADDED
@@ -0,0 +1,70 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: i3-ipc
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 2
9
+ version: 0.0.2
10
+ platform: ruby
11
+ authors:
12
+ - Jan-Erik Rediger
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-03-12 00:00:00 +01:00
18
+ default_executable:
19
+ dependencies: []
20
+
21
+ description: " uses the ipc socket of i3 to send commands or get information directly from the window manager. Useful for scripting the window manager.'\n"
22
+ email: badboy@archlinux.us
23
+ executables:
24
+ - i3-ipc
25
+ extensions: []
26
+
27
+ extra_rdoc_files: []
28
+
29
+ files:
30
+ - README.markdown
31
+ - Rakefile
32
+ - LICENSE
33
+ - lib/i3-ipc/manpage.rb
34
+ - lib/i3-ipc/standalone.rb
35
+ - lib/i3-ipc/version.rb
36
+ - lib/i3-ipc/runner.rb
37
+ - lib/i3-ipc.rb
38
+ - bin/i3-ipc
39
+ has_rdoc: true
40
+ homepage: http://github.com/badboy/i3-ipc
41
+ licenses: []
42
+
43
+ post_install_message:
44
+ rdoc_options: []
45
+
46
+ require_paths:
47
+ - lib
48
+ required_ruby_version: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ segments:
53
+ - 0
54
+ version: "0"
55
+ required_rubygems_version: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ segments:
60
+ - 0
61
+ version: "0"
62
+ requirements: []
63
+
64
+ rubyforge_project:
65
+ rubygems_version: 1.3.6
66
+ signing_key:
67
+ specification_version: 3
68
+ summary: inter-process communication with i3, the improved tiling window manager.
69
+ test_files: []
70
+