zashoku 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +16 -0
- data/bin/zashoku +17 -0
- data/config/daemon.yml +8 -0
- data/config/view.yml +16 -0
- data/lib/core/config/config.rb +96 -0
- data/lib/core/config/daemon_config.rb +19 -0
- data/lib/core/config/view_config.rb +19 -0
- data/lib/core/controller.rb +13 -0
- data/lib/core/formatter.rb +115 -0
- data/lib/core/item.rb +24 -0
- data/lib/core/module.rb +52 -0
- data/lib/core/net/client.rb +115 -0
- data/lib/core/net/server.rb +70 -0
- data/lib/core/options.rb +43 -0
- data/lib/core/util/folder_listen.rb +53 -0
- data/lib/core/util/term.rb +61 -0
- data/lib/core/util/util.rb +47 -0
- data/lib/core/view.rb +268 -0
- data/lib/daemon.rb +83 -0
- data/lib/generator.rb +44 -0
- data/lib/viewer.rb +178 -0
- data/lib/zashoku.rb +35 -0
- metadata +66 -0
data/lib/daemon.rb
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
require 'logger'
|
5
|
+
require 'socket'
|
6
|
+
require 'thread'
|
7
|
+
require 'warning'
|
8
|
+
|
9
|
+
require_relative 'core/controller'
|
10
|
+
require_relative 'core/config/daemon_config'
|
11
|
+
require_relative 'core/net/server'
|
12
|
+
require_relative 'core/util/util'
|
13
|
+
require_relative 'core/formatter'
|
14
|
+
require_relative 'core/item'
|
15
|
+
require_relative 'core/module'
|
16
|
+
|
17
|
+
module Zashoku
|
18
|
+
|
19
|
+
class<<self
|
20
|
+
attr_accessor :controllers
|
21
|
+
def command(message)
|
22
|
+
Zashoku.logger.debug("command got #{message}")
|
23
|
+
message = message.keys.map(&:to_sym).zip(message.values).to_h
|
24
|
+
|
25
|
+
obj = controllers[message[:mod]].send(message[:meth], *message[:args])
|
26
|
+
Zashoku::Util.encode_object(obj)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class Daemon
|
31
|
+
def initialize
|
32
|
+
# Load conf
|
33
|
+
Zashoku.conf = DaemonConfig.new
|
34
|
+
# Load modules
|
35
|
+
Zashoku.modules = Zashoku::Module.load(Zashoku.conf.get(%w[modules enabled]))
|
36
|
+
# Update conf with module defaults
|
37
|
+
Zashoku.conf.reload
|
38
|
+
|
39
|
+
#initialize logger
|
40
|
+
Zashoku.logger = Logger.new(STDOUT)
|
41
|
+
|
42
|
+
Zashoku.controllers =
|
43
|
+
Zashoku.modules.keys.zip(Zashoku.modules.values.map(&:controller)).to_h
|
44
|
+
|
45
|
+
@server = Net::Server.new(12_345)
|
46
|
+
@server.handler = method(:respond)
|
47
|
+
|
48
|
+
Zashoku.controllers.each_value { |c| c.add_observer(self) }
|
49
|
+
|
50
|
+
# $stdout.reopen(@pref.parseDir(@pref.get('daemon_log_file')), 'w')
|
51
|
+
# $stderr.reopen(@pref.parseDir(@pref.get('daemon_log_file')), 'w')
|
52
|
+
# $stdout.sync = true
|
53
|
+
# $stderr.sync = true
|
54
|
+
sleep
|
55
|
+
end
|
56
|
+
|
57
|
+
def update(sender:, event:)
|
58
|
+
Zashoku.logger.debug("controller #{sender} sent update #{event}")
|
59
|
+
@server.event(sender: sender, event: event)
|
60
|
+
end
|
61
|
+
|
62
|
+
def respond(message)
|
63
|
+
Zashoku.logger.debug("daemon.respond #{message}")
|
64
|
+
case message['msg']
|
65
|
+
when 'modules'
|
66
|
+
Zashoku.modules.map { |m, _| m }
|
67
|
+
when 'items'
|
68
|
+
Zashoku.command(mod: message[:mod], meth: :items)
|
69
|
+
when 'fwd'
|
70
|
+
Zashoku.command(message)
|
71
|
+
when 'disconnect'
|
72
|
+
nil
|
73
|
+
else
|
74
|
+
'what?'
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def cleanup
|
79
|
+
@server.exit
|
80
|
+
exit
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
data/lib/generator.rb
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'fileutils'
|
4
|
+
require 'pathname'
|
5
|
+
|
6
|
+
module Zashoku
|
7
|
+
class Generator
|
8
|
+
TemplateDir = File.join(Zashoku::Root, 'templates')
|
9
|
+
LowerCaseIdentifier = '<module_name>'
|
10
|
+
UpperCaseIdentifier = '<Module_name>'
|
11
|
+
Extensions = 'rb,yml,md,gemspec'
|
12
|
+
|
13
|
+
def initialize(template, name)
|
14
|
+
@template = template
|
15
|
+
@name = name
|
16
|
+
@input_dir = Pathname.new(File.join(TemplateDir, template))
|
17
|
+
@output_dir = Pathname.new(File.join(Zashoku::Root, 'modules', @name))
|
18
|
+
raise 'Module already exists' if Dir.exist?(@output_dir)
|
19
|
+
end
|
20
|
+
|
21
|
+
def refactor(thing)
|
22
|
+
thing
|
23
|
+
.to_s
|
24
|
+
.gsub(/#{LowerCaseIdentifier}/, @name)
|
25
|
+
.gsub(/#{UpperCaseIdentifier}/, @name.capitalize)
|
26
|
+
end
|
27
|
+
|
28
|
+
def generate
|
29
|
+
Dir.glob("#{@input_dir}/**/*.#{Extensions}").each do |file|
|
30
|
+
new_file =
|
31
|
+
File.join(
|
32
|
+
@output_dir,
|
33
|
+
refactor(Pathname.new(file).relative_path_from(@input_dir))
|
34
|
+
)
|
35
|
+
|
36
|
+
FileUtils.mkdir_p(File.dirname(new_file))
|
37
|
+
|
38
|
+
File.open(new_file, 'w') do |f|
|
39
|
+
f.print refactor(File.open(file, 'r', &:read))
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
data/lib/viewer.rb
ADDED
@@ -0,0 +1,178 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'curses'
|
4
|
+
require 'highline'
|
5
|
+
require 'io/console'
|
6
|
+
require 'logger'
|
7
|
+
require 'observer'
|
8
|
+
require 'thread'
|
9
|
+
|
10
|
+
require_relative 'core/controller'
|
11
|
+
require_relative 'core/config/view_config'
|
12
|
+
require_relative 'core/net/client'
|
13
|
+
require_relative 'core/util/term'
|
14
|
+
require_relative 'core/util/util'
|
15
|
+
require_relative 'core/formatter'
|
16
|
+
require_relative 'core/item'
|
17
|
+
require_relative 'core/module'
|
18
|
+
require_relative 'core/view'
|
19
|
+
|
20
|
+
$stdout.sync = true
|
21
|
+
|
22
|
+
module Zashoku
|
23
|
+
class<<self
|
24
|
+
attr_accessor :client
|
25
|
+
|
26
|
+
def command(message)
|
27
|
+
message.keys.map(&:to_sym).zip(message.values).to_h
|
28
|
+
|
29
|
+
if /^remote::.*/.match?(message[:mod])
|
30
|
+
message[:mod] = message[:mod].gsub('remote::', '')
|
31
|
+
Zashoku.logger.debug("sending message #{message}")
|
32
|
+
Zashoku::Util.decode_object(client.command('fwd', message))
|
33
|
+
else
|
34
|
+
modules[message[:mod]].send(message[:meth], *message[:args])
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def alert(message)
|
39
|
+
print "\e[#{Util::Term.rows - 2};0H #{message}"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# Main class for the zashoku application
|
44
|
+
class Viewer
|
45
|
+
include Util
|
46
|
+
|
47
|
+
COMMANDS = {
|
48
|
+
'quit' => :cleanup,
|
49
|
+
'enter_command' => :get_user_command
|
50
|
+
}.freeze
|
51
|
+
|
52
|
+
def initialize
|
53
|
+
@semaphore = Mutex.new
|
54
|
+
|
55
|
+
Zashoku.conf = ViewConfig.new
|
56
|
+
|
57
|
+
Zashoku.modules = Zashoku::Module.load(
|
58
|
+
Zashoku.conf.get(%w[modules enabled])
|
59
|
+
)
|
60
|
+
Zashoku.conf.reload
|
61
|
+
|
62
|
+
Zashoku.logger = Logger.new('zashoku_log.log')
|
63
|
+
|
64
|
+
# note: start daemon if not running
|
65
|
+
Zashoku.client = Net::Client.new(12_345)
|
66
|
+
Zashoku.client.callbacks << method(:handle_event)
|
67
|
+
|
68
|
+
@views = Zashoku.modules.keys.zip(Zashoku.modules.map do |_k, m|
|
69
|
+
m.view
|
70
|
+
end).to_h
|
71
|
+
|
72
|
+
@view = @views.keys.first
|
73
|
+
init_screen
|
74
|
+
lay_traps!
|
75
|
+
Thread.abort_on_exception = true
|
76
|
+
Thread.new { scan_keyboard! }
|
77
|
+
@views[@view].add_observer(self, :draw_view)
|
78
|
+
@views[@view].refresh
|
79
|
+
draw_view
|
80
|
+
|
81
|
+
sleep
|
82
|
+
end
|
83
|
+
|
84
|
+
def lay_traps!
|
85
|
+
Signal.trap('WINCH') do
|
86
|
+
Thread.new do
|
87
|
+
@semaphore.synchronize { @views[@view].change_screen_size }
|
88
|
+
end
|
89
|
+
end
|
90
|
+
Signal.trap('INT') do
|
91
|
+
Thread.new do
|
92
|
+
@semaphore.synchronize { cleanup }
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def init_screen
|
98
|
+
Curses.noecho
|
99
|
+
Curses.init_screen
|
100
|
+
Term.hide_cursor
|
101
|
+
Curses.stdscr.keypad(true)
|
102
|
+
end
|
103
|
+
|
104
|
+
def command(mod, meth, *args)
|
105
|
+
if /^remote::.*/.match?(mod)
|
106
|
+
Zashoku.command(mod: mod, meth: meth, args: args)
|
107
|
+
elsif @views.key?(mod) && @views[mod].respond_to?(meth)
|
108
|
+
@views[mod].send(meth, *args)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def get_user_command
|
113
|
+
Util.readline
|
114
|
+
end
|
115
|
+
|
116
|
+
def handle_event(event)
|
117
|
+
case event['event']
|
118
|
+
when 'items'
|
119
|
+
command(event['sender'], :refresh)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def scan_keyboard!
|
124
|
+
loop do
|
125
|
+
key = Curses.getch
|
126
|
+
maps = Zashoku.conf.get(%w[keymaps])
|
127
|
+
cmd =
|
128
|
+
if maps['global'].key?(key)
|
129
|
+
maps['global'][key]
|
130
|
+
elsif maps[@view]&.key?(key)
|
131
|
+
maps[@view][key]
|
132
|
+
else
|
133
|
+
''
|
134
|
+
end
|
135
|
+
|
136
|
+
return send(COMMANDS[cmd]) if COMMANDS.key?(cmd)
|
137
|
+
|
138
|
+
mod, meth, *args = cmd.split
|
139
|
+
# puts "#{key} #{mod} #{meth} #{args}"
|
140
|
+
mod = mod == 'current_view' ? @view : mod
|
141
|
+
args.map! do |arg|
|
142
|
+
if arg.chr == '$'
|
143
|
+
arg = arg[1..-1]
|
144
|
+
chain = arg.split('.')
|
145
|
+
chain[1..-1].reduce(@views[@view].send(chain.first)) do |m, a|
|
146
|
+
m.send(a)
|
147
|
+
end
|
148
|
+
else
|
149
|
+
arg
|
150
|
+
end
|
151
|
+
end
|
152
|
+
command(mod, meth, *args)
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
def cleanup
|
157
|
+
Zashoku.client.disconnect
|
158
|
+
@key_thread&.exit
|
159
|
+
Curses.close_screen
|
160
|
+
Term.show_cursor
|
161
|
+
exit
|
162
|
+
end
|
163
|
+
|
164
|
+
def change_view(new_view:)
|
165
|
+
@view.delete_observers
|
166
|
+
@view.pause
|
167
|
+
new_view.add_observer(self, :draw_view)
|
168
|
+
new_view.change_screen_size(redraw: false)
|
169
|
+
new_view.expand(-1)
|
170
|
+
new_view.unpause
|
171
|
+
@view = view
|
172
|
+
end
|
173
|
+
|
174
|
+
def draw_view
|
175
|
+
@views[@view].draw
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
data/lib/zashoku.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'core/options'
|
4
|
+
|
5
|
+
module Zashoku
|
6
|
+
Version = [1, 0, 0].freeze
|
7
|
+
Root = File.expand_path('../', __dir__)
|
8
|
+
|
9
|
+
autoload :Generator, File.join(Root, 'lib/generator')
|
10
|
+
autoload :Viewer, File.join(Root, 'lib/viewer')
|
11
|
+
autoload :Daemon, File.join(Root, 'lib/daemon')
|
12
|
+
|
13
|
+
class << self
|
14
|
+
attr_accessor :conf, :modules, :logger
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.command(message)
|
18
|
+
message.keys.map(&:to_sym).zip(message.values).to_h
|
19
|
+
|
20
|
+
modules[message[:mod]].send(message[:meth], *message[:args])
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.main(args)
|
24
|
+
options = Options.parse(args)
|
25
|
+
Zashoku.modules = []
|
26
|
+
|
27
|
+
if options[:generate]
|
28
|
+
Generator.new(options[:template], options[:generate_name]).generate
|
29
|
+
elsif options[:daemon]
|
30
|
+
Daemon.new
|
31
|
+
else
|
32
|
+
Viewer.new.run
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
metadata
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: zashoku
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- annacrombie
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-10-12 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: inspired by cmus, vim, and rails
|
14
|
+
email: meotleft@gmail.com
|
15
|
+
executables:
|
16
|
+
- zashoku
|
17
|
+
extensions: []
|
18
|
+
extra_rdoc_files: []
|
19
|
+
files:
|
20
|
+
- "./README.md"
|
21
|
+
- "./config/daemon.yml"
|
22
|
+
- "./config/view.yml"
|
23
|
+
- "./lib/core/config/config.rb"
|
24
|
+
- "./lib/core/config/daemon_config.rb"
|
25
|
+
- "./lib/core/config/view_config.rb"
|
26
|
+
- "./lib/core/controller.rb"
|
27
|
+
- "./lib/core/formatter.rb"
|
28
|
+
- "./lib/core/item.rb"
|
29
|
+
- "./lib/core/module.rb"
|
30
|
+
- "./lib/core/net/client.rb"
|
31
|
+
- "./lib/core/net/server.rb"
|
32
|
+
- "./lib/core/options.rb"
|
33
|
+
- "./lib/core/util/folder_listen.rb"
|
34
|
+
- "./lib/core/util/term.rb"
|
35
|
+
- "./lib/core/util/util.rb"
|
36
|
+
- "./lib/core/view.rb"
|
37
|
+
- "./lib/daemon.rb"
|
38
|
+
- "./lib/generator.rb"
|
39
|
+
- "./lib/viewer.rb"
|
40
|
+
- "./lib/zashoku.rb"
|
41
|
+
- bin/zashoku
|
42
|
+
homepage: https://github.com/zashoku/zashoku/
|
43
|
+
licenses:
|
44
|
+
- MIT
|
45
|
+
metadata: {}
|
46
|
+
post_install_message:
|
47
|
+
rdoc_options: []
|
48
|
+
require_paths:
|
49
|
+
- lib
|
50
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
56
|
+
requirements:
|
57
|
+
- - ">="
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: '0'
|
60
|
+
requirements: []
|
61
|
+
rubyforge_project:
|
62
|
+
rubygems_version: 2.6.11
|
63
|
+
signing_key:
|
64
|
+
specification_version: 4
|
65
|
+
summary: command line application framework
|
66
|
+
test_files: []
|