Module: FalkorLib::Common Abstract

Defined in:
lib/falkorlib/common.rb

Overview

This module is abstract.

Recipe for all my toolbox and versatile Ruby functions I'm using everywhere. You'll typically want to include the FalkorLib::Common module to bring the corresponding definitions into yoru scope.

@example:

require 'falkorlib'
include FalkorLib::Common

info 'exemple of information text'
really_continue?
run %{ echo 'this is an executed command' }

Falkor.config.debug = true
run %{ echo 'this is a simulated command that *will not* be executed' }
error "that's an error text, let's exit with status code 1"

Class Method Summary collapse

Class Method Details

.ask(question, default_answer = '') ⇒ Object

Ask a question



84
85
86
87
88
89
90
91
# File 'lib/falkorlib/common.rb', line 84

def ask(question, default_answer='')
    print "#{question} "
    print "[Default: #{default_answer}]" unless default_answer == ''
    print ": "
    STDOUT.flush
    answer = STDIN.gets.chomp
    return answer.empty?() ? default_answer : answer
end

.bold(str) ⇒ Object

Default printing functions ###

Print a text in bold



37
38
39
# File 'lib/falkorlib/common.rb', line 37

def bold(str)
    COLOR == true ? Term::ANSIColor.bold(str) : str
end

.command?(name) ⇒ Boolean

Check for the presence of a given command

Returns:

  • (Boolean)


105
106
107
108
# File 'lib/falkorlib/common.rb', line 105

def command?(name)
    `which #{name}`
    $?.success?
end

.cyan(str) ⇒ Object

Print a text in cyan



52
53
54
# File 'lib/falkorlib/common.rb', line 52

def cyan(str)
    COLOR == true ? Term::ANSIColor.cyan(str) : str
end

.error(str) ⇒ Object

Print an error message and abort



68
69
70
71
72
# File 'lib/falkorlib/common.rb', line 68

def error(str)
    #abort red("*** ERROR *** " + str)
    $stderr.puts red("*** ERROR *** " + str)
    exit 1
end

.exec_or_exit(cmd) ⇒ Object

Execute a given command - exit if status != 0



146
147
148
149
150
151
152
# File 'lib/falkorlib/common.rb', line 146

def exec_or_exit(cmd)
    status = execute(cmd)
    if (status.to_i != 0)
        error("The command '#{cmd}' failed with exit status #{status.to_i}")
    end
    status
end

.execute(cmd) ⇒ Object

Simpler version that use the system call



130
131
132
133
134
# File 'lib/falkorlib/common.rb', line 130

def execute(cmd)
    puts bold("[Running] #{cmd.gsub(/^\s*/, ' ')}")
    system(cmd)
    $?
end

.execute_in_dir(path, cmd) ⇒ Object

Execute in a given directory



137
138
139
140
141
142
143
# File 'lib/falkorlib/common.rb', line 137

def execute_in_dir(path, cmd)
    exit_status = 0
    Dir.chdir(path) do
        exit_status = run %{ #{cmd} }
    end
    exit_status
end

.green(str) ⇒ Object

Print a text in green



42
43
44
# File 'lib/falkorlib/common.rb', line 42

def green(str)
    COLOR == true ? Term::ANSIColor.green(str) : str
end

.info(str) ⇒ Object

Print an info message



57
58
59
# File 'lib/falkorlib/common.rb', line 57

def info(str)
    puts green("[INFO] " + str)
end

.init_from_template(templatedir, rootdir, config = {}, options = {}) ⇒ Object

Bootstrap the destination directory rootdir using the template directory templatedir. the hash table config hosts the elements to feed ERB files which should have the extension .erb. The initialization is performed as follows:

  • a rsync process is initiated to duplicate the directory structure and the symlinks, and exclude .erb files
  • each erb files (thus with extension .erb) is interpreted, the corresponding file is generated without the .erb extension Supported options: :erb_exclude [array of strings]: pattern(s) to exclude from erb file interpretation and thus to copy 'as is'


273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
# File 'lib/falkorlib/common.rb', line 273

def init_from_template(templatedir, rootdir, config = {}, options = {})
    error "Unable to find the template directory" unless File.directory?(templatedir)
    warning "about to initialize/update the directory #{rootdir}"
    really_continue?
    run %{ mkdir -p #{rootdir} } unless File.directory?( rootdir )
    run %{ rsync --exclude '*.erb' -avzu #{templatedir}/ #{rootdir}/ }
    Dir["#{templatedir}/**/*.erb"].each do |erbfile|
  relative_outdir = Pathname.new( File.realpath( File.dirname(erbfile) )).relative_path_from Pathname.new(templatedir)
  filename = File.basename(erbfile, '.erb')
  outdir   = File.realpath( File.join(rootdir, relative_outdir.to_s) )		        
  outfile  = File.join(outdir, filename)
  unless options[:erb_exclude].nil?
   exclude_entry = false
   options[:erb_exclude].each do |pattern|
    exclude_entry |= erbfile =~ /#{pattern}/
   end
   if exclude_entry
    info "copying non-interpreted ERB file"
    # copy this file since it has been probably excluded from teh rsync process
    run %{ cp #{erbfile} #{outdir}/ }
    next 
   end 
  end 
  # Let's go
  info "updating '#{relative_outdir.to_s}/#{filename}'"
  puts "  using ERB template '#{erbfile}'"
  template = File.read("#{erbfile}")
        output   = ERB.new(template, nil, '<>')
  if File.exists?( outfile )
   warn "the file '#{outfile}' already exists and will be overwritten."
   error "TODO: watch the diff ;)"
  else 
   watch =  ask( cyan("  ==> Do you want to see the generated file before commiting the writing (y|N)"), 'No')
   puts output.result(binding) if watch =~ /y.*/i
  end 
  proceed = ask( cyan("  ==> proceed with the writing (Y|n)"), 'Yes')
  next if proceed =~ /n.*/i
  info("=> writing #{outfile}")
        File.open("#{outfile}", "w+") do |f|
   f.puts output.result(binding)
        end
    end    
end

.init_rvm(rootdir = Dir.pwd, gemset = '') ⇒ Object

RVM init



318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
# File 'lib/falkorlib/common.rb', line 318

def init_rvm(rootdir = Dir.pwd, gemset = '')
 rvm_files = {
  :version => File.join(rootdir, '.ruby-version'),
  :gemset  => File.join(rootdir, '.ruby-gemset')
 }
 unless File.exists?( "#{rvm_files[:version]}")
  v = select_from(FalkorLib.config[:rvm][:rubies], 
                  "Select RVM ruby to configure for this directory", 
                  3)
  File.open( rvm_files[:version], 'w') do |f|
   f.puts v
  end
 end 
 unless File.exists?( "#{rvm_files[:gemset]}")
  g = gemset.empty? ? ask("Enter RVM gemset name for this directory", File.basename(rootdir)) : gemset
  File.open( rvm_files[:gemset], 'w') do |f|
   f.puts g
  end
 end 
 
end

.list_items(glob_pattern, options = {}) ⇒ Object

List items from a glob pattern to ask for a unique choice Supported options:

:only_files      [boolean]: list only files in the glob
:only_dirs       [boolean]: list only directories in the glob
:pattern_include [array of strings]: pattern(s) to include for listing   
:pattern_exclude [array of strings]: pattern(s) to exclude for listing
:text            [string]: text to put

Raises:

  • (SystemExit)


176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
# File 'lib/falkorlib/common.rb', line 176

def list_items(glob_pattern, options = {})
    list  = { 0 => 'Exit' }
    index = 1
    raw_list = { 0 => 'Exit' }

    Dir["#{glob_pattern}"].each do |elem|
        #puts "=> element '#{elem}' - dir = #{File.directory?(elem)}; file = #{File.file?(elem)}"
        next if (! options[:only_files].nil?) && options[:only_files] && File.directory?(elem)
        next if (! options[:only_dirs].nil?)  && options[:only_dirs]  && File.file?(elem)
        entry = File.basename(elem)
        unless options[:pattern_include].nil?
            select_entry = false
            options[:pattern_include].each do |pattern|
                #puts "considering pattern '#{pattern}' on entry '#{entry}'"
                select_entry |= entry =~ /#{pattern}/
            end
            next unless select_entry
        end
        unless options[:pattern_exclude].nil?
            select_entry = false
            options[:pattern_exclude].each do |pattern|
                #puts "considering pattern '#{pattern}' on entry '#{entry}'"
                select_entry |= entry =~ /#{pattern}/
            end
            next if select_entry
        end
        #puts "selected entry = '#{entry}'"
        list[index]     = entry
        raw_list[index] = elem
        index += 1
    end
    text        = options[:text].nil?    ? "select the index" : options[:text]
    default_idx = options[:default].nil? ? 0 : options[:default]
    raise SystemExit.new('Empty list') if index == 1
 #ap list
 #ap raw_list
    # puts list.to_yaml
    # answer = ask("=> #{text}", "#{default_idx}")
    # raise SystemExit.new('exiting selection') if answer == '0'
    # raise RangeError.new('Undefined index')   if Integer(answer) >= list.length
    # raw_list[Integer(answer)]
    select_from(list, text, default_idx, raw_list)
end

.load_config(filepath) ⇒ Object

Return the yaml content as a Hash object



245
246
247
# File 'lib/falkorlib/common.rb', line 245

def load_config(filepath)
    YAML::load_file(filepath)
end

.nice_execute(cmd) ⇒ Object

Execute a given command, return exit code and print nicely stdout and stderr



111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/falkorlib/common.rb', line 111

def nice_execute(cmd)
    puts bold("[Running] #{cmd.gsub(/^\s*/, ' ')}")
    stdout, stderr, exit_status = Open3.capture3( cmd )
    unless stdout.empty?
        stdout.each_line do |line|
            print "** [out] #{line}"
            $stdout.flush
        end
    end
    unless stderr.empty?
        stderr.each_line do |line|
            $stderr.print red("** [err] #{line}")
            $stderr.flush
        end
    end
    exit_status
end

.not_implemented ⇒ Object

simple helper text to mention a non-implemented feature



75
76
77
# File 'lib/falkorlib/common.rb', line 75

def not_implemented()
    error("NOT YET IMPLEMENTED")
end

.really_continue?(default_answer = 'Yes') ⇒ Boolean

Ask whether or not to really continue

Returns:

  • (Boolean)


94
95
96
97
98
# File 'lib/falkorlib/common.rb', line 94

def really_continue?(default_answer = 'Yes')
    pattern = (default_answer =~ /yes/i) ? '(Y|n)' : '(y|N)'
    answer = ask( cyan("=> Do you really want to continue #{pattern}?"), default_answer)
    exit 0 if answer =~ /n.*/i
end

.red(str) ⇒ Object

Print a text in red



47
48
49
# File 'lib/falkorlib/common.rb', line 47

def red(str)
    COLOR == true ? Term::ANSIColor.red(str) : str
end

.run(cmds) ⇒ Object

"Nice" way to present run commands Ex: run %{ hostname -f }



156
157
158
159
160
161
162
163
164
165
166
167
# File 'lib/falkorlib/common.rb', line 156

def run(cmds)
    exit_status = 0
    puts bold("[Running]\n#{cmds.gsub(/^\s*/, '   ')}")
    $stdout.flush
    #puts cmds.split(/\n */).inspect
    cmds.split(/\n */).each do |cmd|
        next if cmd.empty?
        system("#{cmd}") unless FalkorLib.config.debug
        exit_status = $?
    end
    exit_status
end

.select_from(list, text = 'Select the index', default_idx = 0, raw_list = list) ⇒ Object

Display a indexed list to select an i

Raises:

  • (SystemExit)


221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
# File 'lib/falkorlib/common.rb', line 221

def select_from(list, text = 'Select the index', default_idx = 0, raw_list = list)
    error "list and raw_list differs in size" if list.size != raw_list.size
    l     = list
    raw_l = raw_list
    if list.kind_of?(Array)
        l = raw_l = { 0 => 'Exit' }
        list.each_with_index do |e, idx|
            l[idx+1] = e
            raw_l[idx+1] = raw_list[idx]
        end
    end
    puts l.to_yaml
    answer = ask("=> #{text}", "#{default_idx}")
    raise SystemExit.new('exiting selection') if answer == '0'
    raise RangeError.new('Undefined index')   if Integer(answer) >= l.length
    raw_l[Integer(answer)]
end

.store_config(filepath, hash) ⇒ Object

Store the Hash object as a Yaml file



250
251
252
253
254
255
256
# File 'lib/falkorlib/common.rb', line 250

def store_config(filepath, hash)
    File.open( filepath, 'w') do |f|
        f.print "# ", File.basename(filepath), "\n"
        f.puts "# /!\\ DO NOT EDIT THIS FILE: it has been automatically generated"
        f.puts hash.to_yaml
    end
end

.warning(str) ⇒ Object Also known as: warn

Print an warning message



62
63
64
# File 'lib/falkorlib/common.rb', line 62

def warning(str)
    puts cyan("/!\\ WARNING: " + str)
end