├── TODO.md
├── widget.examples
├── netstats.coffee
├── battery.coffee
├── date.coffee
└── calendar.coffee
├── date.rb
├── README.md
├── netstats.rb
├── btbattery.rb
├── battery.rb
└── calendar.rb
/TODO.md:
--------------------------------------------------------------------------------
1 | update README with more information
2 |
3 | add Übersicht sample widget files
4 |
5 | make netstats portable outside of OS X
6 |
7 | make battery portable outside of OS X
8 |
9 | calendar: make --colorday and --colordate work with --vertical
10 |
--------------------------------------------------------------------------------
/widget.examples/netstats.coffee:
--------------------------------------------------------------------------------
1 | command: "/path/to/netstats.rb --options"
2 | refreshFrequency: 60000
3 |
4 | render: (output) -> """
5 | #{output}
6 | """
7 |
8 | # top left of a 1920x1200 screen, adjust as needed
9 | style: """
10 | text-align: left;
11 | top: 5px;
12 | color: #777;
13 | font-family: 'Anonymous Pro for Powerline', monospace;
14 | font-size: 13px;
15 | """
16 |
--------------------------------------------------------------------------------
/widget.examples/battery.coffee:
--------------------------------------------------------------------------------
1 | command: "/path/to/battery.rb --options"
2 | refreshFrequency: 10000
3 |
4 | render: (output) -> """
5 | #{output}
6 | """
7 |
8 | # bottom right corner of a 1920x1200 screen, adust as needed
9 | style: """
10 | text-align: right;
11 | width: 100%;
12 | top: 1165px;
13 | color: #777;
14 | font-family: 'Anonymous Pro for Powerline', monospace;
15 | font-size: 12px;
16 | """
17 |
--------------------------------------------------------------------------------
/widget.examples/date.coffee:
--------------------------------------------------------------------------------
1 | command: "/path/to/date.rb --options"
2 | refreshFrequency: 60000
3 |
4 | render: (output) -> """
5 | #{output}
6 | """
7 |
8 | # top center of a 1920x1200 screen, adjust as needed
9 | style: """
10 | margin-left: auto;
11 | margin-right: auto;
12 | width: 100%;
13 | text-align: center;
14 | top: 40px;
15 | color: #777;
16 | font-family: 'HelveticaNeue-CondensedBold';
17 | font-size: 60 px;
18 | """
19 |
--------------------------------------------------------------------------------
/widget.examples/calendar.coffee:
--------------------------------------------------------------------------------
1 | command: "/path/to/calendar.rb --options"
2 | refreshFrequency: 60000
3 |
4 | render: (output) -> """
5 | #{output}
6 | """
7 |
8 | # top center of a 1920x1200 screen, adjust as needed
9 | style: """
10 | margin-left: auto;
11 | margin-right: auto;
12 | width: 100%;
13 | text-align: center;
14 | top: 5px;
15 | color: #777;
16 | font-family: 'Anonymous Pro for Powerline', monospace;
17 | font-size: 12px;
18 | """
19 |
--------------------------------------------------------------------------------
/date.rb:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 |
3 | require 'optparse'
4 | options = {}
5 |
6 | parser = OptionParser.new do |opts|
7 | opts.banner = "Usage: date.rb [options]"
8 |
9 | options[:type] = 'long'
10 | opts.on( '-t TYPE', '--type TYPE', 'Date string type to output (long, short, time, longDate, shortDate, string)' ) do |type|
11 | options[:type] = type
12 | end
13 |
14 | options[:string] = ''
15 | opts.on( '-s "STRING"', '--string "STRING"', 'UNIX date string to output') do |string|
16 | options[:string] = string
17 | end
18 |
19 | opts.on( '-h', '--help', 'Displays this help screen' ) do
20 | puts opts
21 | exit
22 | end
23 | end
24 |
25 | parser.parse!
26 |
27 | class Datetime
28 | def long # Tuesday, September 23 11:11 PM
29 | return Time.now.strftime("%A, %B %d %I:%M %p")
30 | end # def long
31 |
32 | def short # Tue, Sep 23 11:11 PM
33 | return Time.now.strftime("%a, %b %d %I:%M %p")
34 | end # def short
35 |
36 | def time # 11:11 PM
37 | # future support for time zones and possibly world clocks!
38 | # ENV['TZ']='America/Chicago'
39 | return Time.now.strftime("%I:%M %p")
40 | end # def time
41 |
42 | def longDate # Tuesday, September 23
43 | return Time.now.strftime("%A, %B %d")
44 | end # def longDate
45 |
46 | def shortDate # Tue, Sep 23
47 | return Time.now.strftime("%a, %b %d")
48 | end # def shortDate
49 |
50 | def string(string)# Returns the interpereted value of string
51 | return Time.now.strftime(string)
52 | end # def string
53 | end # class DateTime
54 |
55 | time = Datetime.new
56 | if options[:type] == nil then
57 | puts time.long
58 | else
59 | case options[:type]
60 | when "long"
61 | puts time.long
62 | when "short"
63 | puts time.short
64 | when "time"
65 | puts time.time
66 | when "longDate"
67 | puts time.longDate
68 | when "shortDate"
69 | puts time.shortDate
70 | when "string"
71 | if options[:string] == nil then
72 | puts "Please enter a date format string"
73 | else
74 | puts time.string(options[:string])
75 | end # if options[:string] == nil
76 | else
77 | puts time.long
78 | end # case options[:type]
79 | end # if options[:type] == nil
80 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Geeklet Scripts
2 |
3 | ## A collection of scripts for use with [GeekTool](http://projects.tynsoe.org/en/geektool/) or [Übersicht](http://tracesof.net/uebersicht/)
4 |
5 | For best results using these scripts with geektool you should use a [fixed width font](https://en.wikipedia.org/wiki/Monospaced_font).
6 |
7 | ### calendar.rb
8 |
9 | This geeklet requires the htmlentities gem, you can install this with ```sudo gem install htmlentities```
10 |
11 | ```
12 | Usage: calendar.rb [options]
13 | -v, --vertical Orients the calendar vertically instead of horizontally
14 | -i, --indicator INDICATOR The string used to denote which day it currently is on the separator (should be 2 characters)
15 | -z, --colorize indicate the current day with color
16 | -c, --color COLOR Sets the color to use as the current day marker (black, red, green, yellow, blue, magenta, cyan, white)
17 | -C, --hicolor Uses the hicolor ASCII value for the chose color
18 | -t, --colordate Use color to mark the date (01, 02, 03)
19 | -d, --colorday Use color to mark the day (Mo, Tu, We)
20 | -S, --noseparator Do not output the separator line between days and dates
21 | -H, --html Output HTML color codes instead of shell for use with Ubersicht - requires HTMLEntities gem
22 | -h, --help Displays this help dialogue
23 | ```
24 |
25 | ### battery.rb
26 |
27 | Displays a battery meter for the system battery.
28 |
29 | ```
30 | Usage: battery.rb [options]
31 | -c, --color Display battery meter with color
32 | -s, --size SIZE Size (small, big, bigger) of battery meter
33 | -H, --html Output HTML color codes instead of shell for use with Ubersicht
34 | -h, --help Displays this help screen
35 | ```
36 |
37 | ### btbattery.rb
38 |
39 | This script is very limited in what it supports currently. Tested with Magic Keyboard with Numeric Keypad and Magic Mouse, though it should support all Apple Bluetooth HID devices.
40 |
41 | ```
42 | Usage: battery.rb [options]
43 | -c, --color Display battery meter with color
44 | -s, --size SIZE Size (small, big, bigger) of battery meter
45 | -l, --cell CELL The character to use for each battery cell
46 | -H, --html Out put HTML color codes instead of shell
47 | -m, --map MAP Key:Value mapping of device names to display names, separated by a semicolon (;) (ex: 'Magic Keyboard with Numeric Keypad:Keyboard')
48 | -S, --separator SEPARATOR Split multiple batteries by this string (default '\n')
49 | -h, --help Displays this help screen
50 | ```
51 |
52 | ### netstats.rb
53 |
54 | Displays some basic network interface data.
55 |
56 | ```
57 | Usage: netstats.rb [options]
58 | -i, --iface IFACE Set iface to monitor
59 | -w, --wifi iface is a wireless access point
60 | -s, --server set the server to gauge ping response[google.com]
61 | -H, --html Output HTML color codes instead of shell for use with Ubersicht
62 | -h, --help Displays this help screen
63 | ```
64 |
65 | ### date.rb
66 |
67 | Very basic script to output a date string with some predefined types or using a custom unix date string.
68 |
69 | ```
70 | Usage: date.rb [string type]
71 | -t, --type TYPE Date string type to output (long, short, time, longDate, shortDate, string)
72 | -s, --string "STRING" UNIX date string to output
73 | -h, --help Displays this help screen
74 | ```
75 |
--------------------------------------------------------------------------------
/netstats.rb:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | #coding: utf-8
3 |
4 | require 'open-uri'
5 | require 'optparse'
6 | options = {}
7 |
8 | parser = OptionParser.new do |opts|
9 | opts.banner = "Usage: netstats.rb [options]"
10 |
11 | options[:iface] = 'en1'
12 | opts.on( '-i IFACE', '--iface IFACE', 'Set iface to monitor' ) do |iface|
13 | options[:iface] = iface
14 | end
15 |
16 | options[:wifi] = false
17 | opts.on( '-w', '--wifi', 'iface is a wireless access point' ) do
18 | options[:wifi] = true
19 | end
20 |
21 | options[:ping] = false
22 | opts.on('-p', '--ping', 'run ping test to specified server[default: google.com]' ) do
23 | options[:ping] = true
24 | end
25 |
26 | options[:server] = 'google.com'
27 | opts.on( '-s', '--server', 'set the server to gauge ping response[google.com]' ) do |server|
28 | options[:server] = server
29 | end
30 |
31 | options[:html] = false
32 | opts.on( '-H', '--html', 'Output HTML color codes instead of shell') do
33 | options[:html] = true
34 | end
35 |
36 | opts.on( '-h', '--help', 'Displays this help screen' ) do
37 | puts opts
38 | exit
39 | end
40 | end
41 |
42 | parser.parse!
43 |
44 | class Net_Stats
45 | AIRPORT_UTILITY = "/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport"
46 |
47 | def initialize(opts)
48 | @options = opts
49 | end
50 |
51 | def get_internal_ip
52 | ifc = %x{ifconfig #{@options[:iface]}}
53 | if ifc.each_line.grep(/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/)[0] == nil then
54 | iip = "none"
55 | else
56 | iip = ifc.each_line.grep(/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/)[0].strip.split(" ")[1]
57 | end
58 | return iip
59 | end
60 |
61 | def get_external_ip
62 | begin
63 | return %x{dig +short myip.opendns.com @resolver1.opendns.com}.strip
64 | rescue
65 | return "none"
66 | end
67 | end
68 |
69 | def get_access_point
70 | ap = %x{#{Net_Stats::AIRPORT_UTILITY} -I | awk -F':' '/ SSID/ { print $2 }'}
71 | if ap.to_s == "" then
72 | return "none"
73 | else
74 | return ap.to_s.strip
75 | end
76 | #ap.to_s == "" ? return "none" : return ap
77 | end
78 |
79 | def get_response_time
80 | begin
81 | return %x{ping -c 1 -t 2 -Q #{@options[:server]}}.each_line.grep(/round-trip/)[0].strip.split(" = ")[1].split("/")[2].to_f.round.to_s + "ms"
82 | rescue
83 | return "No Network"
84 | end
85 | end
86 |
87 | def get_txrx_totals
88 | rx = %x{netstat -I #{@options[:iface]} -b | grep -e "#{@options[:iface]}" -m 1 | awk '{print $7}'}.to_i
89 | tx = %x{netstat -I #{@options[:iface]} -b | grep -e "#{@options[:iface]}" -m 1 | awk '{print $10}'}.to_i
90 | return self.human_readable_bytes(tx) + " : " + self.human_readable_bytes(rx)
91 | end
92 |
93 | def human_readable_bytes(bytes)
94 | level = 0
95 | until bytes < 1024
96 | remainder = bytes % 1024
97 | bytes = bytes / 1024
98 | level += 1
99 | end
100 | remainder = ((remainder.to_f / 1024) * 100).to_i
101 | output = bytes.to_s + "." + remainder.to_s
102 | case level
103 | when 0
104 | output = output + " B"
105 | when 1
106 | output = output + " KB"
107 | when 2
108 | output = output + " MB"
109 | when 3
110 | output = output + " GB"
111 | when 4
112 | output = output + " TB"
113 | end
114 | end
115 | end
116 |
117 | netstats = Net_Stats.new(options)
118 |
119 | iface = options[:iface]
120 | ping_server = options[:server]
121 |
122 | internal_ip = netstats.get_internal_ip
123 | external_ip = netstats.get_external_ip
124 | txrx = netstats.get_txrx_totals
125 | if options[:wifi] then
126 | access_point = netstats.get_access_point
127 | else
128 | access_point = "none"
129 | end
130 | if external_ip == "none" then
131 | ping_time = "No network"
132 | else
133 | if options[:ping] then
134 | ping_time = netstats.get_response_time
135 | else
136 | ping_time = 'disabled'
137 | end
138 | end
139 |
140 | if options[:html] then
141 | output =
142 | <<-EOS
143 | Internal IP : #{internal_ip}
144 | External IP : #{external_ip}
145 | Interface : #{iface}
146 | TX:RX : #{txrx}
147 | Access Point : #{access_point}
148 | Ping Time : #{ping_time} (#{ping_server})
149 | EOS
150 | else
151 | output =
152 | <<-EOS
153 | Internal IP : #{internal_ip}
154 | External IP : #{external_ip}
155 | Interface : #{iface}
156 | TX:RX : #{txrx}
157 | Access Point : #{access_point}
158 | Ping Time : #{ping_time} (#{ping_server})
159 | EOS
160 | end
161 | puts output
162 |
--------------------------------------------------------------------------------
/btbattery.rb:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | # include option parsing library
3 | require 'optparse'
4 | options = {}
5 |
6 | # grab command line arguments
7 | parser = OptionParser.new do |opts|
8 | opts.banner = 'Usage: battery.rb [options]'
9 |
10 | options[:color] = false
11 | opts.on('-c', '--color', 'Display battery meter with color') do
12 | options[:color] = true
13 | end
14 |
15 | options[:size] = 'small'
16 | opts.on('-s SIZE', '--size SIZE', %i[small big bigger], 'Size (small, big, bigger) of battery meter') do |size|
17 | options[:size] = size
18 | end
19 |
20 | options[:cell] = '❚'
21 | opts.on('-l CELL', '--cell CELL', 'The character to use for each battery cell') do |cell|
22 | options[:cell] = cell
23 | end
24 |
25 | options[:html] = false
26 | opts.on('-H', '--html', 'Out put HTML color codes instead of shell') do
27 | options[:html] = true
28 | end
29 |
30 | options[:map] = false
31 | opts.on('-m MAP', '--map MAP',
32 | 'Key:Value mapping of device names to display names, separated by a semicolon (;)' \
33 | ' [Magic Keyboard with Numeric Keypad:Keyboard]') do |map|
34 | options[:map] = map
35 | end
36 |
37 | options[:separator] = "\n"
38 | opts.on('-S SEPARATOR', '--separator SEPARATOR',
39 | 'Split multiple batteries by this string (default \'\n\')') do |separator|
40 | options[:separator] = separator
41 | end
42 |
43 | opts.on('-h', '--help', 'Displays this help screen') do
44 | puts opts
45 | exit
46 | end
47 | end
48 |
49 | parser.parse!
50 |
51 | class Battery
52 | # gather relevant info
53 | def initialize(opts)
54 | @options = opts
55 | @options[:separator] = '
' if @options[:html] && @options[:separator] == "\n"
56 | if @options[:map]
57 | @map = {}
58 | @options[:map].split(';').each do |device|
59 | @map[device.split(':')[0]] = device.split(':')[1]
60 | end
61 | end
62 | @devices = `ioreg -c AppleDeviceManagementHIDEventService -r`.split("\n\n")
63 | end
64 |
65 | def build_meter(device, color)
66 | percent = @devices[device].match(/BatteryPercent" = (\d+)/)[1].to_i
67 | meter = ''
68 | # case size
69 | if @options[:size].to_s == 'small'
70 | blength = 10
71 | bpercent = 10
72 | bred = 1
73 | byellow = 3
74 | bgreen = 10
75 | elsif @options[:size].to_s == 'big'
76 | blength = 20
77 | bpercent = 5
78 | bred = 2
79 | byellow = 6
80 | bgreen = 20
81 | else
82 | blength = 50
83 | bpercent = 2
84 | bred = 5
85 | byellow = 15
86 | bgreen = 50
87 | end
88 |
89 | if color
90 | if @options[:html]
91 | red = ""
92 | yellow = ""
93 | green = ""
94 | clear = ''
95 | else
96 | red = "\e[31m"
97 | yellow = "\e[33m"
98 | green = "\e[32m"
99 | clear = "\e[0m"
100 | end
101 | else
102 | red = ''
103 | yellow = ''
104 | green = ''
105 | clear = ''
106 | end
107 |
108 | (1..blength).each do |i|
109 | if percent >= bpercent
110 | i <= bred ? meter << red : nil # first 2 bars red
111 | i <= byellow && i > bred ? meter << yellow : nil # next 3 bars yellow
112 | i <= bgreen && i > byellow ? meter << green : nil # remaining 5 green
113 | meter << @options[:cell] + clear # clear color
114 | else
115 | meter << '·' # empty
116 | end
117 | percent -= bpercent # decrement percentage for next loop
118 | end
119 | meter += "#{percent + 100}%"
120 | meter + clear
121 | end
122 |
123 | def build_identifier(device)
124 | product = @devices[device].match(/Product" = "(.*)"/)
125 | address = @devices[device].match(/DeviceAddress" = "(.*)"/)
126 | id = product && product[1] || address && address[1] || 'Unknown'
127 | id = @map[id].to_s if @map && @map[id]
128 | "#{id}: "
129 | end
130 |
131 | def build_time(device)
132 | bat_time = ''
133 | if @devices[device].match(/BatteryStatusFlags" = (\d+)/)[1] == '3'
134 | bat_time = if @devices[device].match(/BatteryPercent" = (\d+)/)[1] == '100'
135 | ' (Charged)'
136 | else
137 | ' (Charging)'
138 | end
139 | end
140 |
141 | bat_time
142 | end
143 |
144 | def display_meters
145 | meters = []
146 | (0..@devices.length - 1).each do |i|
147 | meters.append(build_identifier(i) + build_meter(i, @options[:color]) + build_time(i).to_s)
148 | end
149 | meters.sort.join(@options[:separator])
150 | end
151 | end
152 |
153 | battery = Battery.new(options)
154 |
155 | puts battery.display_meters
156 |
--------------------------------------------------------------------------------
/battery.rb:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | #coding: utf-8
3 |
4 | # include option parsing library
5 | require 'optparse'
6 | options = {}
7 |
8 | # grab command line arguments
9 | parser = OptionParser.new do |opts|
10 | opts.banner = "Usage: battery.rb [options]"
11 |
12 | options[:color] = false
13 | opts.on( '-c', '--color', 'Display battery meter with color' ) do
14 | options[:color] = true
15 | end
16 |
17 | options[:size] = "small"
18 | opts.on( '-s SIZE', '--size SIZE', [:small, :big, :bigger], 'Size (small, big, bigger) of battery meter') do |size|
19 | options[:size] = size
20 | end
21 |
22 | options[:cell] = "❚"
23 | opts.on( '-l CELL', '--cell CELL', 'The character to use for each battery cell' ) do |cell|
24 | options[:cell] = cell
25 | end
26 |
27 | options[:html] = false
28 | opts.on( '-H', '--html', 'Out put HTML color codes instead of shell' ) do
29 | options[:html] = true
30 | end
31 |
32 | opts.on( '-h', '--help', 'Displays this help screen' ) do
33 | puts opts
34 | exit
35 | end
36 | end
37 |
38 | parser.parse!
39 |
40 | class Battery
41 | def initialize(opts) # gather relevant info
42 | @options = opts
43 | @conn = `ioreg -n AppleSmartBattery | grep ExternalConnected | awk '/ "ExternalConnected" / { print $NF }'` # is power connected
44 | @chrg = `ioreg -n AppleSmartBattery | grep IsCharging | awk '{ print $NF }'` # is battery chargin
45 | @time = `ioreg -n AppleSmartBattery | grep TimeRemaining | awk '{ print $NF }'` # time remaining on battery
46 | @max = `ioreg -n AppleSmartBattery | grep MaxCapacity | awk '/ "MaxCapacity" /{ print $NF }'` # maximum capacity
47 | @cur = `ioreg -n AppleSmartBattery | grep CurrentCapacity | awk '{ print $NF }'` # current capacity
48 | end # def initialize
49 |
50 | def build_meter(color) # built battery meter
51 | percent = self.build_percent # get capacity percentage
52 | # case size
53 | #puts @options[:size]
54 | if @options[:size].to_s == "small" then
55 | blength = 10
56 | bpercent = 10
57 | bred = 1
58 | byellow = 3
59 | bgreen = 10
60 | elsif @options[:size].to_s == "big" then
61 | blength = 20
62 | bpercent = 5
63 | bred = 2
64 | byellow = 6
65 | bgreen = 20
66 | else
67 | blength = 50
68 | bpercent = 2
69 | bred = 5
70 | byellow = 15
71 | bgreen = 50
72 | end
73 |
74 | if color then
75 | if @options[:html] then
76 | red = ""
77 | yellow = ""
78 | green = ""
79 | clear = ""
80 | else
81 | red = "\e[31m"
82 | yellow = "\e[33m"
83 | green = "\e[32m"
84 | clear = "\e[0m"
85 | end
86 | else
87 | red = ""
88 | yellow = ""
89 | green = ""
90 | clear = ""
91 | end
92 | meter = ""
93 |
94 | for i in (1..blength) # one bar per 10% battery, dashes for each empty 10%
95 | if percent >= bpercent then
96 | i <= bred ? meter << red : nil # first 2 bars red
97 | i <= byellow && i > bred ? meter << yellow : nil # next 3 bars yellow
98 | i <= bgreen && i > byellow ? meter << green : nil # remaining 5 green
99 | meter << @options[:cell] + clear # clear color
100 | else
101 | meter << "·" # empty
102 | end # if percent >= 10
103 | percent -= bpercent # decrement percentage for next loop
104 | end # for i in (1..10)
105 | return meter + clear
106 | end # def build_meter
107 |
108 | def build_time # determines time remaining on battery
109 | hour = @time.strip.to_i / 60 # hours left
110 | min = @time.strip.to_i - (hour * 60) # minutes left
111 | min < 10 ? min = "0#{min}" : nil # make sure minutes is two digits long
112 |
113 | if @conn.strip == "Yes" then # power cable connected
114 | if @chrg.strip == "Yes" then # is plugged in and charging
115 | batTime = "Charging: #{hour}:#{min}"
116 | else # is plugged in but not charging
117 | self.build_percent == 100 ? batTime = "Charged" : batTime = "Not Charging"
118 | end # if @chrg.strip == "Yes"
119 | else # power is not connected
120 | if @time.to_i < 1 || @time.to_i > 2000 then
121 | batTime = "Calculating"
122 | else
123 | batTime = "#{hour}:#{min}"
124 | end # if @time < 1 || @ time > 2000
125 | end # if @conn.strip == "Yes"
126 |
127 | return batTime
128 | end # def build_time
129 |
130 | def build_percent # returns percentage of battery remaining
131 | return (@cur.to_f / @max.to_f * 100).round.to_i
132 | end # def build_percent
133 | end # Class Battery
134 |
135 | battery = Battery.new(options)
136 |
137 | puts battery.build_meter(options[:color]) + ' ' + battery.build_percent.to_s + '% (' + battery.build_time.to_s + ')'
138 |
--------------------------------------------------------------------------------
/calendar.rb:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | #coding: utf-8
3 |
4 | require 'optparse'
5 | require 'date'
6 | require 'htmlentities'
7 |
8 | options = {}
9 |
10 | # grab command line arguments
11 | parser = OptionParser.new do |opts|
12 | opts.banner = 'Usage: calendar.rb [options]'
13 |
14 | options[:vertical] = false
15 | opts.on( '-v', '--vertical', 'Orients the calendar vertically instead of horizontally') do
16 | options[:vertical] = true
17 | end
18 |
19 | options[:indicator] = '◆◆'
20 | opts.on( '-i INDICATOR', '--indicator INDICATOR', 'The string used to denote which day it currently is on the separator (should be 2 characters)') do |indicator|
21 | options[:indicator] = indicator
22 | end
23 |
24 | options[:colorize] = false
25 | opts.on( '-z', '--colorize', 'indicate the current day with color') do
26 | options[:colorize] = true
27 | end
28 |
29 | options[:color] = 'green'
30 | opts.on( '-c COLOR', '--color COLOR', [:black, :red, :green, :yellow, :blue, :magenta, :cyan, :white], 'Sets the color to use as the current day marker (black, red, green, yellow, blue, magenta, cyan, white)') do |color|
31 | options[:color] = color
32 | end
33 |
34 | options[:hicolor] = false
35 | opts.on( '-C', '--hicolor', 'Uses the hicolor ASCII value for the chose color') do
36 | options[:hicolor] = true
37 | end
38 |
39 | options[:colordate] = false
40 | opts.on( '-t', '--colordate', 'Use color to mark the date (01, 02, 03)') do
41 | options[:colordate] = true
42 | end
43 |
44 | options[:colorday] = false
45 | opts.on( '-d', '--colorday', 'Use color to mark the day (Mo, Tu, We)') do
46 | options[:colorday] = true
47 | end
48 |
49 | options[:noseparator] = false
50 | opts.on( '-S', '--noseparator', 'Do not output the separator line between days and dates') do
51 | options[:noseparator] = true
52 | end
53 |
54 | options[:html] = false
55 | opts.on( '-H', '--html', 'Output HTML color codes instead of shell - requires HTMLEntities gem') do
56 | options[:html] = true
57 | end
58 |
59 | opts.on( '-h', '--help', 'Displays this help dialogue' ) do
60 | puts opts
61 | exit
62 | end
63 | end
64 |
65 | parser.parse!
66 |
67 | encoder = HTMLEntities.new
68 |
69 | if options[:html] then
70 | options[:indicator] = encoder.encode(options[:indicator], :named)
71 | end
72 |
73 | class Line_Calendar
74 | # set up some constants for use in throughout the script
75 | SEPARATOR_STRING_A = " " # the string used to separate days and dates
76 | SEPARATOR_STRING_B = "··" # the string used between seperators
77 | SEPARATOR_STRING_C = "··" # the separator string
78 | END_COLOR = "\e[0m" # this string ends color output
79 | END_HTML_COLOR = ""
80 | HI_COLOR = "\e[1m" # this string denotes bold color
81 | ABBR_DAYNAMES = {0 => 'Su', 1 => 'Mo', 2 => 'Tu', 3 => 'We', 4 => 'Th', 5 => 'Fr', 6 => 'Sa'} # map of abbreviated day names to matching index for date functions
82 | # hash of the different colors available as ASCII output
83 | COLORS = {'black' => "\e[30m",
84 | 'red' => "\e[31m",
85 | 'green' => "\e[32m",
86 | 'yellow' => "\e[33m",
87 | 'blue' => "\e[34m",
88 | 'magenta' => "\e[35m",
89 | 'cyan' => "\e[36m",
90 | 'white' => "\e[37m"
91 | }
92 | HTML_COLORS = {'black' => "",
93 | 'red' => "",
94 | 'green' => "",
95 | 'yellow' => "",
96 | 'blue' => "",
97 | 'magenta' => "",
98 | 'cyan' => "",
99 | 'white' => ""
100 | }
101 |
102 | def initialize(opts)
103 | @options = opts
104 | end
105 |
106 | # returns intiger with number of days in the month (28, 29, 30, 31)
107 | def days_in_month(year, month)
108 | return (Date.new(year, 12, 31) << (12 - month)).day
109 | end
110 |
111 | # returns what day of the month it is (1-31)
112 | def day_in_month(year, month, day)
113 | return Date.new(year, month, day).wday
114 | end
115 |
116 | # returns an array of days in the month (Mo, Tu, We, etc.)
117 | def build_day_array(year, month)
118 | day_array = Array.new
119 | # cycle through number of days in the month and build an array with one entry per day
120 | for d in (1..self.days_in_month(year, month))
121 | day_array[d] = Line_Calendar::ABBR_DAYNAMES[self.day_in_month(year, month, d)] # populates array with abbreviated daynames
122 | end
123 | # remove the 0 entry and move everything up one
124 | day_array.shift
125 | return day_array
126 | end
127 |
128 | # builds the separator line between the days and dates
129 | def build_separator(year, month)
130 | separator = Array.new
131 | # cycle through days in month
132 | for d in (1..self.days_in_month(year, month))
133 | # does this match today?
134 | if year == Time.now.year && month == Time.now.month && d == Time.now.day then
135 | separator[d.to_i] = @options[:indicator]
136 | else
137 | # append separator to the array
138 | separator[d.to_i] = Line_Calendar::SEPARATOR_STRING_B
139 | end
140 | end
141 | # trim 0 key and move everything up one
142 | separator.shift
143 | return separator
144 | end
145 |
146 | # build array of dates (1-31)
147 | def build_date_array(year, month)
148 | date_array = Array.new
149 | # cycle through days in month creating one key in the array for each day
150 | for d in (1..self.days_in_month(year, month))
151 | if d.to_i < 10 then
152 | # if date is 1-9 make sure it is 01-09
153 | d = "0#{d}"
154 | end
155 | date_array[d.to_i] = d
156 | end
157 | # remove 0 key for 1 to 1 mapping in array
158 | date_array.shift
159 | return date_array
160 | end
161 |
162 | # build array vertically instead of horizontally
163 | def build_vertical_array(year, month)
164 | # pull in arrays of days and dates
165 | dates = self.build_date_array(Time.now.year, Time.now.month)
166 | days = self.build_day_array(Time.now.year, Time.now.month)
167 |
168 | # zip the two arrays so we have the following single array to work with
169 | # [['Mo', '01'], ['Tu', '02']]
170 | vertical = days.zip(dates)
171 |
172 | return vertical
173 | end
174 |
175 | def colorize_days(days)
176 | # implement method to make the day (Mo, Tu, We) colorized
177 | count = 1
178 | days.each do |d|
179 | if Time.now.day == count then
180 | if @options[:html] then
181 | days[count -1] = Line_Calendar::HTML_COLORS[@options[:color].to_s] + days[count -1] + Line_Calendar::END_HTML_COLOR
182 | else
183 | days[count -1] = Line_Calendar::COLORS[@options[:color].to_s] + days[count -1] + Line_Calendar::END_COLOR
184 | end
185 | end
186 | count += 1
187 | end
188 | return days
189 | end
190 |
191 | def colorize_separator(sep) # add color to the separator day indicator
192 | count = 1 # seed to keep track of where we are in the array
193 | sep.each do |s|
194 | # if it's today, add color and replace string in array
195 | if Time.now.day == count then
196 | if @options[:html] then
197 | sep[count -1] = Line_Calendar::HTML_COLORS[@options[:color].to_s] + @options[:indicator] + Line_Calendar::END_HTML_COLOR
198 | else
199 | sep[count -1] = Line_Calendar::COLORS[@options[:color].to_s] + @options[:indicator] + Line_Calendar::END_COLOR
200 | end
201 | end
202 | # increment counter
203 | count += 1
204 | # loop de loop until finished
205 | end
206 | # return new array with colorized strings added
207 | return sep
208 | end
209 |
210 | def colorize_date(dates)
211 | # implement method to make the date (01, 02, 03) colorized
212 | count = 1
213 | dates.each do |d|
214 | if Time.now.day == count then
215 | if @options[:html] then
216 | dates[count -1] = Line_Calendar::HTML_COLORS[@options[:color].to_s] + dates[count -1].to_s + Line_Calendar::END_HTML_COLOR
217 | else
218 | dates[count -1] = Line_Calendar::COLORS[@options[:color].to_s] + dates[count -1].to_s + Line_Calendar::END_COLOR
219 | end
220 | end
221 | count += 1
222 | end
223 | return dates
224 | end
225 | end
226 |
227 | cal = Line_Calendar.new(options) # pass command line args to object
228 | year = Time.now.year # current year
229 | month = Time.now.month # current month
230 |
231 | # print out vertically
232 | if options[:vertical] then
233 | # build and grab relevant information in a hash ( Mo => 01, Tu => 02 )
234 | varray = cal.build_vertical_array(year, month)
235 | # foreach entry in array
236 | varray.each do |d|
237 | # if no separator was requested, don't print one
238 | if options[:noseparator] then
239 | # each hash pair printed out separated by spaces
240 | puts d[0].to_s +encoder.decode(Line_Calendar::SEPARATOR_STRING_A)+ d[1].to_s
241 | puts "
" if options[:html]
242 | elsif Time.now.year == year && Time.now.month == month && d[1].to_i == Time.now.day then
243 | # is it today?
244 | if options[:colorize] then
245 | # add color and indicator if requested
246 | if options[:html] then
247 | puts d[0].to_s + encoder.decode(Line_Calendar::SEPARATOR_STRING_A) + Line_Calendar::HTML_COLORS[options[:color].to_s] + options[:indicator] + Line_Calendar::END_HTML_COLOR + encoder.decode(Line_Calendar::SEPARATOR_STRING_A) + d[1].to_s
248 | else
249 | puts d[0].to_s + encoder.decode(Line_Calendar::SEPARATOR_STRING_A) + Line_Calendar::COLORS[options[:color].to_s] + options[:indicator] + Line_Calendar::END_COLOR + encoder.decode(Line_Calendar::SEPARATOR_STRING_A) + d[1].to_s
250 | end
251 | puts "
" if options[:html]
252 | else
253 | # otherwise just add indicator
254 | puts d[0].to_s + encoder.decode(Line_Calendar::SEPARATOR_STRING_A) + options[:indicator] + encoder.decode(Line_Calendar::SEPARATOR_STRING_A) + d[1].to_s
255 | puts "
" if options[:html]
256 | end
257 | else
258 | # not today, no indication required
259 | puts d[0].to_s + encoder.decode(Line_Calendar::SEPARATOR_STRING_A) + Line_Calendar::SEPARATOR_STRING_C + encoder.decode(Line_Calendar::SEPARATOR_STRING_A) + d[1].to_s
260 | puts "
" if options[:html]
261 | end
262 | end
263 | else
264 | # print out horizontally
265 |
266 | # each day (Mo, Tu, We) separated by spaces
267 | if options[:colorday] then # add color indicating day
268 | puts cal.colorize_days(cal.build_day_array(year, month)) * encoder.decode(Line_Calendar::SEPARATOR_STRING_A)
269 | puts "
" if options[:html]
270 | else
271 | # no color, just output days
272 | puts cal.build_day_array(year, month) * encoder.decode(Line_Calendar::SEPARATOR_STRING_A)
273 | puts "
" if options[:html]
274 | end
275 |
276 | # don't print separator if option set
277 | unless options[:noseparator] then
278 | # add color if requested
279 | if options[:colorize] then
280 | puts cal.colorize_separator(cal.build_separator(year, month)) * Line_Calendar::SEPARATOR_STRING_C
281 | puts "
" if options[:html]
282 | else
283 | # plain separator with no color
284 | puts cal.build_separator(year, month) * Line_Calendar::SEPARATOR_STRING_C
285 | puts "
" if options[:html]
286 | end
287 | end
288 |
289 | # each date (01, 02, 03) separated by spaces
290 | if options[:colordate] then # add color indicating date
291 | puts cal.colorize_date(cal.build_date_array(year, month)) * encoder.decode(Line_Calendar::SEPARATOR_STRING_A)
292 | puts "
" if options[:html]
293 | else # no color, just output dates
294 | puts cal.build_date_array(year, month) * encoder.decode(Line_Calendar::SEPARATOR_STRING_A)
295 | puts "
" if options[:html]
296 | end
297 | end
298 |
--------------------------------------------------------------------------------