module Flucti module Utilities module UserInterface extend self def terminal_width @terminal_width ||= begin # Avoid error messages on Windows result = RUBY_PLATFORM =~ /mswin/ ? "" : `stty size 2>/dev/null` (result.split[1] || 80).to_i end end def puts_title(title, io=$stdout) generic_puts_title(io, title, "=", 3) end def puts_subtitle(title, io=$stdout) generic_puts_title(io, title, "-", 6) end def puts_long(message, io=$stdout) io.puts(adjust_to_terminal(message)) end def puts_list(entries, *args, &block) Utilities::ListDisplayer.new(*args, &block).display(entries) end def qcommand(task_name) quote(command(task_name)) end def quote(str) %(`#{str}') end alias q :quote def confirm(message) puts_title("/!\\ Warning") puts_long(message) puts "(You now have 10 seconds to cancel by pressing CTRL+C.)" puts if ENV['FORCE'] puts "$FORCE set, proceeding forcefully." else # 10 second countdown to cancel begin 10.downto(0) { |left| print(left, " "); sleep 1 } rescue Interrupt puts "\nAction cancelled." exit 0 end end end private POINT_START_FORMAT = '^ *[*$!] +'.freeze def generic_puts_title(io, title, line_block, left_padding) io.puts "", "#{line_block * left_padding} #{title} ".ljust(terminal_width, line_block) end def strip_margin(str) str = str.to_s margin = str.scan(/^\s*/).sort.first str.gsub(/^#{Regexp.escape margin}/, '') end def adjust_to_terminal(str) str = strip_margin(str.to_s) result, paragraph = [], [] process_current_paragraph = lambda do result << adjust_paragraph_to_terminal(paragraph.join("\n"), :auto) if paragraph.any? paragraph = [] end tail = str[/\s+\z/] || "" str.split(/\n/).each do |line| case line when /^\s*$/ process_current_paragraph[] result << nil when /^-/ process_current_paragraph[] paragraph << line process_current_paragraph[] when /#{POINT_START_FORMAT}[^ ]/ process_current_paragraph[] paragraph << line else paragraph << line end end process_current_paragraph[] result.join("\n") + tail end def adjust_paragraph_to_terminal(paragraph, margin=0) paragraph = paragraph.to_s if margin == :auto margin_top = paragraph[/#{POINT_START_FORMAT}/] paragraph = $' if $' margin = margin_top ? margin_top.length : 0 paragraph = paragraph.gsub(/^\s{0,#{margin}}/, '') end tail = paragraph[/\s+\z/] || "" paragraph. split(/\n/).map { |line| line.strip }.join(" ").scan(/(.{1,#{terminal_width - margin}})(\s|$)/). map { |matches| (margin_top ? (old, margin_top = margin_top, nil; old) : " " * margin) + matches.first }. join("\n") + tail end end end end