#!/usr/bin/env ruby

require 'file/tail'
require 'tins/go'
include Tins::GO
require 'thread'
Thread.abort_on_exception = true

$opt = go 'n:m:Mh'
if $opt['h']
  puts <<EOT
Usage: #{File.basename($0)} [OPTS] PATHES

OPTS are
  -n NUMBER    show the last NUMBER of lines in the tailed files
  -m PATTERN   only tail files matching PATTERN, e. g. '*.log'
  -M           prefix every line with the logfile name
  -h           to display this help

EOT
  exit
end

dirs, logfiles = ARGV.partition { |path| File.directory?(path) }

$n = ($opt['n'] || 0).to_i
$logfiles = File::Tail::Group.new

def add_logfiles(logfiles)
  logfiles = logfiles.map { |l| File.expand_path(l) }
  $opt['m'] and logfiles =
    logfiles.select { |l| !$opt['m'] || File.fnmatch?($opt['m'], File.basename(l)) }
  for l in logfiles
    $logfiles.each_file.any? { |f| l == f.path } and next
    warn "Tailing '#{l}'."
    $logfiles.add_filename l, $n
  end
end

add_logfiles logfiles

t = Thread.new do
  $logfiles.tail do |line|
    if $opt['M']
      puts "#{line.file.path}: #{line}"
    else
      puts line
    end
  end
end

begin
  loop do
    logfiles = []
    for d in dirs
      logfiles.concat Dir[File.join(d, '*')].select { |x|
        File.file?(x) || File.symlink?(x)
      }
    end
    add_logfiles logfiles
    sleep 1
  end
rescue Interrupt
  warn " *** Interrupted *** "
end
