hardstatus 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +116 -0
- data/Rakefile +5 -0
- data/bin/hardstatus-daemon +17 -0
- data/ext/hardstatus.c +51 -0
- data/hardstatus.gemspec +17 -0
- data/lib/hardstatus.rb +93 -0
- data/lib/hardstatus/controller.rb +33 -0
- data/lib/hardstatus/time.rb +61 -0
- metadata +79 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 573b9cf310275c4edd2fc8e5f68ac1f3e1bb96d7
|
4
|
+
data.tar.gz: 7a6bc21f0b9b9b3e93b4b6e16ce72bdfd5484c73
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 73706e6604dd64f6e9b9771d54ff511d3995c4014ca360edd1227f96e873c9bcba54fa3d1016f48c851ade6abf12a53caebce7ca5b229f562550475b0b19e333
|
7
|
+
data.tar.gz: 3f43737450231c0c0504f9e6578ad360f86a5915c0626fb9f2e1ecd2d20a19e79db97b2df16527aba34a30c5789e7fe530193588c307eef1f894e4b0ec3592f7
|
data/README.md
ADDED
@@ -0,0 +1,116 @@
|
|
1
|
+
hardstatus
|
2
|
+
==========
|
3
|
+
I use the GNU screen hardstatus as global status bar, the downside was I had
|
4
|
+
about 10 scripts that would make the whole thing lag every few seconds.
|
5
|
+
|
6
|
+
This solves the problem.
|
7
|
+
|
8
|
+
Install
|
9
|
+
-------
|
10
|
+
Just install the gem and build the binary helper by running `rake`, it will
|
11
|
+
put it in `bin/hardstatus`, you can them move it in your PATH and call it as
|
12
|
+
backtick in the hardstatus.
|
13
|
+
|
14
|
+
Assuming you renamed the binary to `hs`.
|
15
|
+
|
16
|
+
```
|
17
|
+
backtick 1 1 1 hs right
|
18
|
+
```
|
19
|
+
|
20
|
+
This will define a right backtick, you have then to hadd the backtick to the
|
21
|
+
hardstatus, supposedly on the right.
|
22
|
+
|
23
|
+
You can have both left and right templates in the configuration.
|
24
|
+
|
25
|
+
Example
|
26
|
+
-------
|
27
|
+
|
28
|
+
```ruby
|
29
|
+
right '#{irssi}#{email}#{hackers}#{processor}#{temperature}#{wireless}#{battery}'
|
30
|
+
|
31
|
+
def wrap (string)
|
32
|
+
"\005{= r}[\005{+b W}#{string}\005{= dr}] "
|
33
|
+
end
|
34
|
+
|
35
|
+
backtick :irssi, every: 1.second do
|
36
|
+
notifications = File.read(File.expand_path('~/.irssi/notifications')).gsub(':', '@').split(/, /)
|
37
|
+
|
38
|
+
unless notifications.empty?
|
39
|
+
wrap "IRC\005{-b r}|" + notifications.map {|n|
|
40
|
+
"\005{+b rW}#{n}\005{-b dd}"
|
41
|
+
}.join(' ')
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
require 'json'
|
46
|
+
require 'socket'
|
47
|
+
require 'timeout'
|
48
|
+
|
49
|
+
backtick :email, every: 3.second do
|
50
|
+
socket = TCPSocket.new('localhost', '9001')
|
51
|
+
socket.puts '* list unread'
|
52
|
+
|
53
|
+
notifications = JSON.parse(socket.gets)
|
54
|
+
|
55
|
+
unless notifications.empty?
|
56
|
+
wrap "Mail\005{-b r}|" + notifications.map {|name|
|
57
|
+
"\005{+b rW}#{name}\005{-b dd}"
|
58
|
+
}.join(' ')
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
backtick :hackers, every: 5.seconds do
|
63
|
+
end
|
64
|
+
|
65
|
+
backtick :processor, every: 5.seconds do
|
66
|
+
wrap `(cpupower -c 0 frequency-info; cpupower -c 1 frequency-info) |
|
67
|
+
grep "current CPU" |
|
68
|
+
head -n 1 |
|
69
|
+
sed 's/^.*is //' |
|
70
|
+
sed 's/\.$//' |
|
71
|
+
tr -d '\n'`
|
72
|
+
end
|
73
|
+
|
74
|
+
backtick :temperature, every: 5.seconds do
|
75
|
+
`sensors`.match(/temp1:\s+([\d+\-.]+)/) { |m|
|
76
|
+
wrap(if m.to_i > 100
|
77
|
+
'STACCA STACCA STACC-'
|
78
|
+
else
|
79
|
+
"#{m} C"
|
80
|
+
end)
|
81
|
+
}
|
82
|
+
end
|
83
|
+
|
84
|
+
backtick :wireless, every: 5.seconds do
|
85
|
+
state = `iwconfig wlan0`
|
86
|
+
|
87
|
+
next if state =~ /No such device/
|
88
|
+
|
89
|
+
essid = state.match(/ESSID:"(.*?)"/)[1]
|
90
|
+
quality = state.match(/Quality=(.*?) /)[1]
|
91
|
+
|
92
|
+
if quality
|
93
|
+
wrap "#{essid}\005{-b r}|\005{+b W}#{quality}"
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
backtick :battery, every: 5.seconds do
|
98
|
+
state = `acpitool -B`
|
99
|
+
|
100
|
+
next if state =~ /100\.0%/
|
101
|
+
|
102
|
+
current = state.match(/([^\s]+%.*)$/)[1].sub(/, /, "\005{-b r}|\005{+b W}")
|
103
|
+
|
104
|
+
if state.match(/discharging/)
|
105
|
+
wrap "v|\005{+b W}#{current}"
|
106
|
+
else
|
107
|
+
wrap "^\005{-b r}|\005{+b W}#{current}"
|
108
|
+
end
|
109
|
+
end
|
110
|
+
```
|
111
|
+
|
112
|
+
Why in the world would you do that?
|
113
|
+
-----------------------------------
|
114
|
+
Because life is too easy, and tmux handling of windows isn't compatible with my
|
115
|
+
workflow, so I have to deal with the shittiness of GNU screen and this makes it
|
116
|
+
both usable and useful to my end.
|
data/Rakefile
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
require 'hardstatus'
|
3
|
+
|
4
|
+
fail 'no configuration file passed' if ARGV.empty?
|
5
|
+
|
6
|
+
EM.run {
|
7
|
+
hardstatus = Hardstatus.load(*ARGV)
|
8
|
+
hardstatus.start
|
9
|
+
|
10
|
+
%w[TERM INT HUP].each {|sig|
|
11
|
+
trap sig do
|
12
|
+
hardstatus.stop
|
13
|
+
|
14
|
+
EM.stop_event_loop
|
15
|
+
end
|
16
|
+
}
|
17
|
+
}
|
data/ext/hardstatus.c
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
#include <sys/socket.h>
|
2
|
+
#include <sys/un.h>
|
3
|
+
#include <stdio.h>
|
4
|
+
#include <stdlib.h>
|
5
|
+
#include <unistd.h>
|
6
|
+
#include <string.h>
|
7
|
+
#include <wordexp.h>
|
8
|
+
|
9
|
+
int
|
10
|
+
main (int argc, char* argv[])
|
11
|
+
{
|
12
|
+
struct sockaddr_un addr;
|
13
|
+
char buf[4096] = {0};
|
14
|
+
int fd;
|
15
|
+
char* path;
|
16
|
+
char* command;
|
17
|
+
|
18
|
+
if (argc == 2) {
|
19
|
+
wordexp_t p;
|
20
|
+
wordexp("$HOME/.hardstatus.ctl", &p, 0);
|
21
|
+
|
22
|
+
path = p.we_wordv[0];
|
23
|
+
command = argv[1];
|
24
|
+
}
|
25
|
+
else if (argc == 3) {
|
26
|
+
path = argv[1];
|
27
|
+
command = argv[2];
|
28
|
+
}
|
29
|
+
|
30
|
+
if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
|
31
|
+
perror("socket error");
|
32
|
+
exit(-1);
|
33
|
+
}
|
34
|
+
|
35
|
+
memset(&addr, 0, sizeof(addr));
|
36
|
+
addr.sun_family = AF_UNIX;
|
37
|
+
strncpy(addr.sun_path, path, sizeof(addr.sun_path)-1);
|
38
|
+
|
39
|
+
if (connect(fd, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
|
40
|
+
perror("connect error");
|
41
|
+
exit(-1);
|
42
|
+
}
|
43
|
+
|
44
|
+
send(fd, command, strlen(command), 0);
|
45
|
+
send(fd, "\r\n", 2, 0);
|
46
|
+
|
47
|
+
recv(fd, buf, 4096, 0);
|
48
|
+
printf("%s", buf);
|
49
|
+
|
50
|
+
return 0;
|
51
|
+
}
|
data/hardstatus.gemspec
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
Gem::Specification.new {|s|
|
2
|
+
s.name = 'hardstatus'
|
3
|
+
s.version = '0.0.1'
|
4
|
+
s.author = 'meh.'
|
5
|
+
s.email = 'meh@schizofreni.co'
|
6
|
+
s.homepage = 'http://github.com/meh/hardstatus'
|
7
|
+
s.platform = Gem::Platform::RUBY
|
8
|
+
s.summary = 'Hardstatus helpers for screen, because tmux just does not cut it for me.'
|
9
|
+
|
10
|
+
s.files = `git ls-files`.split("\n")
|
11
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
|
12
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
13
|
+
s.require_paths = ['lib']
|
14
|
+
|
15
|
+
s.add_runtime_dependency 'eventmachine'
|
16
|
+
s.add_runtime_dependency 'thread'
|
17
|
+
}
|
data/lib/hardstatus.rb
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
#--
|
2
|
+
# DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
3
|
+
# Version 2, December 2004
|
4
|
+
#
|
5
|
+
# DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
6
|
+
# TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
7
|
+
#
|
8
|
+
# 0. You just DO WHAT THE FUCK YOU WANT TO.
|
9
|
+
#++
|
10
|
+
|
11
|
+
require 'thread/every'
|
12
|
+
require 'eventmachine'
|
13
|
+
|
14
|
+
require 'hardstatus/time'
|
15
|
+
require 'hardstatus/controller'
|
16
|
+
|
17
|
+
class Hardstatus
|
18
|
+
def self.load (path)
|
19
|
+
Hardstatus.new.load(path)
|
20
|
+
end
|
21
|
+
|
22
|
+
attr_reader :right, :left
|
23
|
+
|
24
|
+
def initialize
|
25
|
+
@backticks = {}
|
26
|
+
@controller = File.expand_path('~/.hardstatus.ctl')
|
27
|
+
end
|
28
|
+
|
29
|
+
def load (path = nil, &block)
|
30
|
+
if path
|
31
|
+
instance_eval File.read(File.expand_path(path)), path, 1
|
32
|
+
else
|
33
|
+
instance_exec(&block)
|
34
|
+
end
|
35
|
+
|
36
|
+
self
|
37
|
+
end
|
38
|
+
|
39
|
+
def start
|
40
|
+
return if started?
|
41
|
+
|
42
|
+
@started = true
|
43
|
+
|
44
|
+
File.umask(0).tap {|old|
|
45
|
+
begin
|
46
|
+
@signature = EM.start_server(@controller, Controller, self)
|
47
|
+
ensure
|
48
|
+
File.umask(old)
|
49
|
+
end
|
50
|
+
}
|
51
|
+
end
|
52
|
+
|
53
|
+
def started?
|
54
|
+
@started
|
55
|
+
end
|
56
|
+
|
57
|
+
def stop
|
58
|
+
return unless started?
|
59
|
+
|
60
|
+
if @signature
|
61
|
+
EM.stop_server @signature
|
62
|
+
end
|
63
|
+
|
64
|
+
@started = false
|
65
|
+
end
|
66
|
+
|
67
|
+
def controller (path)
|
68
|
+
@controller = path
|
69
|
+
end
|
70
|
+
|
71
|
+
def right (template)
|
72
|
+
@right = template
|
73
|
+
end
|
74
|
+
|
75
|
+
def left (template)
|
76
|
+
@left = template
|
77
|
+
end
|
78
|
+
|
79
|
+
def backtick (name, options = {}, &block)
|
80
|
+
@backticks[name] = Thread.every(options[:every] || 1, &block)
|
81
|
+
end
|
82
|
+
|
83
|
+
def render (side)
|
84
|
+
template = case side
|
85
|
+
when :left then @left || ""
|
86
|
+
when :right then @right || ""
|
87
|
+
end
|
88
|
+
|
89
|
+
template.gsub(/\#{.*?}/) { |m|
|
90
|
+
@backticks[m.match(/\#{(.*?)}/)[1].to_sym].value!.to_s
|
91
|
+
}
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
#--
|
2
|
+
# DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
3
|
+
# Version 2, December 2004
|
4
|
+
#
|
5
|
+
# DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
6
|
+
# TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
7
|
+
#
|
8
|
+
# 0. You just DO WHAT THE FUCK YOU WANT TO.
|
9
|
+
#++
|
10
|
+
|
11
|
+
class Hardstatus
|
12
|
+
|
13
|
+
class Controller < EventMachine::Protocols::LineAndTextProtocol
|
14
|
+
def initialize (hardstatus)
|
15
|
+
super
|
16
|
+
|
17
|
+
@hardstatus = hardstatus
|
18
|
+
end
|
19
|
+
|
20
|
+
def receive_line (line)
|
21
|
+
send_line @hardstatus.render(line.strip.to_sym)
|
22
|
+
|
23
|
+
close_connection_after_writing
|
24
|
+
end
|
25
|
+
|
26
|
+
def send_line (line)
|
27
|
+
raise ArgumentError, 'the line already has a newline character' if line.include? "\n"
|
28
|
+
|
29
|
+
send_data line.dup.force_encoding('BINARY') << "\r\n"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
#--
|
2
|
+
# DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
3
|
+
# Version 2, December 2004
|
4
|
+
#
|
5
|
+
# DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
6
|
+
# TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
7
|
+
#
|
8
|
+
# 0. You just DO WHAT THE FUCK YOU WANT TO.
|
9
|
+
#++
|
10
|
+
|
11
|
+
class Fixnum
|
12
|
+
def seconds
|
13
|
+
self
|
14
|
+
end
|
15
|
+
|
16
|
+
alias second seconds
|
17
|
+
alias s seconds
|
18
|
+
|
19
|
+
def milliseconds
|
20
|
+
self / 1000
|
21
|
+
end
|
22
|
+
|
23
|
+
alias millisecond milliseconds
|
24
|
+
alias ms milliseconds
|
25
|
+
|
26
|
+
def minutes
|
27
|
+
self * 60
|
28
|
+
end
|
29
|
+
|
30
|
+
alias minute minutes
|
31
|
+
|
32
|
+
def hours
|
33
|
+
self * 60 * 60
|
34
|
+
end
|
35
|
+
|
36
|
+
alias hour hours
|
37
|
+
|
38
|
+
def days
|
39
|
+
self * 60 * 60 * 24
|
40
|
+
end
|
41
|
+
|
42
|
+
alias day days
|
43
|
+
end
|
44
|
+
|
45
|
+
module Kernel
|
46
|
+
def second
|
47
|
+
1.second
|
48
|
+
end
|
49
|
+
|
50
|
+
def minute
|
51
|
+
1.minute
|
52
|
+
end
|
53
|
+
|
54
|
+
def hour
|
55
|
+
1.hour
|
56
|
+
end
|
57
|
+
|
58
|
+
def day
|
59
|
+
1.day
|
60
|
+
end
|
61
|
+
end
|
metadata
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: hardstatus
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- meh.
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-05-16 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: eventmachine
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: thread
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
description:
|
42
|
+
email: meh@schizofreni.co
|
43
|
+
executables:
|
44
|
+
- hardstatus-daemon
|
45
|
+
extensions: []
|
46
|
+
extra_rdoc_files: []
|
47
|
+
files:
|
48
|
+
- README.md
|
49
|
+
- Rakefile
|
50
|
+
- bin/hardstatus-daemon
|
51
|
+
- ext/hardstatus.c
|
52
|
+
- hardstatus.gemspec
|
53
|
+
- lib/hardstatus.rb
|
54
|
+
- lib/hardstatus/controller.rb
|
55
|
+
- lib/hardstatus/time.rb
|
56
|
+
homepage: http://github.com/meh/hardstatus
|
57
|
+
licenses: []
|
58
|
+
metadata: {}
|
59
|
+
post_install_message:
|
60
|
+
rdoc_options: []
|
61
|
+
require_paths:
|
62
|
+
- lib
|
63
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - '>='
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '0'
|
68
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
69
|
+
requirements:
|
70
|
+
- - '>='
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: '0'
|
73
|
+
requirements: []
|
74
|
+
rubyforge_project:
|
75
|
+
rubygems_version: 2.0.0
|
76
|
+
signing_key:
|
77
|
+
specification_version: 4
|
78
|
+
summary: Hardstatus helpers for screen, because tmux just does not cut it for me.
|
79
|
+
test_files: []
|