zashoku 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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: []