Permalink
Browse files

initial commit

  • Loading branch information...
0 parents commit 60ff22a2e2d10f99f7bb789a239e775da6cb058b @joemiller committed Nov 16, 2011
Showing with 153 additions and 0 deletions.
  1. +53 −0 README.md
  2. +100 −0 spark-ping
@@ -0,0 +1,53 @@
+spark-ping
+==========
+
+A ping 'GUI' for the command line using sparklines.
+
+Example:
+
+ $ ./spark-ping google.com
+ ▃▇▄▄▅▄▃▃▃▄▃▃▄▄▄▄▅▄▅▃▅▃▃▃▄▄▃▃▄▅▄▃▄▃ 24.731 ms
+
+Implemented as a Ruby wrapper around your system's normal `ping` utility.
+Does not require any special gems, so it should work out of the box on
+many platforms.
+
+The sparklines are multi-byte UTF8 characters, so your terminal may or may
+not display them correctly.
+
+Tested with
+-----------
+
+- Ruby: 1.8.7, 1.9.2, 1.8.5 (centos5)
+- Terminal: Terminal.app, iTerm2.app
+- OS Ping: OSX 10.7, Linux (centos5)
+
+Install
+-------
+
+Copy it somewhere in your path. Run it like you would run `ping`.
+
+Thanks
+------
+
+- https://github.com/holman/spark - for "sparking" this whole thing
+- R.I.Pienaar (http://www.devco.net) - for the ping idea on ##infra-talk
+
+LICENSE
+-------
+
+ Author:: Joe Miller (http://joemiller.me)
+ Copyright:: Copyright (c) 2011 Joe Miller
+ License:: Apache License, Version 2.0
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
@@ -0,0 +1,100 @@
+#!/usr/bin/env ruby
+#
+# A ping 'GUI' for the command line using sparklines.
+#
+# Example:
+#
+# $ ./spark-ping google.com
+# ▃▇▄▄▅▄▃▃▃▄▃▃▄▄▄▄▅▄▅▃▅▃▃▃▄▄▃▃▄▅▄▃▄▃ 24.731 ms
+#
+# Implemented as a Ruby wrapper around your system's normal `ping` utility.
+# Does not require any special gems, so it should work out of the box on
+# many platforms. Only tested with OSX and Linux `ping`.
+#
+# The sparklines are multi-byte UTF8 characters, so your terminal may or may
+# not display them correctly. Tested on Mac OSX using Terminal.app and iTerm2.
+#
+# Joe Miller (http://joemiller.me, https://github.com/joemiller). 11/16/2011
+
+require 'pty'
+
+def command_exists?(command)
+ ENV['PATH'].split(File::PATH_SEPARATOR).any? {|d| File.exists? File.join(d, command) }
+end
+
+def detect_terminal_size
+ if (ENV['COLUMNS'] =~ /^\d+$/) && (ENV['LINES'] =~ /^\d+$/)
+ [ENV['COLUMNS'].to_i, ENV['LINES'].to_i]
+ elsif (RUBY_PLATFORM =~ /java/ || (!STDIN.tty? && ENV['TERM'])) && command_exists?('tput')
+ [`tput cols`.to_i, `tput lines`.to_i]
+ elsif STDIN.tty? && command_exists?('stty')
+ `stty size`.scan(/\d+/).map { |s| s.to_i }.reverse
+ else
+ nil
+ end
+ rescue
+ nil
+end
+
+def spark(durations)
+ return "" unless durations.size > 1
+
+ ticks=%w[▁ ▂ ▃ ▄ ▅ ▆ ▇]
+
+ range = durations.max - durations.min
+ scale = ticks.length - 1
+ distance = durations.max.to_f / ticks.size
+
+ str = ''
+ durations.each do |val|
+ tick = (val / distance).round - 1
+ str << ticks[tick]
+ end
+ str
+end
+
+### main --
+if __FILE__ == $0
+ trap("INT") { puts; exit }
+ # XXX: could also trap WINCH to detect changes in terminal size..
+
+ (columns,lines) = detect_terminal_size
+ durations = []
+
+ begin
+ PTY.spawn( "ping #{ARGV.join(' ')}" ) do |stdin, stdout, pid|
+ begin
+ stdin.each do |line|
+ ## if we see 'usage:' or 'ping: ..' an error probably occurred
+ ## so flush the output from ping and exit. (XXX: this is hacky)
+ if line =~ /^usage:/i or line =~ /^ping:/
+ puts line
+ puts stdin.readlines
+ exit 1
+ end
+
+ duration = line.scan( /time=(\S+)/ ).last
+ durations << duration.first.to_f unless duration.nil?
+
+ sparkline = spark( durations )
+ output = "#{sparkline} #{durations.last} ms\r"
+ print output
+
+ # if we reach the end of the line, reset and start on next line.
+ # NOTE: need to use a regex to count the number of chars
+ # because `output` is a multibyte utf8 string.
+ if output.scan(/./mu).size >= columns
+ durations = []
+ puts
+ end
+ end
+ rescue Errno::EIO
+ puts "IO error (EIO)" # XXX
+ end
+ end
+ rescue PTY::ChildExited
+ puts "ping exited unexpectedly" # XXX
+ end
+
+ puts
+end

0 comments on commit 60ff22a

Please sign in to comment.