obfusk-util 0.0.1.SNAPSHOT.20130724234552

Sign up to get free protection for your applications and to get access to all the features.
data/README.md ADDED
@@ -0,0 +1,232 @@
1
+ []: {{{1
2
+
3
+ File : README.md
4
+ Maintainer : Felix C. Stegerman <flx@obfusk.net>
5
+ Date : 2013-07-24
6
+
7
+ Copyright : Copyright (C) 2013 Felix C. Stegerman
8
+ Version : v0.0.1.SNAPSHOT
9
+
10
+ []: }}}1
11
+
12
+ ## Description
13
+ []: {{{1
14
+
15
+ [rb-]obfusk-util - miscellaneous utility library for ruby
16
+
17
+ ...
18
+
19
+ []: }}}1
20
+
21
+ ## Examples
22
+ []: {{{1
23
+
24
+ []: {{{2
25
+
26
+ ```ruby
27
+ Obfusk::Util::Cmd.killsig 'SIGINT foo bar'
28
+ # => { command: 'foo bar', signal: 'SIGINT' }
29
+
30
+ Obfusk::Util::Cmd.killsig 'foo bar'
31
+ # => { command: 'foo bar', signal: 'SIGTERM' }
32
+
33
+ Obfusk::Util::Cmd.shell 'SHELL echo "$FOO: $BAR"'
34
+ # => { command: 'echo "$FOO: $BAR"', shell: 'bash' }
35
+
36
+ Obfusk::Util::Cmd.set_vars 'echo ${FOO} ... ${BAR} ...',
37
+ { 'FOO' => 'foo', 'BAR' => 'bar' }
38
+ # => 'echo foo ... bar ...'
39
+ ```
40
+
41
+ []: }}}2
42
+
43
+ []: {{{2
44
+
45
+ ```ruby
46
+ x = { x: { y: 0 }, z: [1,2,3] }
47
+ Obfusk::Util.assoc(x, [:x,:y] => 1, [:z,1] => 99)
48
+ x[:x][:y] == 1 # => true
49
+ x[:z] == [1,99,3] # => true
50
+
51
+ y = Obfusk::Util.deepdup x
52
+ Obfusk::Util.empty_as_nil(ENV['FOO']) || default
53
+ ```
54
+
55
+ []: }}}2
56
+
57
+ []: {{{2
58
+
59
+ ```ruby
60
+ Obfusk::Util::FS.append 'file', *lines
61
+ Obfusk::Util::FS.exists? 'file-or-possibly-broken-symlink'
62
+ ```
63
+
64
+ []: }}}2
65
+
66
+ []: {{{2
67
+
68
+ ```ruby
69
+ Obfusk::Util.ohai *%w{ rackup -p 8888 }
70
+ # shows '==> rackup -p 8888' in colour
71
+
72
+ Obfusk::Util.onow 'Starting', 'foo', 'bar'
73
+ # shows '==> Starting: foo, bar' in colour
74
+
75
+ Obfusk::Util.onoe 'Something is wrong!' # error in colour
76
+ Obfusk::Util.opoo 'This looks funny!' # warning in colour
77
+ ```
78
+
79
+ There are some o\* methods all over obfusk-util that combine some
80
+ operation with e.g. ohai.
81
+
82
+ []: }}}2
83
+
84
+ []: {{{2
85
+
86
+ ```ruby
87
+ Obfusk::Util.require_all 'foo/bar'
88
+ # requires foo/bar/*
89
+
90
+ Obfusk::Util.submodules Foo
91
+ # => { 'bar' => Foo::Bar, 'baz' => Foo:Baz, ... }
92
+ ```
93
+
94
+ []: }}}2
95
+
96
+ []: {{{2
97
+
98
+ Slightly improved OptionParser (w/o officious options):
99
+
100
+ ```ruby
101
+ p = Obfusk::Util::Opt::Parser.new # ...
102
+ remaining_args = p.parse_r ARGV
103
+ ```
104
+
105
+ []: }}}2
106
+
107
+ []: {{{2
108
+
109
+ ```ruby
110
+ Obfusk::Util::OS.home # => current user's home
111
+ Obfusk::Util::OS.home 'user' # => user's home
112
+ Obfusk::Util::OS.user # => current user
113
+ Obfusk::Util::OS.now # => current time as '%F %T'
114
+ ```
115
+
116
+ []: }}}2
117
+
118
+ []: {{{2
119
+
120
+ ```ruby
121
+ Obfusk::Util::Process.age pid # => e.g. '01:06:19'
122
+ Obfusk::Util::Process.alive? pid # => false/true/:not_mine
123
+ ```
124
+
125
+ []: }}}2
126
+
127
+ []: {{{2
128
+
129
+ spawn_w is spawn + wait (which is nicer than system). No shell is
130
+ ever used; env is an option instead of an optional first argument;
131
+ ENOENT becomes RunError. See also: exec, spawn, system, popen3.
132
+
133
+ ```ruby
134
+ Obfusk::Util.spawn_w *%w{ some command }, env: { 'FOO' => 'bar' },
135
+ chdir: 'some/dir' #, ...
136
+ # => $?
137
+
138
+ # raise RunError if command returned non-zero
139
+ Obfusk::Util.chk_exit(%w{ some command }) do |a|
140
+ # spawn + wait + ohai
141
+ Obfusk::Util.ospawn_w *a
142
+ end
143
+ ```
144
+
145
+ []: }}}2
146
+
147
+ []: {{{2
148
+
149
+ ```ruby
150
+ Foo = Obfusk::Util.struct(*%w{ field1 field2 field3 }) do
151
+ def some_method; field1 + field2; end
152
+ end
153
+
154
+ foo = Foo.new field1: 37, field2: 5
155
+ foo.some_method # => 42
156
+
157
+ # build a Foo which is frozen when the block ends
158
+ bar = Foo.build(field1: 99) do |x|
159
+ c.field2 = 1
160
+ # ...
161
+ end
162
+
163
+ bar.field3 = 99 # => RuntimeError b/c frozen
164
+ bar.check! # => IncompleteError b/c there are empty fields
165
+ ```
166
+
167
+ []: }}}2
168
+
169
+ []: {{{2
170
+
171
+ ```ruby
172
+ Obfusk::Util::Term.colour :red
173
+ # => ansi escape code if $stdout is a tty, '' otherwise
174
+
175
+ Obfusk::Util::Term.columns # terminal columns
176
+ Obfusk::Util::Term.lines # terminal lines
177
+ Obfusk::Util::Term.tty? # is $stdout a tty?
178
+ Obfusk::Util::Term.tty? :err # is $stderr a tty?
179
+
180
+ Obfusk::Util::Term.prompt 'foo> ' # prompt for input
181
+ Obfusk::Util::Term.prompt 'foo> ', :hide # prompt for password
182
+ ```
183
+
184
+ []: }}}2
185
+
186
+ []: {{{2
187
+
188
+ ```ruby
189
+ def foo(*args_)
190
+ Obfusk::Util::Valid.args 'description', args_, 1, 3
191
+ # => ArgumentError if #args not in 1..3
192
+ end
193
+ ```
194
+
195
+ []: }}}2
196
+
197
+ []: }}}1
198
+
199
+ ## Specs & Docs
200
+ []: {{{1
201
+
202
+ $ rake spec
203
+ $ rake docs
204
+
205
+ []: }}}1
206
+
207
+ ## TODO
208
+ []: {{{1
209
+
210
+ * write more specs
211
+ * write more docs
212
+ * dual-license under EPLv1?
213
+ * ...
214
+
215
+ []: }}}1
216
+
217
+ ## License
218
+ []: {{{1
219
+
220
+ GPLv2 [1].
221
+
222
+ []: }}}1
223
+
224
+ ## References
225
+ []: {{{1
226
+
227
+ [1] GNU General Public License, version 2
228
+ --- http://www.opensource.org/licenses/GPL-2.0
229
+
230
+ []: }}}1
231
+
232
+ []: ! ( vim: set tw=70 sw=2 sts=2 et fdm=marker : )
@@ -0,0 +1,29 @@
1
+ # -- ; {{{1
2
+ #
3
+ # File : obfusk/util/all.rb
4
+ # Maintainer : Felix C. Stegerman <flx@obfusk.net>
5
+ # Date : 2013-07-24
6
+ #
7
+ # Copyright : Copyright (C) 2013 Felix C. Stegerman
8
+ # Licence : GPLv2
9
+ #
10
+ # -- ; }}}1
11
+
12
+ require 'obfusk/util/cmd'
13
+ require 'obfusk/util/data'
14
+ require 'obfusk/util/die'
15
+ require 'obfusk/util/fs'
16
+ require 'obfusk/util/message'
17
+ require 'obfusk/util/misc'
18
+ require 'obfusk/util/module'
19
+ require 'obfusk/util/opt'
20
+ require 'obfusk/util/os'
21
+ require 'obfusk/util/process'
22
+ require 'obfusk/util/run'
23
+ require 'obfusk/util/spec'
24
+ require 'obfusk/util/struct'
25
+ require 'obfusk/util/term'
26
+ require 'obfusk/util/valid'
27
+ require 'obfusk/util/version'
28
+
29
+ # vim: set tw=70 sw=2 sts=2 et fdm=marker :
@@ -0,0 +1,69 @@
1
+ # -- ; {{{1
2
+ #
3
+ # File : obfusk/util/cmd.rb
4
+ # Maintainer : Felix C. Stegerman <flx@obfusk.net>
5
+ # Date : 2013-07-24
6
+ #
7
+ # Copyright : Copyright (C) 2013 Felix C. Stegerman
8
+ # Licence : GPLv2
9
+ #
10
+ # -- ; }}}1
11
+
12
+ # my namespace
13
+ module Obfusk; module Util; module Cmd
14
+
15
+ SIG_RX = /^(SIG[A-Z0-9]+)\s+(.*)$/
16
+ SH_RX = /^SHELL(=(\S+))?\s+(.*)$/
17
+ VAR_RX = / \$ \{ ([A-Z_]+) \} /x
18
+
19
+ # --
20
+
21
+ # parses optional `SIG*` prefix in command string;
22
+ # (e.g. `'SIGINT foo bar ...'`);
23
+ # if there is no prefix, signal is default
24
+ # @return [Hash] `{ command: command, signal: signal }`
25
+ def self.killsig(cmd, default = 'SIGTERM') # {{{1
26
+ if m = cmd.match(SIG_RX)
27
+ { command: m[2], signal: m[1] }
28
+ else
29
+ { command: cmd, signal: default }
30
+ end
31
+ end # }}}1
32
+
33
+ # parses optional `SHELL[=...]` prefix in command string
34
+ # (e.g. `'SHELL=bash foo bar ...'`, `'SHELL foo bar ...'`);
35
+ # if there is no prefix, shell is nil;
36
+ # if there is no `=...`, shell is default
37
+ # @return [Hash] `{ command: command, shell: shell }`
38
+ def self.shell(cmd, default = 'bash') # {{{1
39
+ if m = cmd.match(SH_RX)
40
+ { command: m[3], shell: (m[2] || default) }
41
+ else
42
+ { command: cmd, shell: nil }
43
+ end
44
+ end # }}}1
45
+
46
+ # --
47
+
48
+ # prepend nohup to args
49
+ def self.nohup(*args)
50
+ ['nohup'] + args
51
+ end
52
+
53
+ # replaces `${VAR}s` in command string using vars hash;
54
+ # missing values are replaced with empty strings
55
+ def self.set_vars(cmd, vars)
56
+ cmd.gsub(VAR_RX) { |m| vars[$1] }
57
+ end
58
+
59
+ # --
60
+
61
+ # env hash as array (w/o nil values)
62
+ # @return [<String>] `['k1="v1"', ...]`
63
+ def self.env_to_a(h)
64
+ h.reject { |k,v| v.nil? } .map { |k,v| "#{k}=#{v.inspect}" }
65
+ end
66
+
67
+ end; end; end
68
+
69
+ # vim: set tw=70 sw=2 sts=2 et fdm=marker :
@@ -0,0 +1,53 @@
1
+ # -- ; {{{1
2
+ #
3
+ # File : obfusk/util/data.rb
4
+ # Maintainer : Felix C. Stegerman <flx@obfusk.net>
5
+ # Date : 2013-07-24
6
+ #
7
+ # Copyright : Copyright (C) 2013 Felix C. Stegerman
8
+ # Licence : GPLv2
9
+ #
10
+ # -- ; }}}1
11
+
12
+ # my namespace
13
+ module Obfusk; module Util
14
+
15
+ # assoc key(s) w/ value(s); array keys represent nested keys;
16
+ # will autovivivy missing (if false/nil) nested objects as hashes
17
+ #
18
+ # ```
19
+ # x = { x: { y: 0 } }; assoc(x, [:x,:y] => 1); x[:x][:y] == 1
20
+ # ```
21
+ def self.assoc(x, h = {}) # {{{1
22
+ h.each do |k,v|
23
+ if k.is_a? Array
24
+ case k.length
25
+ when 0; raise ArgumentError, 'empty array key'
26
+ when 1; x[k.first] = v
27
+ else h, *t = k; assoc (x[h] ||= {}), t => v
28
+ end
29
+ else
30
+ x[k] = v
31
+ end
32
+ end
33
+ x
34
+ end # }}}1
35
+
36
+ # deep copy using Marshal
37
+ def self.deepdup(obj)
38
+ Marshal.load Marshal.dump obj
39
+ end
40
+
41
+ # nil if x is `.empty?`, x otherwise
42
+ def self.empty_as_nil(x)
43
+ x && x.empty? ? nil : x
44
+ end
45
+
46
+ # hash to struct
47
+ def self.h_to_struct(h = {})
48
+ Struct.new(*h.keys).new(*h.values)
49
+ end
50
+
51
+ end; end
52
+
53
+ # vim: set tw=70 sw=2 sts=2 et fdm=marker :
@@ -0,0 +1,45 @@
1
+ # -- ; {{{1
2
+ #
3
+ # File : obfusk/util/die.rb
4
+ # Maintainer : Felix C. Stegerman <flx@obfusk.net>
5
+ # Date : 2013-07-24
6
+ #
7
+ # Copyright : Copyright (C) 2013 Felix C. Stegerman
8
+ # Licence : GPLv2
9
+ #
10
+ # -- ; }}}1
11
+
12
+ # my namespace
13
+ module Obfusk; module Util
14
+
15
+ # print msgs to stderr and exit 1;
16
+ # pass `{ status: code }` as last argument to use other statuscode
17
+ def self.die!(*msgs)
18
+ code = _die_msgs msgs; exit code
19
+ end
20
+
21
+ # print msgs to stderr, show usage, exit
22
+ def self.udie!(usage, *msgs)
23
+ code = _die_msgs msgs; $stderr.puts "Usage: #{usage}"; exit code
24
+ end
25
+
26
+ # --
27
+
28
+ # onoe, exit; requires `obfusk/util/message`
29
+ def self.odie!(msg, opts = {})
30
+ o = opts.dup; c = o.delete(:status) || 1
31
+ ::Obfusk::Util.onoe msg, o; exit c
32
+ end
33
+
34
+ # --
35
+
36
+ # helper; modifies msgs -> OK b/c comes from *msgs
37
+ def self._die_msgs(msgs)
38
+ code = (msgs.last.is_a?(Hash) && msgs.pop[:status]) || 1
39
+ msgs.each { |m| $stderr.puts "Error: #{m}" }
40
+ code
41
+ end
42
+
43
+ end; end
44
+
45
+ # vim: set tw=70 sw=2 sts=2 et fdm=marker :
@@ -0,0 +1,35 @@
1
+ # -- ; {{{1
2
+ #
3
+ # File : obfusk/util/fs.rb
4
+ # Maintainer : Felix C. Stegerman <flx@obfusk.net>
5
+ # Date : 2013-07-24
6
+ #
7
+ # Copyright : Copyright (C) 2013 Felix C. Stegerman
8
+ # Licence : GPLv2
9
+ #
10
+ # -- ; }}}1
11
+
12
+ require 'fileutils'
13
+
14
+ # my namespace
15
+ module Obfusk; module Util; module FS
16
+
17
+ # append to file
18
+ def self.append(file, *lines)
19
+ File.open(file, 'a') { |f| f.puts lines }
20
+ end
21
+
22
+ # does file/dir or symlink exists?
23
+ def self.exists?(path)
24
+ File.exists?(path) || File.symlink?(path)
25
+ end
26
+
27
+ # ohai + mkdir_p; requires `obfusk/util/message`
28
+ def self.omkdir_p(*paths)
29
+ ::Obfusk::Util.ohai "mkdir -p #{paths*' '}"
30
+ FileUtils.mkdir_p paths
31
+ end
32
+
33
+ end; end; end
34
+
35
+ # vim: set tw=70 sw=2 sts=2 et fdm=marker :
@@ -0,0 +1,73 @@
1
+ # -- ; {{{1
2
+ #
3
+ # File : obfusk/util/message.rb
4
+ # Maintainer : Felix C. Stegerman <flx@obfusk.net>
5
+ # Date : 2013-07-24
6
+ #
7
+ # Copyright : Copyright (C) 2013 Felix C. Stegerman
8
+ # Licence : GPLv2
9
+ #
10
+ # -- ; }}}1
11
+
12
+ require 'obfusk/util/term'
13
+
14
+ # my namespace
15
+ module Obfusk; module Util
16
+
17
+ # info message w/ colours:
18
+ # ```
19
+ # "==> <msg>"
20
+ # ```
21
+ def self.ohai(msg)
22
+ puts _tcol(:lbl) + '==> ' + _tcol(:whi) + msg + _tcol(:non)
23
+ end
24
+
25
+ # info message w/ colours:
26
+ # ```
27
+ # "==> <msg>: <a>[, <b>, ...]"
28
+ # ```
29
+ def self.onow(msg, *what)
30
+ puts _tcol(:lgn) + '==> ' + _tcol(:whi) + msg + _tcol(:non) +
31
+ (what.empty? ? '' : _owhat(what))
32
+ end
33
+
34
+ # --
35
+
36
+ # error message w/ colours:
37
+ # ```
38
+ # "<label>: <msg>"
39
+ # ```
40
+ #
41
+ # `opts[:label]` defaults to 'Error';
42
+ # set `opts[:log]` to a lambda to pass message on to a logger
43
+ def self.onoe(msg, opts = {})
44
+ l = opts[:label] || 'Error'
45
+ $stderr.puts _tcole(:lrd) + l + _tcole(:non) + ': ' + msg
46
+ opts[:log]["#{l}: #{msg}"] if opts[:log]
47
+ end
48
+
49
+ # warning message (onoe w/ label 'Warning')
50
+ def self.opoo(msg, opts = {})
51
+ onoe msg, opts.merge(label: 'Warning')
52
+ end
53
+
54
+ # --
55
+
56
+ # (helper for onow)
57
+ def self._owhat(what)
58
+ ': ' + what.map { |x| _tcol(:lgn) + x + _tcol(:non) } *', '
59
+ end
60
+
61
+ # Term.colour
62
+ def self._tcol(*a)
63
+ Term.colour *a
64
+ end
65
+
66
+ # Term.colour_e
67
+ def self._tcole(*a)
68
+ Term.colour_e *a
69
+ end
70
+
71
+ end; end
72
+
73
+ # vim: set tw=70 sw=2 sts=2 et fdm=marker :
@@ -0,0 +1,19 @@
1
+ # -- ; {{{1
2
+ #
3
+ # File : obfusk/util/misc.rb
4
+ # Maintainer : Felix C. Stegerman <flx@obfusk.net>
5
+ # Date : 2013-07-17
6
+ #
7
+ # Copyright : Copyright (C) 2013 Felix C. Stegerman
8
+ # Licence : GPLv2
9
+ #
10
+ # -- ; }}}1
11
+
12
+ # my namespace
13
+ module Obfusk; module Util
14
+
15
+ # ...
16
+
17
+ end; end
18
+
19
+ # vim: set tw=70 sw=2 sts=2 et fdm=marker :
@@ -0,0 +1,41 @@
1
+ # -- ; {{{1
2
+ #
3
+ # File : obfusk/util/module.rb
4
+ # Maintainer : Felix C. Stegerman <flx@obfusk.net>
5
+ # Date : 2013-07-24
6
+ #
7
+ # Copyright : Copyright (C) 2013 Felix C. Stegerman
8
+ # Licence : GPLv2
9
+ #
10
+ # -- ; }}}1
11
+
12
+ # my namespace
13
+ module Obfusk; module Util
14
+
15
+ # load `dir/*` (by searching for `dir/*.rb` in `$LOAD_PATH`)
16
+ #
17
+ # ```
18
+ # require_all('napp/types') ~> require 'napp/types/*'
19
+ # ```
20
+ #
21
+ # @return [Hash] `{ module => result-of-require }`
22
+ def self.require_all(dir)
23
+ Hash[ $LOAD_PATH.map { |x| Dir["#{x}/#{dir}/*.rb"] } .flatten \
24
+ .map { |x| "#{dir}/" + File.basename(x, '.rb') } .uniq \
25
+ .map { |x| y = require x; [x,y] } ]
26
+ end
27
+
28
+ # get submodules as hash
29
+ #
30
+ # ```
31
+ # submodules(Foo) -> { 'bar' => Foo::Bar, ... }
32
+ # ```
33
+ def self.submodules(mod)
34
+ Hash[ mod.constants \
35
+ .map { |x| [x.downcase.to_s, mod.const_get(x)] } \
36
+ .select { |k,v| v.class == Module } ]
37
+ end
38
+
39
+ end; end
40
+
41
+ # vim: set tw=70 sw=2 sts=2 et fdm=marker :
@@ -0,0 +1,37 @@
1
+ # -- ; {{{1
2
+ #
3
+ # File : obfusk/util/opt.rb
4
+ # Maintainer : Felix C. Stegerman <flx@obfusk.net>
5
+ # Date : 2013-07-24
6
+ #
7
+ # Copyright : Copyright (C) 2013 Felix C. Stegerman
8
+ # Licence : GPLv2
9
+ #
10
+ # -- ; }}}1
11
+
12
+ require 'optparse'
13
+
14
+ # my namespace
15
+ module Obfusk; module Util; module Opt
16
+
17
+ # better OptionParser
18
+ class Parser < OptionParser
19
+ # do nothing!
20
+ def add_officious; end
21
+
22
+ # parse options, return remaining args
23
+ def parse_r(args)
24
+ as = args.dup; parse! as; as
25
+ end
26
+ end
27
+
28
+ # --
29
+
30
+ # parse options, return remaining args
31
+ def self.parse(op, args)
32
+ as = args.dup; op.parse! as; as
33
+ end
34
+
35
+ end; end; end
36
+
37
+ # vim: set tw=70 sw=2 sts=2 et fdm=marker :
@@ -0,0 +1,36 @@
1
+ # -- ; {{{1
2
+ #
3
+ # File : obfusk/util/os.rb
4
+ # Maintainer : Felix C. Stegerman <flx@obfusk.net>
5
+ # Date : 2013-07-24
6
+ #
7
+ # Copyright : Copyright (C) 2013 Felix C. Stegerman
8
+ # Licence : GPLv2
9
+ #
10
+ # -- ; }}}1
11
+
12
+ require 'etc'
13
+
14
+ # my namespace
15
+ module Obfusk; module Util; module OS
16
+
17
+ # home dir of (current) user
18
+ def self.home(user = nil)
19
+ user ? Etc.getpwnam(user).dir : Dir.home
20
+ end
21
+
22
+ # user name
23
+ def self.user
24
+ Etc.getlogin
25
+ end
26
+
27
+ # --
28
+
29
+ # current time ('%F %T')
30
+ def self.now(fmt = '%F %T')
31
+ Time.now.strftime fmt
32
+ end
33
+
34
+ end; end; end
35
+
36
+ # vim: set tw=70 sw=2 sts=2 et fdm=marker :
@@ -0,0 +1,41 @@
1
+ # -- ; {{{1
2
+ #
3
+ # File : obfusk/util/process.rb
4
+ # Maintainer : Felix C. Stegerman <flx@obfusk.net>
5
+ # Date : 2013-07-24
6
+ #
7
+ # Copyright : Copyright (C) 2013 Felix C. Stegerman
8
+ # Licence : GPLv2
9
+ #
10
+ # -- ; }}}1
11
+
12
+ # my namespace
13
+ module Obfusk; module Util; module Process
14
+
15
+ GET_AGE = ->(pid) { "ps -p #{pid} -o etime=" }
16
+
17
+ # --
18
+
19
+ # get process age information from ps
20
+ def self.age(pid)
21
+ ispid! pid; %x[#{GET_AGE[pid]}].gsub(/\s/, '')
22
+ end
23
+
24
+ # process alive?
25
+ # @return [Boolean] false if not alive
26
+ # @return [Boolean] true if alive and mine
27
+ # @return [Symbol] :not_mine if alive and not mine
28
+ def self.alive?(pid)
29
+ ::Process.kill 0, pid; true
30
+ rescue Errno::EPERM; :not_mine
31
+ rescue Errno::ESRCH; false
32
+ end
33
+
34
+ # @raise ArgumentError if pid is not an integer
35
+ def self.ispid!(pid)
36
+ pid.is_a? Integer or raise ArgumentError, 'invalid PID'
37
+ end
38
+
39
+ end; end; end
40
+
41
+ # vim: set tw=70 sw=2 sts=2 et fdm=marker :
@@ -0,0 +1,124 @@
1
+ # -- ; {{{1
2
+ #
3
+ # File : obfusk/util/run.rb
4
+ # Maintainer : Felix C. Stegerman <flx@obfusk.net>
5
+ # Date : 2013-07-24
6
+ #
7
+ # Copyright : Copyright (C) 2013 Felix C. Stegerman
8
+ # Licence : GPLv2
9
+ #
10
+ # -- ; }}}1
11
+
12
+ require 'open3'
13
+
14
+ # my namespace
15
+ module Obfusk; module Util
16
+
17
+ class RunError < RuntimeError; end
18
+
19
+ # --
20
+
21
+ # better Kernel.exec; should never return (if successful);
22
+ # see spawn, spawn_w, system
23
+ # @raise RunError on ENOENT
24
+ def self.exec(*args)
25
+ _enoent_to_run('exec', args) do |a|
26
+ Kernel.exec *_spawn_args(*a)
27
+ end
28
+ end
29
+
30
+ # better Kernel.spawn; options can be passed as last arg like w/
31
+ # Kernel.spawn, but instead of env as optional first arg, options
32
+ # takes an :env key as well; also, no shell is ever used;
33
+ # returns PID; see exec, spawn_w, system
34
+ # @raise RunError on ENOENT
35
+ def self.spawn(*args)
36
+ _enoent_to_run('spawn', args) do |a|
37
+ Kernel.spawn *_spawn_args(*a)
38
+ end
39
+ end
40
+
41
+ # better system: spawn + wait; returns $?; see exec, spawn, system
42
+ def self.spawn_w(*args)
43
+ pid = spawn(*args); ::Process.wait pid; $?
44
+ end
45
+
46
+ # better Kernel.system; returns true/false; see exec, spawn, spawn_w
47
+ # @raise RunError on failure (Kernel.system -> nil)
48
+ def self.system(*args)
49
+ r = Kernel.system *_spawn_args(*args)
50
+ raise RunError, "failed to run command #{args} (#$?)" if r.nil?
51
+ r
52
+ end
53
+
54
+ # --
55
+
56
+ # better Open3.popen3; see exec, spawn, spawn_w, system
57
+ # @raise RunError on ENOENT
58
+ def self.popen3(*args, &b)
59
+ _enoent_to_run('popen3', args) do |a|
60
+ Open3.popen3 *_spawn_args(*a), &b
61
+ end
62
+ end
63
+
64
+ # --
65
+
66
+ # ohai + spawn; requires `obfusk/util/message`
67
+ def self.ospawn(*args)
68
+ ::Obfusk::Util.ohai _spawn_rm_opts(args)*' '; spawn *args
69
+ end
70
+
71
+ # ohai + spawn_w; requires `obfusk/util/message`
72
+ def self.ospawn_w(*args)
73
+ ::Obfusk::Util.ohai _spawn_rm_opts(args)*' '; spawn_w *args
74
+ end
75
+
76
+ # --
77
+
78
+ # run block w/ args, check `.exitstatus`
79
+ # @raise RunError if Process::Status's exitstatus is non-zero
80
+ def self.chk_exit(args, &b)
81
+ chk_exitstatus args, b[args].exitstatus
82
+ end
83
+
84
+ # @raise RunError if c != 0
85
+ def self.chk_exitstatus(args, c)
86
+ exit_non_zero! args, c if c != 0
87
+ end
88
+
89
+ # @raise RunError command returned non-zero
90
+ def self.exit_non_zero!(args, c)
91
+ raise RunError, "command returned non-zero: #{args} -> #{c}"
92
+ end
93
+
94
+ # --
95
+
96
+ # helper
97
+ def self._enoent_to_run(what, args, &b) # {{{1
98
+ begin
99
+ b[args]
100
+ rescue Errno::ENOENT => e
101
+ raise RunError,
102
+ "failed to #{what} command #{args}: #{e.message}"
103
+ end
104
+ end # }}}1
105
+
106
+ # helper
107
+ def self._spawn_args(cmd, *args) # {{{1
108
+ c = [cmd, cmd]
109
+ if args.last && (l = args.last.dup).is_a?(Hash) \
110
+ && e = l.delete(:env)
111
+ [e, c] + args[0..-2] + [l]
112
+ else
113
+ [c] + args
114
+ end
115
+ end # }}}1
116
+
117
+ # helper
118
+ def self._spawn_rm_opts(args)
119
+ args.last.is_a?(Hash) ? args[0..-2] : args
120
+ end
121
+
122
+ end; end
123
+
124
+ # vim: set tw=70 sw=2 sts=2 et fdm=marker :
@@ -0,0 +1,55 @@
1
+ # -- ; {{{1
2
+ #
3
+ # File : obfusk/util/spec.rb
4
+ # Maintainer : Felix C. Stegerman <flx@obfusk.net>
5
+ # Date : 2013-07-24
6
+ #
7
+ # Copyright : Copyright (C) 2013 Felix C. Stegerman
8
+ # Licence : GPLv2
9
+ #
10
+ # -- ; }}}1
11
+
12
+ require 'stringio'
13
+
14
+ # my namespace
15
+ module Obfusk; module Util
16
+
17
+ # use StringIO to provide $stdin to block
18
+ def self.provide_stdin(str, isatty = false, &b) # {{{1
19
+ old = $stdin
20
+ begin
21
+ StringIO.open(str, 'r') do |s|
22
+ def s.isatty; true; end if isatty; $stdin = s; b[]
23
+ end
24
+ ensure
25
+ $stdin = old
26
+ end
27
+ end # }}}1
28
+
29
+ # use StringIO to capture $stdout from block
30
+ def self.capture_stdout(isatty = false, &b) # {{{1
31
+ old = $stdout
32
+ begin
33
+ StringIO.open('', 'w') do |s|
34
+ def s.isatty; true; end if isatty; $stdout = s; b[]; s.string
35
+ end
36
+ ensure
37
+ $stdout = old
38
+ end
39
+ end # }}}1
40
+
41
+ # use StringIO to capture $stderr from block
42
+ def self.capture_stderr(isatty = false, &b) # {{{1
43
+ old = $stderr
44
+ begin
45
+ StringIO.open('', 'w') do |s|
46
+ def s.isatty; true; end if isatty; $stderr = s; b[]; s.string
47
+ end
48
+ ensure
49
+ $stderr = old
50
+ end
51
+ end # }}}1
52
+
53
+ end; end
54
+
55
+ # vim: set tw=70 sw=2 sts=2 et fdm=marker :
@@ -0,0 +1,83 @@
1
+ # -- ; {{{1
2
+ #
3
+ # File : obfusk/util/struct.rb
4
+ # Maintainer : Felix C. Stegerman <flx@obfusk.net>
5
+ # Date : 2013-07-24
6
+ #
7
+ # Copyright : Copyright (C) 2013 Felix C. Stegerman
8
+ # Licence : GPLv2
9
+ #
10
+ # -- ; }}}1
11
+
12
+ # my namespace
13
+ module Obfusk; module Util
14
+
15
+ # better Struct; create using Obfusk::Util.struct
16
+ module BetterStruct # {{{1
17
+
18
+ class IncompleteError < RuntimeError; end
19
+
20
+ # --
21
+
22
+ # include class methods as well
23
+ def self.included(base)
24
+ base.extend ClassMethods
25
+ end
26
+
27
+ module ClassMethods # {{{2
28
+
29
+ # new, block, freeze, return
30
+ def build(h = {}, &b)
31
+ x = new h; b[x] if b; x.freeze
32
+ end
33
+
34
+ end # }}}2
35
+
36
+ # checks for missing fields, returns self
37
+ # @raise IncompleteError if any fields are nil
38
+ def check!
39
+ members.each do |f|
40
+ self[f].nil? and raise IncompleteError, "empty field: #{f}"
41
+ end; self
42
+ end
43
+
44
+ # def with(h = {}, &b)
45
+ # x = dup
46
+ # h.each {
47
+ # end
48
+
49
+ unless Struct.method_defined? :to_h
50
+ # convert to hash (ruby 2 has this already)
51
+ def to_h
52
+ Hash[each_pair.to_a]
53
+ end
54
+ end
55
+
56
+ # convert to hash w/ string keys
57
+ def to_str_h
58
+ Hash[to_h.map { |k,v| [k.to_s,v] }]
59
+ end
60
+
61
+ end # }}}1
62
+
63
+ # --
64
+
65
+ # better struct; see examples in README.md
66
+ def self.struct(*fields, &b) # {{{1
67
+ Class.new(Struct.new(*fields.map(&:to_sym))) do
68
+
69
+ include BetterStruct
70
+
71
+ # init w/ hash
72
+ def initialize(h = {})
73
+ h.each { |k,v| self[k] = v }
74
+ end
75
+
76
+ self.class_eval &b if b
77
+
78
+ end
79
+ end # }}}1
80
+
81
+ end; end
82
+
83
+ # vim: set tw=70 sw=2 sts=2 et fdm=marker :
@@ -0,0 +1,94 @@
1
+ # -- ; {{{1
2
+ #
3
+ # File : obfusk/util/term.rb
4
+ # Maintainer : Felix C. Stegerman <flx@obfusk.net>
5
+ # Date : 2013-07-24
6
+ #
7
+ # Copyright : Copyright (C) 2013 Felix C. Stegerman
8
+ # Licence : GPLv2
9
+ #
10
+ # -- ; }}}1
11
+
12
+ require 'io/console'
13
+
14
+ # my namespace
15
+ module Obfusk; module Util; module Term
16
+
17
+ # ansi colour codes
18
+ TERM_COLOUR_CODES = { # {{{1
19
+ black: '0;30', dark_gray: '1;30',
20
+ blue: '0;34', light_blue: '1;34',
21
+ green: '0;32', light_green: '1;32',
22
+ cyan: '0;36', light_cyan: '1;36',
23
+ red: '0;31', light_red: '1;31',
24
+ purple: '0;35', light_purple: '1;35',
25
+ brown: '0;33', yellow: '1;33',
26
+ light_gray: '0;37', white: '1;37',
27
+ none: '0'
28
+ } # }}}1
29
+
30
+ # some colour aliases
31
+ TERM_COLOUR_ALIASES = { # {{{1
32
+ bla: :black, dgr: :dark_gray,
33
+ blu: :blue, lbl: :light_blue,
34
+ grn: :green, lgn: :light_green,
35
+ cyn: :cyan, lcy: :light_cyan, lrd: :light_red,
36
+ pur: :purple, lpu: :light_purple,
37
+ bro: :brown, yel: :yellow,
38
+ lgr: :light_gray, whi: :white, non: :none,
39
+ } # }}}1
40
+
41
+ # ansi colour escapes
42
+ TERM_COLOUR_ESCAPES = (->(;a,b) {
43
+ a = Hash[TERM_COLOUR_CODES.map { |k,v| [k,"\e[#{v}m"] }]
44
+ b = Hash[TERM_COLOUR_ALIASES.map { |k,v| [k, a[v] ] }]
45
+ a.merge b
46
+ })[]
47
+
48
+ GET_COLS = 'TERM=${TERM:-dumb} tput cols'
49
+ GET_LINES = 'TERM=${TERM:-dumb} tput lines'
50
+
51
+ # --
52
+
53
+ # colour code (or '' if not tty)
54
+ def self.colour(x, what = :out)
55
+ c = TERM_COLOUR_ESCAPES[x] or raise ArgumentError,
56
+ "No such colour: #{x}"
57
+ tty?(what) ? c : ''
58
+ end
59
+
60
+ # colour code for $stderr
61
+ def self.colour_e(x)
62
+ colour x, :err
63
+ end
64
+
65
+ # --
66
+
67
+ # terminal columns
68
+ def self.columns
69
+ %x[#{GET_COLS}].to_i
70
+ end
71
+
72
+ # terminal lines
73
+ def self.lines
74
+ %x[#{GET_LINES}].to_i
75
+ end
76
+
77
+ # is $stdout (or $stderr) a tty?
78
+ def self.tty?(what = :out)
79
+ (what == :out ? $stdout : $stderr).isatty
80
+ end
81
+
82
+ # --
83
+
84
+ # prompt for line; optionally hide input
85
+ def self.prompt(prompt, hide = false)
86
+ print prompt; $stdout.flush
87
+ line = hide ? $stdin.noecho { |i| i.gets } .tap { puts } :
88
+ $stdin.gets
89
+ line && line.chomp
90
+ end
91
+
92
+ end; end; end
93
+
94
+ # vim: set tw=70 sw=2 sts=2 et fdm=marker :
@@ -0,0 +1,43 @@
1
+ # -- ; {{{1
2
+ #
3
+ # File : obfusk/util/valid.rb
4
+ # Maintainer : Felix C. Stegerman <flx@obfusk.net>
5
+ # Date : 2013-07-24
6
+ #
7
+ # Copyright : Copyright (C) 2013 Felix C. Stegerman
8
+ # Licence : GPLv2
9
+ #
10
+ # -- ; }}}1
11
+
12
+ # my namespace
13
+ module Obfusk; module Util; module Valid
14
+
15
+ class ArgumentError < RuntimeError; end
16
+ class ValidationError < RuntimeError; end
17
+
18
+ # --
19
+
20
+ # validate #args in min..max (min.. if max is nil)
21
+ # @return [Array] args
22
+ # @raise ArgumentError on out of bounds
23
+ def self.args(what, args, min, max = min)
24
+ if (l = args.length) < min || (max && l > max)
25
+ raise ArgumentError,
26
+ "#{what} expected #{min}..#{max} arguments, got #{l}"
27
+ end; args
28
+ end
29
+
30
+ # @raise ValidationError
31
+ def self.invalid!(msg)
32
+ raise ValidationError, msg
33
+ end
34
+
35
+ # validate value against regex
36
+ # @raise ValidationError on no match
37
+ def self.validate!(x, rx, name)
38
+ x.to_s.match /^(#{rx})$/ or invalid! "invalid #{name}"
39
+ end
40
+
41
+ end; end; end
42
+
43
+ # vim: set tw=70 sw=2 sts=2 et fdm=marker :
@@ -0,0 +1,5 @@
1
+ # my namespace
2
+ module Obfusk; module Util
3
+ VERSION = '0.0.1.SNAPSHOT.20130724234552'
4
+ DATE = '2013-07-24'
5
+ end; end
@@ -0,0 +1,27 @@
1
+ require File.expand_path('../lib/obfusk/util/version', __FILE__)
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = 'obfusk-util'
5
+ s.homepage = 'https://github.com/obfusk/rb-obfusk-util'
6
+ s.summary = 'miscellaneous utility library for ruby'
7
+
8
+ s.description = <<-END.gsub(/^ {4}/, '')
9
+ ...
10
+ END
11
+
12
+ s.version = Obfusk::Util::VERSION
13
+ s.date = Obfusk::Util::DATE
14
+
15
+ s.authors = [ 'Felix C. Stegerman' ]
16
+ s.email = %w{ flx@obfusk.net }
17
+
18
+ s.license = 'GPLv2'
19
+
20
+ s.files = %w{ README.md obfusk-util.gemspec }\
21
+ + Dir['lib/**/*.rb']
22
+
23
+ s.add_development_dependency 'rake'
24
+ s.add_development_dependency 'rspec'
25
+
26
+ s.required_ruby_version = '>= 1.9.1'
27
+ end
metadata ADDED
@@ -0,0 +1,90 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: obfusk-util
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1.SNAPSHOT.20130724234552
5
+ prerelease: 6
6
+ platform: ruby
7
+ authors:
8
+ - Felix C. Stegerman
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-07-24 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rake
16
+ requirement: &15323640 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: *15323640
25
+ - !ruby/object:Gem::Dependency
26
+ name: rspec
27
+ requirement: &15321480 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: *15321480
36
+ description: ! '...
37
+
38
+ '
39
+ email:
40
+ - flx@obfusk.net
41
+ executables: []
42
+ extensions: []
43
+ extra_rdoc_files: []
44
+ files:
45
+ - README.md
46
+ - obfusk-util.gemspec
47
+ - lib/obfusk/util/message.rb
48
+ - lib/obfusk/util/struct.rb
49
+ - lib/obfusk/util/spec.rb
50
+ - lib/obfusk/util/os.rb
51
+ - lib/obfusk/util/version.rb
52
+ - lib/obfusk/util/process.rb
53
+ - lib/obfusk/util/run.rb
54
+ - lib/obfusk/util/data.rb
55
+ - lib/obfusk/util/opt.rb
56
+ - lib/obfusk/util/fs.rb
57
+ - lib/obfusk/util/term.rb
58
+ - lib/obfusk/util/misc.rb
59
+ - lib/obfusk/util/valid.rb
60
+ - lib/obfusk/util/all.rb
61
+ - lib/obfusk/util/die.rb
62
+ - lib/obfusk/util/module.rb
63
+ - lib/obfusk/util/cmd.rb
64
+ homepage: https://github.com/obfusk/rb-obfusk-util
65
+ licenses:
66
+ - GPLv2
67
+ post_install_message:
68
+ rdoc_options: []
69
+ require_paths:
70
+ - lib
71
+ required_ruby_version: !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ! '>='
75
+ - !ruby/object:Gem::Version
76
+ version: 1.9.1
77
+ required_rubygems_version: !ruby/object:Gem::Requirement
78
+ none: false
79
+ requirements:
80
+ - - ! '>'
81
+ - !ruby/object:Gem::Version
82
+ version: 1.3.1
83
+ requirements: []
84
+ rubyforge_project:
85
+ rubygems_version: 1.8.11
86
+ signing_key:
87
+ specification_version: 3
88
+ summary: miscellaneous utility library for ruby
89
+ test_files: []
90
+ has_rdoc: