zashoku 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
@@ -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
@@ -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
@@ -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: []