epitools 0.5.4 → 0.5.5

Sign up to get free protection for your applications and to get access to all the features.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.5.4
1
+ 0.5.5
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "epitools"
8
- s.version = "0.5.4"
8
+ s.version = "0.5.5"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["epitron"]
12
- s.date = "2012-04-28"
12
+ s.date = "2012-05-01"
13
13
  s.description = "Miscellaneous utility libraries to make my life easier."
14
14
  s.email = "chris@ill-logic.com"
15
15
  s.extra_rdoc_files = [
@@ -60,6 +60,8 @@ Gem::Specification.new do |s|
60
60
  "lib/epitools/sys.rb",
61
61
  "lib/epitools/term.rb",
62
62
  "lib/epitools/trie.rb",
63
+ "lib/epitools/typed_struct.rb",
64
+ "lib/epitools/wm.rb",
63
65
  "lib/epitools/zopen.rb",
64
66
  "spec/autoreq_spec.rb",
65
67
  "spec/browser_spec.rb",
@@ -78,6 +80,7 @@ Gem::Specification.new do |s|
78
80
  "spec/spec_helper.rb",
79
81
  "spec/sys_spec.rb",
80
82
  "spec/term_spec.rb",
83
+ "spec/typed_struct_spec.rb",
81
84
  "spec/zopen_spec.rb"
82
85
  ]
83
86
  s.homepage = "http://github.com/epitron/epitools"
@@ -43,12 +43,14 @@ autoload :Ezdb, 'epitools/ezdb'
43
43
  autoload :Browser, 'epitools/browser'
44
44
  autoload :Rash, 'epitools/rash'
45
45
  autoload :Ratio, 'epitools/ratio'
46
- autoload :Sys, 'epitools/sys'
47
46
  autoload :ProgressBar, 'epitools/progressbar'
48
47
  autoload :Trie, 'epitools/trie'
49
48
  autoload :MimeMagic, 'epitools/mimemagic'
50
49
  autoload :Term, 'epitools/term'
51
50
  autoload :Iter, 'epitools/iter'
51
+ autoload :WM, 'epitools/wm'
52
+ autoload :TypedStruct, 'epitools/typed_struct'
53
+ autoload :Sys, 'epitools/sys'
52
54
 
53
55
  ## Gems (common)
54
56
  autoreq :Nokogiri, 'nokogiri'
@@ -193,6 +193,8 @@ module Enumerable
193
193
  def deep_select(depth=nil, &block)
194
194
  map do |*args|
195
195
 
196
+ obj = args.last
197
+
196
198
  if depth.nil? or depth > 0
197
199
 
198
200
  case obj
@@ -257,6 +257,15 @@ class String
257
257
  end
258
258
  end
259
259
 
260
+ #
261
+ # Converts time duration strings (mm:ss, hh:mm:ss, or dd:hh:mm:ss) to seconds.
262
+ # (The reverse of Integer#to_hms)
263
+ #
264
+ def from_hms
265
+ nums = split(':').map(&:to_i)
266
+ nums_and_units = nums.reverse.zip %w[seconds minutes hours days]
267
+ nums_and_units.map { |num, units| num.send(units) }.sum
268
+ end
260
269
 
261
270
  unless public_method_defined? :to_proc
262
271
 
@@ -0,0 +1,67 @@
1
+ #
2
+ #
3
+ #
4
+ class TypedStruct < Struct
5
+
6
+ ## TODO: Compact syntax: "a,b,c:int x:string y:date"
7
+ ## TODO: Optional commas separating fields: "a, b, c:int, d:bool"
8
+ ## TODO: booleans fields add "field?" methods
9
+
10
+ #
11
+ # A perhaps-too-clever table of { "typename" => convert_proc } mappings.
12
+ #
13
+ CONVERTERS = Hash[ *{
14
+
15
+ ["str", "string"] => :passthru,
16
+ ["int", "integer"] => proc { |me| me.to_i },
17
+ ["hex"] => proc { |me| me.to_i(16) },
18
+ ["bool", "boolean"] => proc { |me|
19
+ case me
20
+ when false, 0, "0", "off", "no", "false", nil
21
+ false
22
+ when true, 1, "1", "on", "yes", "true"
23
+ true
24
+ else
25
+ raise "Invalid boolean type: #{me.inspect}"
26
+ end
27
+ },
28
+ ["date", "time", "datetime"] => proc { |me| DateTime.parse me },
29
+ ["timestamp"] => proc { |me| Time.at me },
30
+
31
+ }.map { |names, converter| names.map { |n| [n, converter] } }.flatten ]
32
+
33
+ #
34
+ # Initialize a new struct.
35
+ #
36
+ def self.[](specs)
37
+ # create [name,type] pairs
38
+ pairs = specs.split.map do |spec|
39
+ name, type = spec.split(":")
40
+
41
+ type ||= "string"
42
+ unless converter = CONVERTERS[type]
43
+ raise "Unknown type: #{type}"
44
+ end
45
+
46
+ [name.to_sym, converter]
47
+ end
48
+
49
+ # initialize the C Struct
50
+ struct = new(*pairs.transpose.first)
51
+
52
+ # overload setter methods to call the proc
53
+ pairs.each do |field, converter|
54
+ next if converter == :passthru
55
+ struct.send(:define_method, "#{field}=") do |val|
56
+ self[field] = ( val and converter.call val )
57
+ end
58
+ end
59
+
60
+ struct
61
+ end
62
+
63
+ def initialize(*args)
64
+ members.zip(args).each { |field,value| send "#{field}=", value }
65
+ end
66
+
67
+ end
@@ -0,0 +1,83 @@
1
+ module WM
2
+
3
+ raise "Error: wmctrl not found." unless Path.which("wmctrl")
4
+
5
+ def self.windows; @windows ||= Window.all; end
6
+ def self.desktops; @desktops ||= Desktop.all; end
7
+ def self.processes; @processes ||= Hash[ Sys.ps.map { |process| [process.pid, process] } ] ; end
8
+ def self.current_desktop; @current = desktops.find { |d| d.current? }; end
9
+
10
+ class Desktop < TypedStruct["num:int current:bool resolution viewport desktop_geometry name"]
11
+ def self.all
12
+ # 0 - DG: 1680x1050 VP: N/A WA: 0,25 1680x974 Workspace 1
13
+ # 1 - DG: 1680x1050 VP: N/A WA: 0,25 1680x974 Workspace 2
14
+ # 2 * DG: 1680x1050 VP: 0,0 WA: 0,25 1680x974 Workspace 3
15
+ # 3 - DG: 1680x1050 VP: N/A WA: 0,25 1680x974 Workspace 4
16
+ # 4 - DG: 1680x1050 VP: N/A WA: 0,25 1680x974 Workspace 5
17
+ # 5 - DG: 1680x1050 VP: N/A WA: 0,25 1680x974 Workspace 6
18
+ # 0 1 2 3 4 5 6 7 8 9
19
+ `wmctrl -d`.lines.map(&:strip).map { |line| Desktop.from_line(line) }
20
+ end
21
+
22
+ def self.from_line(line)
23
+ fields = line.split
24
+ fields[1] = (fields[1] == "*")
25
+ fields[5] = nil if fields[5] == "N/A"
26
+
27
+ name = fields[9..-1].join(" ")
28
+
29
+ new *(fields.values_at(0,1,3,5,8) + [name])
30
+ end
31
+
32
+ def current?
33
+ current
34
+ end
35
+
36
+ def windows
37
+ #binding.pry
38
+ @windows ||= WM.windows.select { |w| w.desktop_id == num }
39
+ end
40
+ end
41
+
42
+
43
+ class Window < TypedStruct["addr desktop_id:int pid:int x:int y:int w:int h:int hostname title"]
44
+
45
+ def self.all
46
+ `wmctrl -lpG`.lines.map(&:strip).map { |line| Window.from_line(line) }
47
+ end
48
+
49
+ def self.from_line(line)
50
+ # 0x01600031 -1 2562 0 0 1680 25 fizz Top Expanded Edge Panel
51
+ # 0x01600003 -1 2562 0 1998 1680 51 fizz Bottom Expanded Edge Panel
52
+ # 0x02c0001f 0 3012 849 173 783 667 fizz Terminal
53
+ # 0x048001f8 5 4080 311 186 1316 835 fizz Gorillaz - Highway (Under Construction)
54
+ # 0x02c28577 4 3012 66 461 1143 548 fizz Terminal
55
+ # 0x07c00003 0 14117 12 73 1298 948 fizz tr1984001_comp_soft.pdf
56
+ # 0x02d767d8 2 3012 520 470 1143 548 fizz Terminal
57
+
58
+ fields = line.split
59
+ title = fields[8..-1].join ' '
60
+
61
+ new *(fields[0..7] + [title])
62
+ end
63
+
64
+ def desktop
65
+ WM.desktops[desktop_id]
66
+ end
67
+
68
+ def sticky?
69
+ desktop == -1
70
+ end
71
+
72
+ alias_method :name, :title
73
+
74
+ def process
75
+ WM.processes[pid]
76
+ end
77
+
78
+ def inspect
79
+ "{ ::#{name}:: [#{desktop_id}]}"
80
+ end
81
+ end
82
+
83
+ end
@@ -613,3 +613,9 @@ describe "to_jsons and to_yamls" do
613
613
  data.to_yaml.from_yaml.should == data
614
614
  end
615
615
 
616
+ describe "to_hms and from_hms" do
617
+ 60.to_hms.should == "01:00"
618
+ 60.to_hms.from_hms.should == 60
619
+ "1:20:33".from_hms.to_hms.should == "01:20:33"
620
+ "5:01:20:33".from_hms.to_hms.should == "05:01:20:33"
621
+ end
@@ -0,0 +1,16 @@
1
+ require 'epitools'
2
+
3
+ describe TypedStruct do
4
+
5
+ it "works" do
6
+ t = TypedStruct["a:int b c:boolean d:timestamp"].new
7
+
8
+ t.a.should == nil
9
+ t.a = "111"; t.a.should == 111
10
+ t.b = "111"; t.b.should == "111"
11
+ t.c = "yes"; t.c.should == true
12
+ #t.c?.should == true
13
+ end
14
+
15
+ end
16
+
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: epitools
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.4
4
+ version: 0.5.5
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-04-28 00:00:00.000000000 Z
12
+ date: 2012-05-01 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
@@ -110,6 +110,8 @@ files:
110
110
  - lib/epitools/sys.rb
111
111
  - lib/epitools/term.rb
112
112
  - lib/epitools/trie.rb
113
+ - lib/epitools/typed_struct.rb
114
+ - lib/epitools/wm.rb
113
115
  - lib/epitools/zopen.rb
114
116
  - spec/autoreq_spec.rb
115
117
  - spec/browser_spec.rb
@@ -128,6 +130,7 @@ files:
128
130
  - spec/spec_helper.rb
129
131
  - spec/sys_spec.rb
130
132
  - spec/term_spec.rb
133
+ - spec/typed_struct_spec.rb
131
134
  - spec/zopen_spec.rb
132
135
  homepage: http://github.com/epitron/epitools
133
136
  licenses: