Module: FalkorLib::Common Abstract
- Defined in:
- lib/falkorlib/common.rb
Overview
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
-
.ask(question, default_answer = '') ⇒ Object
Ask a question.
-
.bold(str) ⇒ Object
Default printing functions ###.
-
.command?(name) ⇒ Boolean
Check for the presence of a given command.
-
.cyan(str) ⇒ Object
Print a text in cyan.
-
.error(str) ⇒ Object
Print an error message and abort.
-
.exec_or_exit(cmd) ⇒ Object
Execute a given command - exit if status != 0.
-
.execute(cmd) ⇒ Object
Simpler version that use the system call.
-
.execute_in_dir(path, cmd) ⇒ Object
Execute in a given directory.
-
.green(str) ⇒ Object
Print a text in green.
-
.info(str) ⇒ Object
Print an info message.
-
.init_from_template(templatedir, rootdir, config = {}, options = { :erb_exclude => [], :no_interaction => false }) ⇒ Object
Bootstrap the destination directory ‘rootdir` using the template directory `templatedir`.
-
.init_rvm(rootdir = Dir.pwd, gemset = '') ⇒ Object
RVM init.
-
.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.
-
.load_config(filepath) ⇒ Object
Return the yaml content as a Hash object.
-
.nice_execute(cmd) ⇒ Object
Execute a given command, return exit code and print nicely stdout and stderr.
-
.not_implemented ⇒ Object
simple helper text to mention a non-implemented feature.
-
.really_continue?(default_answer = 'Yes') ⇒ Boolean
Ask whether or not to really continue.
-
.red(str) ⇒ Object
Print a text in red.
-
.run(cmds) ⇒ Object
“Nice” way to present run commands Ex: run %{ hostname -f }.
-
.select_from(list, text = 'Select the index', default_idx = 0, raw_list = list) ⇒ Object
Display a indexed list to select an i.
-
.show_diff_and_write(content, outfile, options = { :no_interaction => false, :json_pretty_format => false, }) ⇒ Object
Show the difference between a ‘content` string and an destination file (using Diff algorithm).
-
.store_config(filepath, hash) ⇒ Object
Store the Hash object as a Yaml file.
-
.warning(str) ⇒ Object
(also: warn)
Print an warning message.
-
.write_from_erb_template(erbfile, outfile, config = {}, options = { :no_interaction => false }) ⇒ Object
ERB generation of the file ‘outfile` using the source template file `erbfile` Supported options: :no_interaction [boolean]: do not interact.
-
.write_from_template(src, dstdir, options = { :no_interaction => false, :srcdir => '', :outfile => '' }) ⇒ Object
Blind copy of a source file ‘src` into its destination directory `dstdir` Supported options: :no_interaction [boolean]: do not interact :srcdir [string]: source directory, make the `src` file relative to that directory :outfile [string]: alter the outfile name (File.basename(src) by default).
Class Method Details
.ask(question, default_answer = '') ⇒ Object
Ask a question
85 86 87 88 89 90 91 92 |
# File 'lib/falkorlib/common.rb', line 85 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
38 39 40 |
# File 'lib/falkorlib/common.rb', line 38 def bold(str) COLOR == true ? Term::ANSIColor.bold(str) : str end |
.command?(name) ⇒ Boolean
Check for the presence of a given command
106 107 108 109 |
# File 'lib/falkorlib/common.rb', line 106 def command?(name) `which #{name}` $?.success? end |
.cyan(str) ⇒ Object
Print a text in cyan
53 54 55 |
# File 'lib/falkorlib/common.rb', line 53 def cyan(str) COLOR == true ? Term::ANSIColor.cyan(str) : str end |
.error(str) ⇒ Object
Print an error message and abort
69 70 71 72 73 |
# File 'lib/falkorlib/common.rb', line 69 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
147 148 149 150 151 152 153 |
# File 'lib/falkorlib/common.rb', line 147 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
131 132 133 134 135 |
# File 'lib/falkorlib/common.rb', line 131 def execute(cmd) puts bold("[Running] #{cmd.gsub(/^\s*/, ' ')}") system(cmd) $? end |
.execute_in_dir(path, cmd) ⇒ Object
Execute in a given directory
138 139 140 141 142 143 144 |
# File 'lib/falkorlib/common.rb', line 138 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
43 44 45 |
# File 'lib/falkorlib/common.rb', line 43 def green(str) COLOR == true ? Term::ANSIColor.green(str) : str end |
.info(str) ⇒ Object
Print an info message
58 59 60 |
# File 'lib/falkorlib/common.rb', line 58 def info(str) puts green("[INFO] " + str) end |
.init_from_template(templatedir, rootdir, config = {}, options = { :erb_exclude => [], :no_interaction => false }) ⇒ 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'
:no_interaction [boolean]: do not interact
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 |
# File 'lib/falkorlib/common.rb', line 275 def init_from_template(templatedir, rootdir, config = {}, = { :erb_exclude => [], :no_interaction => false }) 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 [:erb_exclude].nil? exclude_entry = false [: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}'" write_from_erb_template(erbfile, outfile, config, ) end end |
.init_rvm(rootdir = Dir.pwd, gemset = '') ⇒ Object
RVM init
387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 |
# File 'lib/falkorlib/common.rb', line 387 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
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 219 |
# File 'lib/falkorlib/common.rb', line 177 def list_items(glob_pattern, = {}) 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 (! [:only_files].nil?) && [:only_files] && File.directory?(elem) next if (! [:only_dirs].nil?) && [: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 [:pattern_exclude].nil? select_entry = false [: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 = [:text].nil? ? "select the index" : [:text] default_idx = [:default].nil? ? 0 : [: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
246 247 248 |
# File 'lib/falkorlib/common.rb', line 246 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
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 |
# File 'lib/falkorlib/common.rb', line 112 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
76 77 78 |
# File 'lib/falkorlib/common.rb', line 76 def not_implemented() error("NOT YET IMPLEMENTED") end |
.really_continue?(default_answer = 'Yes') ⇒ Boolean
Ask whether or not to really continue
95 96 97 98 99 |
# File 'lib/falkorlib/common.rb', line 95 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
48 49 50 |
# File 'lib/falkorlib/common.rb', line 48 def red(str) COLOR == true ? Term::ANSIColor.red(str) : str end |
.run(cmds) ⇒ Object
“Nice” way to present run commands Ex: run %{ hostname -f }
157 158 159 160 161 162 163 164 165 166 167 168 |
# File 'lib/falkorlib/common.rb', line 157 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
222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 |
# File 'lib/falkorlib/common.rb', line 222 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 |
.show_diff_and_write(content, outfile, options = { :no_interaction => false, :json_pretty_format => false, }) ⇒ Object
Show the difference between a ‘content` string and an destination file (using Diff algorithm). Obviosuly, if the outfile does not exists, no difference is proposed. Supported options:
:no_interaction [boolean]: do not interact
:json_pretty_format [boolean]: write a json content, in pretty format
return 0 if nothing happened, 1 if a write has been done
331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 |
# File 'lib/falkorlib/common.rb', line 331 def show_diff_and_write(content, outfile, = { :no_interaction => false, :json_pretty_format => false, }) if File.exists?( outfile ) ref = File.read( outfile ) if [:json_pretty_format] ref = JSON.pretty_generate (JSON.parse( IO.read( outfile ) )) end if ref == content warn "Nothing to update" return 0 end warn "the file '#{outfile}' already exists and will be overwritten." warn "Expected difference: \n------" Diffy::Diff.default_format = :color puts Diffy::Diff.new(ref, content, :context => 1) else watch = [:no_interaction] ? 'no' : ask( cyan(" ==> Do you want to see the generated file before commiting the writing (y|N)"), 'No') puts content if watch =~ /y.*/i end proceed = [:no_interaction] ? 'yes' : ask( cyan(" ==> proceed with the writing (Y|n)"), 'Yes') return 0 if proceed =~ /n.*/i info("=> writing #{outfile}") File.open("#{outfile}", "w+") do |f| f.write content end if FalkorLib::Git.init?(File.dirname(outfile)) do_commit = [:no_interaction] ? 'yes' : ask( cyan(" ==> commit the changes (Y|n)"), 'Yes') FalkorLib::Git.add(outfile, "update content of '#{File.basename(outfile)}'") if do_commit =~ /y.*/i end return 1 end |
.store_config(filepath, hash) ⇒ Object
Store the Hash object as a Yaml file
251 252 253 254 255 256 257 |
# File 'lib/falkorlib/common.rb', line 251 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
63 64 65 |
# File 'lib/falkorlib/common.rb', line 63 def warning(str) puts cyan("/!\\ WARNING: " + str) end |
.write_from_erb_template(erbfile, outfile, config = {}, options = { :no_interaction => false }) ⇒ Object
ERB generation of the file ‘outfile` using the source template file `erbfile` Supported options:
:no_interaction [boolean]: do not interact
313 314 315 316 317 318 319 320 321 322 |
# File 'lib/falkorlib/common.rb', line 313 def write_from_erb_template(erbfile, outfile, config = {}, = { :no_interaction => false }) error "Unable to find the template file #{erbfile}" unless File.exists? (erbfile ) template = File.read("#{erbfile}") output = ERB.new(template, nil, '<>') content = output.result(binding) show_diff_and_write(content, outfile, ) end |
.write_from_template(src, dstdir, options = { :no_interaction => false, :srcdir => '', :outfile => '' }) ⇒ Object
Blind copy of a source file ‘src` into its destination directory `dstdir` Supported options:
:no_interaction [boolean]: do not interact
:srcdir [string]: source directory, make the `src` file relative to that directory
:outfile [string]: alter the outfile name (File.basename(src) by default)
371 372 373 374 375 376 377 378 379 380 381 382 383 |
# File 'lib/falkorlib/common.rb', line 371 def write_from_template(src,dstdir, = { :no_interaction => false, :srcdir => '', :outfile => '' }) srcfile = [:srcdir].nil? ? src : File.join([:srcdir], src) error "Unable to find the source file #{srcfile}" unless File.exists? ( srcfile ) error "The destination directory '#{dstdir}' do not exist" unless File.directory?( dstdir ) dstfile = [:outfile].nil? ? File.basename(srcfile) : [:outfile] outfile = File.join(dstdir, dstfile) content = File.read( srcfile ) show_diff_and_write(content, outfile, ) end |