i3-ipc 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
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
+