cline 0.3.2 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +1 -1
- data/README.md +77 -42
- data/bin/cline +7 -13
- data/cline.gemspec +32 -20
- data/lib/cline.rb +60 -38
- data/lib/cline/client.rb +28 -0
- data/lib/cline/collectors.rb +7 -3
- data/lib/cline/collectors/feed.rb +28 -22
- data/lib/cline/command.rb +93 -17
- data/lib/cline/configure.rb +4 -2
- data/lib/cline/monkey.rb +7 -0
- data/lib/cline/notification.rb +12 -12
- data/lib/cline/notify_io.rb +24 -0
- data/lib/cline/scheduled_job.rb +26 -0
- data/lib/cline/server.rb +102 -0
- data/lib/cline/version.rb +1 -1
- data/spec/lib/notification_spec.rb +7 -15
- data/spec/lib/server_spec.rb +22 -0
- data/spec/spec_helper.rb +3 -3
- data/spec/support/example_group_helper.rb +8 -0
- metadata +65 -93
- data/lib/cline/out_streams.rb +0 -34
data/.travis.yml
CHANGED
@@ -1,2 +1,2 @@
|
|
1
1
|
rvm:
|
2
|
-
-
|
2
|
+
- 1.9.3
|
data/README.md
CHANGED
@@ -1,39 +1,78 @@
|
|
1
|
-
# Cline -
|
1
|
+
# Cline - Show recently news on the terminal[![Build Status](https://secure.travis-ci.org/hibariya/cline.png?branch=master)](http://travis-ci.org/hibariya/cline)
|
2
2
|
|
3
|
-
|
3
|
+
```
|
4
|
+
+-------------------------+ +-------+ +--------------------------------------+
|
5
|
+
| Notification Collectors | -> | Cline | -> | IO (STDOUT, File and Other notifier) |
|
6
|
+
+-------------------------+ +-------+ +--------------------------------------+
|
7
|
+
Collect any news Store notifications Put anywhere
|
8
|
+
```
|
9
|
+
|
10
|
+
Cline is a simple notification tool for CLI.
|
11
|
+
This tool collects automatically any Feeds and GitHub activities.
|
12
|
+
Those notifications shown on stdout or anywhere at good timing.
|
13
|
+
|
14
|
+
Like this:
|
15
|
+
|
16
|
+
```
|
17
|
+
$ cline show
|
18
|
+
[2012/11/27 01:18][5][184] TED: Ideas worth spreading http://icio.us/+a922037eaf9bb
|
19
|
+
```
|
20
|
+
|
21
|
+
A notification is structured by below contents:
|
22
|
+
|
23
|
+
* Published date of the entry and activity
|
24
|
+
* Displayed count
|
25
|
+
* Alias number for specify from CLI ([0-9a-z]+)
|
26
|
+
* Title or summary (includes source URL)
|
27
|
+
|
28
|
+
In most cases Cline used for backtick of screen. Like this:
|
29
|
+
|
30
|
+
```
|
31
|
+
[2012/12/01 23:12][9][1bt] Amazon Redshift http://aws.amazon.com/redshift/
|
32
|
+
[2012/12/01 23:12][9][1bu] My eBook build process and some PDF, EPUB and MOBI tips - Pat Shaughnessy http://patshaughnessy.net/2012/11/27/my-ebook-build-process-and-some-pdf-epub-and-mobi-tips
|
33
|
+
[2012/12/01 23:12][9][1bs] How to Clean Up Your Online Presence and Make a Great First Impression http://lifehacker.com/5963864/how-to-clean-up-your-online-presence-and-make-a-great-first-impression
|
34
|
+
```
|
35
|
+
|
36
|
+
You can open the URI of a notification. Like this:
|
4
37
|
|
5
38
|
```
|
6
|
-
|
7
|
-
| Collectors | ----------> | Cline | ----------> | OutStream |
|
8
|
-
+------------+ +-----------+ +-----------+
|
9
|
-
Collect any notifications Pool notifications Put anywhere
|
39
|
+
$ cline open 1bt
|
10
40
|
```
|
11
41
|
|
42
|
+
Cline decides priority of each notification automatically with 'displayed count' and 'published date'.
|
43
|
+
You can't control priority of Cline's output.
|
44
|
+
|
12
45
|
## Installation and Setting
|
13
46
|
|
14
47
|
```
|
15
48
|
$ gem install cline
|
16
|
-
$ cline init
|
49
|
+
$ cline init # database file will created under ~/.cline directory
|
17
50
|
```
|
18
51
|
|
19
|
-
|
52
|
+
An example of configuration file (~/.cline/config):
|
20
53
|
|
21
54
|
```ruby
|
55
|
+
ENV['NOTIFY'] = 'notify-send' # ensure notification behaviour if you use the notify gem
|
56
|
+
|
22
57
|
Cline.configure do |config|
|
23
|
-
config.
|
58
|
+
config.notifications_limit = 2000 # old notifications will be removed automatically
|
59
|
+
|
60
|
+
config.notify_io = Cline::NotifyIO::WithNotify.new
|
61
|
+
# Default is:
|
62
|
+
# config.notify_io = $stdout
|
24
63
|
|
25
|
-
config.
|
26
|
-
## Or
|
27
|
-
# config.out_stream = $stdout
|
64
|
+
config.collectors << Cline::Collectors::Feed
|
28
65
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
66
|
+
# Github:
|
67
|
+
config.collectors << Cline::Collectors::Github
|
68
|
+
Cline::Collectors::Github.login_name = 'hibariya'
|
69
|
+
|
70
|
+
# When server is running then collectors will run every hours.
|
71
|
+
config.jobs << Cline::ScheduledJob.new(-> { Time.now.min.zero? }, &:collect)
|
33
72
|
end
|
34
73
|
```
|
35
74
|
|
36
|
-
Write your RSS feeds
|
75
|
+
Write OPML file of your RSS feeds:
|
37
76
|
|
38
77
|
```
|
39
78
|
$ curl http://foo.examle.com/url/to/opml.xml > ~/.cline/feeds.xml
|
@@ -48,14 +87,14 @@ Collect notifications:
|
|
48
87
|
Show notifications:
|
49
88
|
|
50
89
|
```
|
51
|
-
$ cline tick
|
90
|
+
$ cline tick 5
|
52
91
|
[2012/05/02 02:34][9][w6] Introducing DuckDuckHack - Gabriel Weinberg's Blog http://www.gabrielweinberg.com/blog/2012/05/introducing-duckduckhack.html
|
53
92
|
| | |
|
54
93
|
`-- time | `-- alias
|
55
94
|
`----- display count
|
56
95
|
```
|
57
96
|
|
58
|
-
|
97
|
+
How to open a URL in the message: Use open command and specify notification alias.
|
59
98
|
|
60
99
|
```
|
61
100
|
$ cline open w6
|
@@ -63,29 +102,29 @@ Open URL in the message:
|
|
63
102
|
|
64
103
|
## Use case
|
65
104
|
|
66
|
-
|
67
|
-
|
68
|
-
```
|
69
|
-
backtick 0 0 0 cline tick 0 60
|
70
|
-
```
|
71
|
-
|
72
|
-
## initialize Database
|
105
|
+
In most cases Cline used for backtick of screen.
|
73
106
|
|
74
|
-
|
107
|
+
In ~/.screenrc:
|
75
108
|
|
76
109
|
```
|
77
|
-
|
110
|
+
backtick 0 0 0 cline tick 5
|
78
111
|
```
|
79
112
|
|
80
|
-
##
|
113
|
+
## Cline daemon
|
81
114
|
|
82
|
-
|
115
|
+
When server is running then cline uses server process.
|
116
|
+
Using server is faster and less memory.
|
83
117
|
|
84
118
|
```
|
85
|
-
$ cline
|
119
|
+
$ cline server start # start server
|
120
|
+
$ cline server reload # reload ~/.cline/config file
|
121
|
+
$ cline server stop # stop server
|
122
|
+
$ cline server status # show server status
|
86
123
|
```
|
87
124
|
|
88
|
-
|
125
|
+
## Customize
|
126
|
+
|
127
|
+
### Custom collector
|
89
128
|
|
90
129
|
*collector* required `collect` method.
|
91
130
|
|
@@ -106,29 +145,27 @@ example:
|
|
106
145
|
```
|
107
146
|
|
108
147
|
Cline::Collectors::Base class provides `create_or_pass` method.
|
109
|
-
It create a new unique notification.
|
148
|
+
It create a new (unique) notification.
|
110
149
|
|
111
|
-
|
112
|
-
|
113
|
-
in ~/.cline/config
|
150
|
+
In ~/.cline/config:
|
114
151
|
|
115
152
|
```ruby
|
116
153
|
require 'path/to/my_collector'
|
117
154
|
|
118
155
|
Cline.configure do |config|
|
119
156
|
# ...
|
120
|
-
config.
|
157
|
+
config.collectors << MyCollector
|
121
158
|
end
|
122
159
|
```
|
123
160
|
|
124
161
|
## Notifier
|
125
162
|
|
126
163
|
`show` and `tick` command uses Cline's notifier.
|
127
|
-
Default notifier is
|
164
|
+
Default notifier is $stdout.
|
128
165
|
|
129
166
|
### Custom Notifyer
|
130
167
|
|
131
|
-
Cline's notifier required `puts`
|
168
|
+
Cline's notifier required `puts` method.
|
132
169
|
|
133
170
|
example:
|
134
171
|
|
@@ -140,9 +177,7 @@ example:
|
|
140
177
|
end
|
141
178
|
```
|
142
179
|
|
143
|
-
|
144
|
-
|
145
|
-
in ~/.cline/config
|
180
|
+
In ~/.cline/config
|
146
181
|
|
147
182
|
```ruby
|
148
183
|
require 'path/to/my_notifier'
|
data/bin/cline
CHANGED
@@ -1,18 +1,12 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
# coding: utf-8
|
3
3
|
|
4
|
-
|
4
|
+
trap :INT do
|
5
|
+
print "\r"
|
6
|
+
exit
|
7
|
+
end
|
5
8
|
|
6
|
-
|
7
|
-
Cline::Command.start
|
8
|
-
rescue Exception
|
9
|
-
Pathname.new("#{Cline.cline_dir}/log").open('a') do |f|
|
10
|
-
f.puts '---'
|
11
|
-
f.puts Time.now
|
12
|
-
f.puts $!.class
|
13
|
-
f.puts $!.message
|
14
|
-
f.puts $!.backtrace.join("\n")
|
15
|
-
end
|
9
|
+
require 'cline'
|
16
10
|
|
17
|
-
|
18
|
-
|
11
|
+
Cline.boot
|
12
|
+
Cline::Command.start
|
data/cline.gemspec
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
|
+
|
2
3
|
$:.push File.expand_path('../lib', __FILE__)
|
3
4
|
require 'cline/version'
|
4
5
|
|
@@ -8,31 +9,42 @@ Gem::Specification.new do |s|
|
|
8
9
|
s.authors = ['hibariya']
|
9
10
|
s.email = ['celluloid.key@gmail.com']
|
10
11
|
s.homepage = 'https://github.com/hibariya/cline'
|
11
|
-
s.summary = %q{
|
12
|
-
s.description = %q{
|
12
|
+
s.summary = %q{Show recently news on the terminal}
|
13
|
+
s.description = %q{Show recently news on the terminal.}
|
14
|
+
|
15
|
+
s.post_install_message = <<-EOM
|
16
|
+
**Important changes**
|
17
|
+
|
18
|
+
`tick` command usage has changed.
|
19
|
+
|
20
|
+
`cline tick OFFSET INTERVAL' -> `cline tick INTERVAL OFFSET'
|
13
21
|
|
14
|
-
|
15
|
-
|
22
|
+
**Cline server is available**
|
23
|
+
|
24
|
+
Cline uses daemon process if it's running.
|
25
|
+
|
26
|
+
$ cline server start # start server
|
27
|
+
$ cline server stop # stop server
|
28
|
+
$ cline server reload # reload config file
|
29
|
+
EOM
|
16
30
|
|
17
31
|
s.files = `git ls-files`.split("\n")
|
18
32
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
19
33
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
20
34
|
s.require_paths = ['lib']
|
21
35
|
|
22
|
-
s.add_runtime_dependency 'thor', ['
|
23
|
-
s.add_runtime_dependency 'activerecord', ['
|
24
|
-
s.add_runtime_dependency 'sqlite3', ['
|
25
|
-
s.add_runtime_dependency 'feedzirra', ['~> 0.
|
26
|
-
s.add_runtime_dependency 'notify', ['
|
27
|
-
s.add_runtime_dependency 'launchy', ['
|
28
|
-
|
29
|
-
s.add_development_dependency 'rake', ['
|
30
|
-
s.add_development_dependency '
|
31
|
-
s.add_development_dependency '
|
32
|
-
s.add_development_dependency '
|
33
|
-
s.add_development_dependency '
|
34
|
-
s.add_development_dependency '
|
35
|
-
s.add_development_dependency '
|
36
|
-
s.add_development_dependency 'simplecov', ['>= 0.5.3']
|
37
|
-
s.add_development_dependency 'activesupport', ['>= 3.1.1']
|
36
|
+
s.add_runtime_dependency 'thor', ['~> 0.16.0']
|
37
|
+
s.add_runtime_dependency 'activerecord', ['~> 3.1.8']
|
38
|
+
s.add_runtime_dependency 'sqlite3', ['~> 1.3.6']
|
39
|
+
s.add_runtime_dependency 'feedzirra', ['~> 0.1.3']
|
40
|
+
s.add_runtime_dependency 'notify', ['~> 0.4.0']
|
41
|
+
s.add_runtime_dependency 'launchy', ['~> 2.1.2']
|
42
|
+
|
43
|
+
s.add_development_dependency 'rake', ['~> 10.0.2']
|
44
|
+
s.add_development_dependency 'tapp', ['~> 1.4.0']
|
45
|
+
s.add_development_dependency 'rspec', ['~> 2.12.0']
|
46
|
+
s.add_development_dependency 'fabrication', ['~> 2.5.0']
|
47
|
+
s.add_development_dependency 'fuubar', ['~> 1.1.0']
|
48
|
+
s.add_development_dependency 'simplecov', ['~> 0.7.1']
|
49
|
+
s.add_development_dependency 'activesupport', ['~> 3.1.8']
|
38
50
|
end
|
data/lib/cline.rb
CHANGED
@@ -1,70 +1,92 @@
|
|
1
1
|
# coding: utf-8
|
2
2
|
|
3
|
-
|
4
|
-
|
3
|
+
require 'fileutils'
|
4
|
+
require 'logger'
|
5
|
+
require 'cline/configure'
|
6
|
+
require 'cline/version'
|
5
7
|
|
6
8
|
module Cline
|
9
|
+
autoload :Collectors, 'cline/collectors'
|
10
|
+
autoload :Command, 'cline/command'
|
11
|
+
autoload :Notification, 'cline/notification'
|
12
|
+
autoload :Server, 'cline/server'
|
13
|
+
autoload :Client, 'cline/client'
|
14
|
+
autoload :NotifyIO, 'cline/notify_io'
|
15
|
+
autoload :ScheduledJob, 'cline/scheduled_job'
|
16
|
+
|
17
|
+
autoload :OutStreams, 'cline/notify_io' # obsolete
|
18
|
+
|
7
19
|
class << self
|
20
|
+
attr_accessor :logger, :notifications_limit
|
21
|
+
attr_writer :collectors, :notify_io, :jobs
|
22
|
+
|
8
23
|
def cline_dir
|
9
24
|
"#{ENV['HOME']}/.cline"
|
10
25
|
end
|
11
26
|
|
12
27
|
def boot
|
13
28
|
mkdir_if_needed
|
14
|
-
setup_logger
|
15
|
-
establish_connection
|
16
29
|
load_config_if_exists
|
30
|
+
load_default_config
|
31
|
+
|
32
|
+
self
|
17
33
|
end
|
18
34
|
|
19
|
-
def
|
20
|
-
|
21
|
-
path.mkdir unless path.directory?
|
35
|
+
def collectors
|
36
|
+
@collectors ||= []
|
22
37
|
end
|
23
38
|
|
24
|
-
def
|
25
|
-
|
26
|
-
ActiveRecord::Base.logger.level = Logger::WARN
|
39
|
+
def jobs
|
40
|
+
@jobs ||= []
|
27
41
|
end
|
28
42
|
|
29
|
-
def
|
30
|
-
|
43
|
+
def establish_database_connection
|
44
|
+
require 'active_record'
|
45
|
+
|
46
|
+
ActiveRecord::Base.logger = logger
|
47
|
+
ActiveRecord::Base.establish_connection adapter: 'sqlite3', database: %(#{cline_dir}/cline.sqlite3), timeout: 10000, pool: 10
|
31
48
|
end
|
32
49
|
|
33
|
-
def
|
34
|
-
|
35
|
-
load config if config.exist?
|
50
|
+
def stdout
|
51
|
+
Thread.current[:stdout] || $stdout
|
36
52
|
end
|
37
53
|
|
38
|
-
def
|
39
|
-
|
54
|
+
def stderr
|
55
|
+
Thread.current[:stderr] || $stderr
|
40
56
|
end
|
41
57
|
|
42
|
-
def
|
43
|
-
@
|
58
|
+
def notify_io
|
59
|
+
@notify_io == $stdout ? stdout : @notify_io
|
44
60
|
end
|
45
61
|
|
46
|
-
def
|
47
|
-
|
62
|
+
def load_config_if_exists
|
63
|
+
config_file = "#{cline_dir}/config"
|
64
|
+
|
65
|
+
load config_file if File.exist?(config_file)
|
48
66
|
end
|
49
67
|
|
50
|
-
def
|
51
|
-
@
|
68
|
+
def load_default_config
|
69
|
+
@logger ||= default_logger
|
70
|
+
@notify_io ||= stdout
|
71
|
+
@notifications_limit ||= nil
|
52
72
|
end
|
53
73
|
|
54
|
-
|
55
|
-
define_method(:collectors) { collectors }
|
56
|
-
end
|
57
|
-
end
|
74
|
+
private
|
58
75
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
require 'sqlite3'
|
63
|
-
require 'active_record'
|
76
|
+
def mkdir_if_needed
|
77
|
+
FileUtils.mkdir_p cline_dir
|
78
|
+
end
|
64
79
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
80
|
+
def default_logger
|
81
|
+
Logger.new("#{cline_dir}/log").tap {|l| l.level = Logger::WARN }
|
82
|
+
end
|
83
|
+
|
84
|
+
public
|
85
|
+
|
86
|
+
# obsoletes
|
87
|
+
[%w(out_stream notify_io), %w(pool_size notifications_limit)].each do |obsolete, original|
|
88
|
+
alias_method obsolete, original
|
89
|
+
alias_method %(#{obsolete}=), %(#{original}=)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
data/lib/cline/client.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require 'socket'
|
4
|
+
require 'json'
|
5
|
+
|
6
|
+
module Cline
|
7
|
+
class Client
|
8
|
+
def self.start(args)
|
9
|
+
new(args).invoke
|
10
|
+
end
|
11
|
+
|
12
|
+
def initialize(args)
|
13
|
+
@args = args
|
14
|
+
end
|
15
|
+
|
16
|
+
def invoke
|
17
|
+
$stdout.sync = true
|
18
|
+
|
19
|
+
UNIXSocket.open Server.socket_file.to_path do |socket|
|
20
|
+
socket.puts @args.to_json
|
21
|
+
|
22
|
+
while line = socket.gets
|
23
|
+
puts line
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|