Ravn::CLI::

Subcommand module

Convenience module for subcommand registration syntax sugar.

Public Class Methods

extended( mod )

Extension callback – register the extending object as a subcommand.

# File lib/ravn/cli.rb, line 304
def self::extended( mod )
        Ravn::CLI.log.debug "Registering subcommands from %p" % [ mod ]
        Ravn::CLI.register_subcommands( mod )
end

Public Instance Methods

display_table( header, rows )

Output a table with the given header (an array) and rows (an array of arrays).

# File lib/ravn/cli.rb, line 391
def display_table( header, rows )
        table = TTY::Table.new( header, rows )
        renderer = nil

        if hl.enabled?
                renderer = TTY::Table::Renderer::Unicode.new(
                        table,
                        multiline: true,
                        padding: [0,1,0,1]
                )
                renderer.border.style = :dim

        else
                renderer = TTY::Table::Renderer::ASCII.new(
                        table,
                        multiline: true,
                        padding: [0,1,0,1]
                )
        end

        puts renderer.render
end
edit( path )

Invoke the user’s editor on a copy of the file at path (if it exists), and after the process exits move the copy back over the original unless it’s a zero-byte file.

# File lib/ravn/cli.rb, line 527
def edit( path )
        raise "Shell is not interactive" unless $stdin.isatty

        edit_cmd = find_editor() or exit_now!( "Couldn't find a suitable editor!" )

        path = Pathname( path ).expand_path
        tmpfile = Tempfile.create( [path.basename, 'edit'] )
        edit_cmd += [ tmpfile.path ]

        FileUtils.cp( path, tmpfile.path ) if path.exist?

        if system( *edit_cmd )
                if File.size?( tmpfile.path )
                        FileUtils.mv( tmpfile.path, path )
                        return true
                else
                        return false
                end
        else
                return false
        end
ensure
        File.unlink( tmpfile.path ) if tmpfile && File.exist?( tmpfile.path )
end
edit_and_read( filename, initial_content: '' )

Invoke the user’s editor on a tempfile with a name based on filename, then read it in and return the contents.

# File lib/ravn/cli.rb, line 555
def edit_and_read( filename, initial_content: '' )
        raise "Shell is not interactive" unless $stdin.isatty

        edit_cmd = find_editor() or exit_now!( "Couldn't find a suitable editor!" )
        tmpname = [
                File.basename( filename, File.extname(filename) ),
                File.extname( filename )
        ]

        Tempfile.create( tmpname ) do |tmpfile|
                tmpfile.write( initial_content )
                tmpfile.flush

                edit_cmd += [ tmpfile.path ]

                if system( *edit_cmd )
                        tmpfile.reopen( tmpfile.path, 'r' ) # Some editors use a tmpfile too
                        return tmpfile.read
                else
                        return nil
                end
        end
end
error_string( string )

Return the specified string in the ‘error’ ANSI color.

# File lib/ravn/cli.rb, line 384
def error_string( string )
        return hl.error( string )
end
execute( *command )

Execute the specified command.

# File lib/ravn/cli.rb, line 453
def execute( *command )
        command.flatten!( 1 )
        options = command.pop if command.last.is_a?( Hash )
        options ||= {}

        ignore_errors = options.delete( :ignore_errors )

        # Normalize the command into an array so we avoid a shell
        command = Shellwords.split( command.first ) if command.size == 1
        command_desc = highlight_string( Shellwords.join(command) )

        # Set up options for system()
        errlog = Tempfile.new( 'ravn-cli.log' )
        options[:err] = errlog
        options[:out] ||= errlog unless $VERBOSE || $DEBUG

        # Exec the command
        self.log.debug "Running command `%s`" % [ command_desc ]
        rval = system( *command, options )
        errlog.rewind

        # Handle result
        if rval
                self.log.debug "  command executed successfully."
        elsif rval.nil?
                Ravn::CLI.exit_now! "%s `%s` (%d)" % [
                        error_string( "Failed to execute" ),
                        command_desc,
                        $?.exitstatus
                ]
        elsif !ignore_errors
                Ravn::CLI.prompt.say "%s `%s`: \n%s" % [
                        error_string( "Error while running" ),
                        command_desc,
                        errlog.read
                ]
        end

        return rval
ensure
        errlog.unlink if errlog
end
exit_now!( message, exit_code=1 )

Exit with the specified exit_code after printing the given message.

# File lib/ravn/cli.rb, line 339
def exit_now!( message, exit_code=1 )
        raise GLI::CustomExit.new( message, exit_code )
end
find_editor()

Find the path to the user’s configured text editor and return it as a command Array (suitable for passing to Kernel.spawn). If no editor could be found, returns nil.

# File lib/ravn/cli.rb, line 500
def find_editor
        unless @found_editor
                raw_cmd =
                        Ravn::CLI.editor ||
                        Ravn::Subcommand.git_config_editor ||
                        EDITOR_ENV_VARS.map {|var| ENV[var] }.compact.first ||
                        FALLBACK_EDITOR_COMMAND
                self.log.debug "Raw editor command is: %p" % [ raw_cmd ]

                @found_editor = Shellwords.split( raw_cmd )
        end

        return @found_editor
end
format_branchname( branchname )

Return the specified branchname with formatting.

# File lib/ravn/cli.rb, line 422
def format_branchname( branchname )
        colors = case branchname
                when 'master'
                        [ :red ]
                when 'develop'
                        [ :blue ]
                else
                        [ :green ]
                end

        return hl.decorate( branchname, *colors )
end
git_config_editor()

Return the core.editor setting from the current environment’s git config.

# File lib/ravn/cli.rb, line 517
def git_config_editor
        results = self.read_output_of( ['git', 'config', 'core.editor'], ignore_errors: true ) or
                return nil
        return results.chomp
end
headline_string( string )

Return the specified string in the ‘headline’ ANSI color.

# File lib/ravn/cli.rb, line 366
def headline_string( string )
        return hl.headline( string )
end
help_now!( message=nil )

Exit with a helpful message and display the usage.

# File lib/ravn/cli.rb, line 345
def help_now!( message=nil )
        exception = OptionParser::ParseError.new( message )
        def exception.exit_code; 64; end

        raise exception
end
highlight_string( string )

Return the specified string in the ‘highlight’ ANSI color.

# File lib/ravn/cli.rb, line 372
def highlight_string( string )
        return hl.highlight( string )
end
hl()

Return the global Pastel object for convenient formatting, color, etc.

# File lib/ravn/cli.rb, line 360
def hl
        return Ravn::CLI.pastel
end
prompt()

Get the prompt (a TTY::Prompt object)

# File lib/ravn/cli.rb, line 354
def prompt
        return Ravn::CLI.prompt
end
read_output_of( *command )

Execute the specified command and return what it wrote to STDOUT.

# File lib/ravn/cli.rb, line 437
def read_output_of( *command )
        command.flatten!( 1 )
        options = command.pop if command.last.is_a?( Hash )
        options ||= {}

        r, w = IO.pipe
        reader = Thread.new { r.read }
        options.merge!( out: w, r => :close )
        execute( command, options ) or return nil
        w.close

        return reader.value
end
skips_around()

Use this if the following command should not have the around block executed. By default, the around block is executed, but for commands that might not want the setup to happen, this can be handy

# File lib/ravn/cli.rb, line 329
def skips_around
        @skips_around = true
end
skips_post()

Use this if the following command should not have the post block executed. By default, the post block is executed after each command. Using this will avoid that behavior for the following command

# File lib/ravn/cli.rb, line 321
def skips_post
        @skips_post = true
end
skips_pre()

Use this if the following command should not have the pre block executed. By default, the pre block is executed before each command and can result in aborting the call. Using this will avoid that behavior for the following command

# File lib/ravn/cli.rb, line 313
def skips_pre
        @skips_pre = true
end
success_string( string )

Return the specified string in the ‘success’ ANSI color.

# File lib/ravn/cli.rb, line 378
def success_string( string )
        return hl.success( string )
end
visible_chars( string )

Return the count of visible (i.e., non-control) characters in the given string.

# File lib/ravn/cli.rb, line 416
def visible_chars( string )
        return string.to_s.gsub(/\e\[.*?m/, '').scan( /\P{Cntrl}/ ).size
end