Verified Commit be27b1a3 authored by Hermann Mayer's avatar Hermann Mayer
Browse files

VimRC: Added a ruby-bundler package. BashRC: Added more fonts, updated some...

VimRC: Added a ruby-bundler package. BashRC: Added more fonts, updated some tooling and replaced the mpx implementation.

Signed-off-by: Hermann Mayer's avatarHermann Mayer <hermann.mayer92@gmail.com>
parent e9202c19
Loading
Loading
Loading
Loading

bin/mpx

0 → 100755
+228 −0
Original line number Diff line number Diff line
#!/usr/bin/env ruby
# vim: ft=ruby

$clr_rst = "\e[0m"
$clr_ylw = "\e[0;33m"
$clr_cyn = "\e[0;36m"
$clr_red = "\e[0;31m"
$clr_grn = "\e[0;32m"
$clr_mag = "\e[0;35m"
$term_cols = `tput cols`.to_i

def help(exit_code: nil)
  puts <<~EOF
  #{$PROGRAM_NAME} [OPTIONS] [DIR..] [COMMAND]

  MultiPleXing - execute the given command on all given directories.
  With this tool you can ease the work of repetetive tasks.

  By default all directories in the current working directory are used
  when the directory list is omitted by the user. The default command is
  `ls -lisa` when no command is passed by the user.

  Options

    --[no]changes      Only run the command when Git changes are present,
      -c, -C           or when Git changes are absent. By default no filter
                       is applied to the directory list. (-C no changes)
    --[no]clear        Soft reset the terminal after each command
      -x, -X
    --[no]reset,       Hard reset the terminal after each command
      -r, -R
    --prompt, -p       Prompt the user after each command
    --dryrun, -d       No actual command is invoked
    --compact, -s      No fancy headers

  Examples

    Show the Git status of all sub-directories of your CWD
    $ mpx * "git status"

    Push only the sub-directories with changes
    $ mpx --changes "git push"
EOF
  unless exit_code.nil?
    exit(exit_code)
  end
end

def branch(dir)
  return nil unless File.directory? "#{dir}/.git"
  output = `cd "#{dir}" && git rev-parse --abbrev-ref HEAD 2>&1`.strip
  return nil if /fatal:/.match? output
  output
end

def skip?(dir, branch)
  # When no changes filter is set, do not skip
  return false if $options[:changes].nil?

  # Check for git changes
  unless $options[:changes].nil?
    changes = Dir.chdir(dir) do
      # Check for uncommited file changes
      output = `LC_ALL=C git status 2>&1`
      changes = /Changes|Untracked files/.match? output

      # Check for commits which are not yet pushed,
      # in case there are no uncommited file changes
      if !changes && branch
        output = `LC_ALL=C git log origin/#{branch}..#{branch} 2>&1`
        changes = output.lines.count > 0
      end

      changes
    end

    return false if changes && $options[:changes]
    return false if !changes && !$options[:changes]
    return true
  end

  false
end

def header(cur, all, dir, skip, branch)
  line = ["#{$clr_ylw}##{$clr_rst}"]

  line << sprintf('%3i/%i | %5.1f%%', cur, all, (cur * 1.0 / all) * 100) \
    if $options[:prompt]

  line << "#{$clr_red}      [SKIP]" if skip
  line << "#{$clr_grn}   [CHANGES]" if $options[:changes] && !skip
  line << "#{$clr_grn}[NO CHANGES]" \
    if !$options[:changes] && !skip && !$options[:changes].nil?
  line << "#{$clr_cyn}#{dir}"
  line << "#{$clr_mag}(#{branch})#{$clr_rst}" unless branch.nil?
  line = line.join(' ')

  if $options[:compact]
    puts line
  else
    no_color = line.gsub(/\e\[[^m]+m/, '').strip
    len = no_color.length
    add = $term_cols - len - 1

    line << "#{' ' * add}#{$clr_ylw}#" if add > 1
    line << "#{$clr_rst}"

    puts "#{$clr_ylw}##{$clr_rst}" * $term_cols
    puts line
    puts "#{$clr_ylw}##{$clr_rst}" * $term_cols
    puts "#{$clr_ylw}##{$clr_rst} Command: #{$command}" unless $options[:dryrun]
  end
end

def run(cur, all, dir)
  # Clear the terminal when configured
  unless $options[:reset].nil?
    system('clear') if $options[:reset] == :soft
    system('reset') if $options[:reset] == :hard
  end

  branch = branch(dir)
  skip = skip?(dir, branch)
  header(cur, all, dir, skip, branch)
  puts unless skip || $options[:dryrun]

  # Run the command in case we should not skip the current directory
  unless $options[:dryrun]
    Dir.chdir(dir) do
      system '/bin/bash', '-c', '/bin/bash ' \
        '--rcfile <(echo "clear() { true; }; ' \
          'trap \"exit\" EXIT; ' \
          'trap() { true; }; ' \
          'source ~/.bashrc 1>/dev/null 2>&1") ' \
        "-ci #{$command.inspect}"
      puts
    end unless skip
  end

  # Prompt the user when configured
  if $options[:prompt] && !skip
    printf "\n#{$clr_ylw}##{$clr_rst} Press "
    printf "#{$clr_ylw}[Enter]#{$clr_rst} to continue "
    printf "or #{$clr_ylw}[Ctrl+C]#{$clr_rst} to abort"

    begin
      $stdin.gets
    rescue SystemExit, Interrupt
      puts "\n\nAborted."
      exit(1)
    end
  end

  puts unless $options[:compact]
end

$endofargs = false
$dirs = []
$command = []
$options = {
  prompt: false,
  reset: nil,
  changes: nil,
  dryrun: false,
  compact: false
}

# Analyse the given arguments
ARGV.each do |str|
  # Detect options
  if str.start_with?('-') && $endofargs == false
    case str
    when /-h|--help/
      help(exit_code: 0)
    when /-C|--nochanges/
      $options[:changes] = false
    when /-c|--changes/
      $options[:changes] = true
    when /-x|--clear/
      $options[:reset] = :soft
    when /-r|--reset/
      $options[:reset] = :hard
    when /-X|--noclear|-R|--noreset/
      $options[:reset] = nil
    when /-p|--prompt/
      $options[:prompt] = true
    when /-d|--dryrun/
      $options[:dryrun] = true
    when /-s|--compact/
      $options[:compact] = true
    else
      puts "Unknown option '#{str}'\n\n"
      help(exit_code: 1)
    end
    next
  end

  if File.directory? str
    # Detect directories
    $dirs << str
    $endofargs = true
  else
    # Must be part of the command
    $command << str
    $endofargs = true
  end
end

# Set defaults
#
# Use all directories in our CWD when no dirs were passed
$dirs = Dir.glob('*').select { |file| File.directory? file } \
  if $dirs.empty?
# Use a default command when no command was passed
$command = %w(ls -lisa) if $command.empty?
$command = $command.join(' ')

# If no arguments were given, just list dirs with changes
if ARGV.empty?
  $options[:reset] = nil
  $options[:changes] = true
  $options[:compact] = true
  $options[:dryrun] = true
end

# Run the configured command on all configured directories
$dirs.sort.each_with_index { |dir, idx| run(idx + 1, $dirs.count, dir) }
+2 −2
Original line number Diff line number Diff line
install: --no-ri --no-rdoc
update: --no-ri --no-rdoc
install: --no-document
update: --no-document
+1 −1
Original line number Diff line number Diff line
fb86c0f1-3fd8-4677-aba4-a75f7eae8259
 No newline at end of file
24699ffe-94e4-4e38-81c4-144689074b51
 No newline at end of file
+219 KiB

File added.

No diff preview for this file type.

+208 KiB

File added.

No diff preview for this file type.

Loading