zashoku 1.3.2 → 1.5.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 293949927ade60de5f383df77ee37dec6c24dab1
4
- data.tar.gz: eda30013219a99aa1045aec09f90d326b674c517
3
+ metadata.gz: 859618076e68ab5194ed1cf1dd81b712fee21bd1
4
+ data.tar.gz: fe04a7bd55c690282a93f3f489ebeb000e80f943
5
5
  SHA512:
6
- metadata.gz: 4be47481a6d80651cb4534152e34515c3c31e69e20d194257080524dd13d53a24c845236c48a6892a113c63a4d73e9f292feedc00d05338fc94828ede23ba54c
7
- data.tar.gz: b16bfe03e5cfedf4f9cb4205565eedf821f90d5c7889773ea806afe8ab21aebecd2166ee96c3bcbee44cf3956b136e1d06304d19880e77823b0eac821d6bc56d
6
+ metadata.gz: 1a4f5813981d126ec306ef852b202153c2feb0761c9a37b317df4c8f562c6336ca4954e641fa8a86e538e6d8b2088ed2aa20f316a1aeef48cc0437df7f8421e5
7
+ data.tar.gz: 0da1b091ab566af7da57af4d8e5fc4c47c6373907048e6aa6400179a8ad9b87bc5db9f9faea4c5430f955313c696a2e41b065e3c61b49b2423f7eab7cd2bb75a
data/README.md CHANGED
@@ -9,13 +9,14 @@
9
9
 
10
10
  # zashoku座食 [![Maintainability][mb]][m] [![Gem Version][gb]][g] ![座食][c]
11
11
  command line application framework
12
- ![screenshot](img/screenshot.png)
12
+ [![screenshot](img/screenshot.png)](examples/hello/modules/hello/lib/hello/hello_controller.rb)
13
13
 
14
14
  ## features
15
15
  + good for lazy people
16
16
  + generators
17
17
  + optimized view
18
18
  + mvc
19
+ + simple?!
19
20
  + client / server model
20
21
  + rendering support for asian characters
21
22
 
data/config/daemon.yml CHANGED
@@ -1 +1,2 @@
1
1
  ---
2
+ daemon_log: $conf_dir/daemon.log
data/config/view.yml CHANGED
@@ -6,10 +6,16 @@ color:
6
6
  main: "\e[0m\e[34m"
7
7
  keymaps:
8
8
  global:
9
- 259: current_view move_cursor up
10
- 258: current_view move_cursor down
11
- " ": current_view expand $selected_group
9
+ 259: $current_view move_cursor up
10
+ 258: $current_view move_cursor down
11
+ k: $current_view move_cursor up
12
+ j: $current_view move_cursor down
13
+ h: $current_view select $selected_group 0
14
+ " ": $current_view expand $selected_group
12
15
  q: quit
13
16
  ":": enter_command
17
+ "/": search $current_view
18
+ n: $current_view next_match
19
+ N: $current_view previous_match
14
20
  format:
15
21
  statusline: " "
data/lib/constants.rb ADDED
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'core/util/util'
4
+
5
+ module Zashoku
6
+ Version = [1, 5, 0].freeze
7
+
8
+ Root = File.expand_path('../', __dir__)
9
+
10
+ DefConf = {
11
+ app: {
12
+ root: Root,
13
+ name: 'zashoku',
14
+ commands: {},
15
+ modules: {
16
+ viewer: [],
17
+ daemon: [],
18
+ },
19
+ save_config: false,
20
+ save_history: false,
21
+ persistent_daemon: false,
22
+ net: {
23
+ host: 'localhost',
24
+ port: 26_119
25
+ }
26
+ },
27
+ core: {
28
+ commands: {
29
+ 'quit' => :cleanup,
30
+ 'q' => :cleanup,
31
+ 'enter_command' => :get_user_command,
32
+ 'change_view' => :change_view,
33
+ 'map_key' => :map_key,
34
+ 'search' => :search,
35
+ 'zv' => :print_version
36
+ }
37
+ }
38
+ }.freeze
39
+
40
+ CConf = const_defined?(:AppConf) ? Zashoku::Util.deep_merge(DefConf, AppConf) : DefConf
41
+
42
+ LoadPaths = [
43
+ File.join(Zashoku::CConf[:app][:root], 'modules')
44
+ ].freeze
45
+ end
@@ -5,24 +5,22 @@ require 'fileutils'
5
5
 
6
6
  module Zashoku
7
7
  class Config < Controller
8
- CONF_DIR = File.join(Dir.home, '.config/', Zashoku::AppName)
8
+ CONF_DIR = File.join(Dir.home, '.config/', Zashoku::CConf[:app][:name])
9
9
  CONF_FILE = File.join(CONF_DIR, '/conf.yml')
10
10
 
11
11
  def initialize
12
- FileUtils.mkdir_p(CONF_DIR) unless File.directory?(CONF_DIR)
12
+ FileUtils.mkdir_p(CONF_DIR) if save? && !File.directory?(CONF_DIR)
13
13
  reload
14
14
  save unless File.exist?(self.class::CONF_FILE)
15
15
  end
16
16
 
17
- def reload
18
- @conf = merge!(default_conf, user_conf)
19
- save
17
+ def save?
18
+ Zashoku::CConf[:app][:save_config]
20
19
  end
21
20
 
22
- def merge!(this, that)
23
- this&.merge(that || {}) do |_k, old, nu|
24
- old.class == Hash ? merge!(old, nu) : nu
25
- end
21
+ def reload
22
+ @conf = Zashoku::Util.deep_merge(default_conf, user_conf)
23
+ save
26
24
  end
27
25
 
28
26
  def base_conf
@@ -31,7 +29,7 @@ module Zashoku
31
29
 
32
30
  def default_conf
33
31
  module_conf.reduce(base_conf) do |mem, mc|
34
- merge!(mem, mc)
32
+ Zashoku::Util.deep_merge(mem, mc)
35
33
  end
36
34
  end
37
35
 
@@ -69,8 +67,7 @@ module Zashoku
69
67
 
70
68
  def parse_dir(path)
71
69
  {
72
- # '$airing_dir' => @conf['airing_dir'],
73
- # '$conf_dir' => @conf['conf_dir'],
70
+ '$conf_dir' => CONF_DIR,
74
71
  '~' => Dir.home
75
72
  }.inject(path) { |p, r| p.gsub(r[0], r[1]) }
76
73
  end
@@ -89,6 +86,7 @@ module Zashoku
89
86
  end
90
87
 
91
88
  def save
89
+ return unless save?
92
90
  File.open(self.class::CONF_FILE, 'w') { |f| f.write(YAML.dump(@conf)) }
93
91
  end
94
92
  end
@@ -13,9 +13,9 @@ module Zashoku
13
13
  end
14
14
 
15
15
  def base_conf
16
- merge!(
16
+ Zashoku::Util.deep_merge(
17
17
  Util.get_yaml(File.join(Zashoku::Root, 'config/daemon.yml')),
18
- Util.get_yaml(File.join(Zashoku::AppRoot, 'config/daemon.yml')),
18
+ Util.get_yaml(File.join(Zashoku::CConf[:app][:root], 'config/daemon.yml')),
19
19
  )
20
20
  end
21
21
  end
@@ -13,9 +13,9 @@ module Zashoku
13
13
  end
14
14
 
15
15
  def base_conf
16
- merge!(
16
+ Zashoku::Util.deep_merge(
17
17
  Util.get_yaml(File.join(Zashoku::Root, 'config/view.yml')),
18
- Util.get_yaml(File.join(Zashoku::AppRoot, 'config/view.yml')),
18
+ Util.get_yaml(File.join(Zashoku::CConf[:app][:root], 'config/view.yml')),
19
19
  )
20
20
  end
21
21
  end
@@ -4,13 +4,16 @@ require 'socket'
4
4
  require 'json'
5
5
  require 'thread'
6
6
 
7
+ require 'pry'
8
+
7
9
  module Zashoku
8
10
  module Net
9
11
  class Client
10
12
  attr_accessor :callbacks
11
13
 
12
- def initialize(port, host = Zashoku::Host)
13
- @socket = connect(host, port)
14
+ def initialize(port, host = Zashoku::CConf[:app][:net][:host])
15
+ @host, @port = host, port
16
+ @socket = connect(@host, @port)
14
17
  @alive = true
15
18
 
16
19
  @callbacks = []
@@ -19,11 +22,21 @@ module Zashoku
19
22
  @result_queue = Queue.new
20
23
  @event_queue = Queue.new
21
24
 
25
+ start_threads
26
+
27
+ @semaphore = Mutex.new
28
+ end
29
+
30
+ def start_threads
22
31
  @command_thread = Thread.new { pump_commands! }
23
32
  @results_thread = Thread.new { pump_results! }
24
33
  @events_thread = Thread.new { dispatch_events! }
34
+ end
25
35
 
26
- @semaphore = Mutex.new
36
+ def stop_threads
37
+ @command_thread&.exit
38
+ @results_thread&.exit
39
+ @events_thread&.exit
27
40
  end
28
41
 
29
42
  def self.command(host, port, msg, args = {})
@@ -31,18 +44,31 @@ module Zashoku
31
44
  sock.puts(JSON.generate({'msg' => msg}.merge(args)))
32
45
  result = sock.readline
33
46
  sock.close
34
- JSON.parse(result).map { |k, v| "#{k}: #{v}\n" }.join
47
+ {
48
+ payload: JSON.parse(result).map { |k, v| "#{k}: #{v}\n" }.join,
49
+ status: true
50
+ }
35
51
  rescue Errno::ECONNREFUSED
36
- "error: could not connect connect to server\n"
52
+ {
53
+ payload: "error: could not connect connect to #{host}:#{port}\n",
54
+ status: false
55
+ }
37
56
  rescue EOFError
38
- nil
57
+ {
58
+ payload: nil,
59
+ status: false
60
+ }
39
61
  end
40
62
 
41
- def connect(host, port)
63
+ def connect(host, port, loud_fail: true)
42
64
  TCPSocket.new(host, port)
43
65
  rescue Errno::ECONNREFUSED
44
- puts "error: could not connect to #{host}:#{port}"
45
- exit
66
+ if loud_fail
67
+ puts "error: could not connect to #{host}:#{port}"
68
+ Thread.exit
69
+ end
70
+ @alive = false
71
+ nil
46
72
  end
47
73
 
48
74
  def alive?
@@ -51,9 +77,10 @@ module Zashoku
51
77
 
52
78
  def lost_connection
53
79
  @alive = false
80
+ @socket.close
54
81
  Zashoku.logger.debug('lost connection')
55
82
  Util.alert('no connection')
56
- Thread.exit
83
+ stop_threads
57
84
  end
58
85
 
59
86
  def disconnect
@@ -67,12 +94,11 @@ module Zashoku
67
94
  def command(msg, args = {})
68
95
  return unless alive?
69
96
  @semaphore.synchronize {
97
+ payload = { 'msg' => msg }.merge(args)
98
+ @command_queue << JSON.generate(payload)
70
99
 
71
- payload = { 'msg' => msg }.merge(args)
72
- @command_queue << JSON.generate(payload)
73
-
74
- result = @result_queue.pop
75
- result.keys.length == 1 ? result['response'] : result
100
+ result = @result_queue.pop
101
+ result.keys.length == 1 ? result['response'] : result
76
102
  }
77
103
  end
78
104
 
@@ -102,7 +128,12 @@ module Zashoku
102
128
  rescue JSON::ParserError
103
129
  Zashoku.logger.debug("discarding #{response}, JSON::ParserError")
104
130
  rescue EOFError
131
+ Zashoku.logger.debug('eof error')
105
132
  lost_connection
133
+ rescue IOError
134
+ Util.alert("error: socket#{@socket}")
135
+ #binding.pry
136
+ #exit
106
137
  end
107
138
 
108
139
  def dispatch_events!
data/lib/core/options.rb CHANGED
@@ -23,7 +23,7 @@ module Zashoku
23
23
  end
24
24
 
25
25
  opts.on('-d', '--daemon', 'daemonize the server') do |d|
26
- options[:daemonize] = true
26
+ options[:daemon] = true
27
27
  end
28
28
 
29
29
  opts.on('-g TEMPLATE', '--generate TEMPLATE', 'generate a template') do |template|
@@ -20,6 +20,11 @@ module Zashoku
20
20
  refresh
21
21
  end
22
22
 
23
+ def change_screen_size
24
+ refresh
25
+ changed!
26
+ end
27
+
23
28
  def changed!
24
29
  changed
25
30
  notify_observers
File without changes
@@ -1,10 +1,10 @@
1
1
  # frozen_string_literal: true
2
-
3
- require 'amatch'
2
+ # encoding: utf-8
4
3
 
5
4
  module Zashoku
6
5
  module Util
7
6
  class Readline
7
+ COLOR = "\e[0m"
8
8
  attr_accessor :ac_index, :hy_index, :ac_sorted, :prompt, :x, :y, :history
9
9
 
10
10
  def initialize(prompt = '', ac_tree: {}, history: [])
@@ -14,11 +14,15 @@ module Zashoku
14
14
  @hy_index = 0
15
15
  @ac_sorted = []
16
16
  @tree = ac_tree
17
- @y = Term.rows
17
+ #@y = Term.rows
18
+ end
19
+
20
+ def y
21
+ Term.rows
18
22
  end
19
23
 
20
24
  def draw(string)
21
- print "\e[#{y};0H#{prompt}#{string}\e[K\e[#{y};#{@x + 1}H"
25
+ print "#{COLOR}\e[#{y};0H#{prompt}#{string}\e[K\e[#{y};#{@x + 1}H"
22
26
  end
23
27
 
24
28
  def read(string = '')
@@ -65,6 +69,7 @@ module Zashoku
65
69
  string = string[0...rx] + string[rx..-1]
66
70
  string[x - prompt.length] = ''
67
71
  when 9 #tab
72
+ next if @tree.empty?
68
73
  if @ac_index == 0
69
74
  acl = ac_list(string)
70
75
  @ac_sorted = sort_ac_list(acl, string)
@@ -82,6 +87,7 @@ module Zashoku
82
87
  Curses.beep
83
88
  end
84
89
  else
90
+ Zashoku.logger.debug("unknown key #{c}")
85
91
  Curses.beep
86
92
  end
87
93
  @history[@hy_index] = string
@@ -115,8 +121,7 @@ module Zashoku
115
121
  end
116
122
 
117
123
  def sort_ac_list(list, string)
118
- m = Amatch::JaroWinkler.new(string)
119
- list.map { |e| [m.match(e.to_s), e] }.sort.map { |a| a[1] }.reverse
124
+ list.select { |e| /^#{string}.*/i.match?(e.to_s) }
120
125
  end
121
126
  end
122
127
  end
@@ -17,6 +17,19 @@ module Zashoku
17
17
  {}
18
18
  end
19
19
 
20
+ def self.deep_merge(this, that)
21
+ this&.merge(that || {}) do |_k, old, nu|
22
+ case old
23
+ when Hash
24
+ deep_merge(old, nu)
25
+ #when Array
26
+ # old + nu
27
+ else
28
+ nu
29
+ end
30
+ end
31
+ end
32
+
20
33
  def self.get_yaml(file, nil_value = {})
21
34
  YAML.safe_load(File.open(file, 'r', &:read)) || nil_value
22
35
  rescue Errno::ENOENT
data/lib/core/view.rb CHANGED
@@ -1,10 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # require 'benchmark'
4
-
5
- # require_relative 'color'
6
- # require_relative '../util/util'
7
-
8
3
  module Zashoku
9
4
  class View
10
5
  include Zashoku::Util
@@ -19,6 +14,9 @@ module Zashoku
19
14
  @expanded = -1
20
15
  @selected = 0
21
16
 
17
+ @matches = []
18
+ @match_i = -1
19
+
22
20
  @items_formatted = {}
23
21
 
24
22
  @old_rows = Term.rows
@@ -29,7 +27,47 @@ module Zashoku
29
27
  end
30
28
 
31
29
  def dirty_all_lines
32
- @dirty_lines = 0.step(get_len).to_a
30
+ @dirty_lines = 0.step(Term.rows-2).to_a
31
+ end
32
+
33
+ def next_match
34
+ return if @matches.empty?
35
+ @match_i += 1
36
+
37
+ if @match_i >= @matches.length
38
+ @match_i = 0
39
+ end
40
+
41
+ select(*@matches[@match_i])
42
+ end
43
+
44
+ def previous_match
45
+ return if @matches.empty?
46
+
47
+ @match_i -= 1
48
+
49
+ if @match_i < 0
50
+ @match_i = @matches.length - 1
51
+ end
52
+ select(*@matches[@match_i])
53
+ end
54
+
55
+ def search(term)
56
+ re = /.*#{term}.*/i
57
+ @match_i = -1
58
+ outer = -1
59
+ @matches = @items_formatted.map do |parent, children|
60
+ inner = 0
61
+ outer += 1
62
+ matches = re.match?(parent) ? [[outer, 0]] : []
63
+ matches += children.map do |c|
64
+ [outer, inner+=1] if re.match?(c)
65
+ end.compact
66
+
67
+ matches
68
+ end.flatten(1) #.sort.reverse
69
+ Zashoku.logger.debug(@matches)
70
+ next_match
33
71
  end
34
72
 
35
73
  def unpause; end
@@ -42,21 +80,6 @@ module Zashoku
42
80
  notify_observers
43
81
  end
44
82
 
45
- def auto_update(s: :start)
46
- case s
47
- when :start
48
- @update_thread = Thread.new do
49
- loop do
50
- refresh
51
- changed!
52
- sleep 1
53
- end
54
- end
55
- when :stop
56
- @update_thread.exit if @update_thread
57
- end
58
- end
59
-
60
83
  def change_screen_size(redraw: true)
61
84
  @items_formatted = {}
62
85
  refresh_formats
@@ -144,6 +167,27 @@ module Zashoku
144
167
  changed!
145
168
  end
146
169
 
170
+ def select(out, inr)
171
+ out = out.to_i
172
+ inr = inr.to_i
173
+
174
+ #return if out >= @items.length
175
+ #return if inr >= @items[@expanded].length
176
+ unless inr == 0 || @expanded == out
177
+ oexpanded = @expanded
178
+ @expanded = out
179
+ arr = [@expanded, oexpanded] - [-1]
180
+ @dirty_lines += arr.min.step(@view[1]).to_a
181
+ end
182
+ os = @selected
183
+ @selected = out + inr
184
+
185
+ @dirty_lines += [os, @selected]
186
+
187
+ adjust_view
188
+ changed!
189
+ end
190
+
147
191
  def fix_cursor
148
192
  @selected = 0 if @selected < 0
149
193
  @selected = get_len - 1 if @selected >= get_len
data/lib/daemon.rb CHANGED
@@ -39,7 +39,7 @@ module Zashoku
39
39
  # Load conf
40
40
  Zashoku.conf = DaemonConfig.new
41
41
  # Load modules
42
- Zashoku.modules = Zashoku::Module.load(Zashoku::DaemonModules)
42
+ Zashoku.modules = Zashoku::Module.load(Zashoku::CConf[:app][:modules][:daemon])
43
43
  # Update conf with module defaults
44
44
  Zashoku.conf.reload
45
45
 
@@ -47,16 +47,11 @@ module Zashoku
47
47
  Zashoku.modules.keys.zip(Zashoku.modules.values.map(&:controller)).to_h
48
48
 
49
49
  Zashoku.controllers.each_value { |c| c.add_observer(self) }
50
-
51
- # $stdout.reopen(file, 'w')
52
- # $stderr.reopen(file, 'w')
53
- # $stdout.sync = true
54
- # $stderr.sync = true
55
50
  end
56
51
 
57
52
  def listen
58
53
  lay_traps!
59
- @server = Net::Server.new(Zashoku::Port)
54
+ @server = Net::Server.new(Zashoku::CConf[:app][:net][:port])
60
55
  @server.handler = method(:respond)
61
56
  Zashoku.logger.debug('server listening')
62
57
  sleep
@@ -80,6 +75,8 @@ module Zashoku
80
75
  nil
81
76
  when 'stop'
82
77
  cleanup
78
+ when 'up?'
79
+ true
83
80
  else
84
81
  'what?'
85
82
  end
data/lib/viewer.rb CHANGED
@@ -33,7 +33,9 @@ module Zashoku
33
33
  if /^remote::.*/.match?(message[:mod])
34
34
  message[:mod] = message[:mod].gsub('remote::', '')
35
35
  Zashoku.logger.debug("sending message #{message}")
36
- Zashoku::Util.decode_object(client.command('fwd', message))
36
+ msg = Zashoku::Util.decode_object(client.command('fwd', message))
37
+ Zashoku.logger.debug('got it')
38
+ msg
37
39
  else
38
40
  modules[message[:mod]].send(message[:meth], *message[:args])
39
41
  end
@@ -44,30 +46,26 @@ module Zashoku
44
46
  class Viewer
45
47
  include Util
46
48
 
47
- HISTORY = File.join(Zashoku::Config::CONF_DIR, 'cmd_history.yml')
49
+ CMD_HISTORY = File.join(Zashoku::Config::CONF_DIR, 'cmd_history.yml')
50
+ SRCH_HISTORY = File.join(Zashoku::Config::CONF_DIR, 'srch_history.yml')
48
51
 
49
- COMMANDS = {
50
- 'quit' => :cleanup,
51
- 'enter_command' => :get_user_command,
52
- 'change_view' => :change_view,
53
- 'map_key' => :map_key
54
- }.freeze
52
+ COMMANDS = Zashoku::CConf[:core][:commands].merge(Zashoku::CConf[:app][:commands])
55
53
 
56
54
  def initialize
57
55
  @semaphore = Mutex.new
58
56
 
59
57
  Zashoku.logger = Logger.new(
60
- File.join(Zashoku::AppRoot, "#{Zashoku::AppName}.log")
58
+ File.join(Zashoku::CConf[:app][:root], "#{Zashoku::CConf[:app][:name]}.log")
61
59
  )
62
60
 
63
61
  Zashoku.conf = ViewConfig.new
64
62
 
65
- Zashoku.modules = Zashoku::Module.load(Zashoku::ViewerModules)
63
+ Zashoku.modules = Zashoku::Module.load(Zashoku::CConf[:app][:modules][:viewer])
66
64
  Zashoku.modules.merge!('conf' => Conf)
67
65
  Zashoku.conf.reload
68
66
 
69
67
  # note: start daemon if not running
70
- Zashoku.client = Net::Client.new(Zashoku::Port)
68
+ Zashoku.client = Net::Client.new(Zashoku::CConf[:app][:net][:port])
71
69
  Zashoku.client.callbacks << method(:handle_event)
72
70
 
73
71
  @server_modules = Zashoku.client.command('modules')
@@ -89,8 +87,9 @@ module Zashoku
89
87
  .merge(COMMANDS.map { |k, _v| [k, nil] }.to_h)
90
88
  .merge({'conf' => Zashoku.conf.methods - Object.methods })
91
89
  .merge(@server_modules.map { |m| ['remote::' + m, nil] }.to_h),
92
- history: Util.get_yaml(HISTORY, [])
90
+ history: Util.get_yaml(CMD_HISTORY, [])
93
91
  )
92
+ @searchline = Util::Readline.new('/', history: Util.get_yaml(SRCH_HISTORY, []))
94
93
 
95
94
  init_screen
96
95
  lay_traps!
@@ -102,6 +101,18 @@ module Zashoku
102
101
  sleep
103
102
  end
104
103
 
104
+ def reconnect_client
105
+ loop do
106
+ @socket = connect(@host, @port, loud_fail: false)
107
+ break if @socket
108
+ sleep 1
109
+ end
110
+
111
+ @alive = true
112
+ start_threads
113
+ Util.alert('regained connection!')
114
+ end
115
+
105
116
  def change_view(new_view)
106
117
  Zashoku.logger.debug("Changing view to #{new_view}")
107
118
  @views[@view].delete_observers
@@ -121,12 +132,15 @@ module Zashoku
121
132
  def lay_traps!
122
133
  Signal.trap('WINCH') do
123
134
  Thread.new do
124
- @semaphore.synchronize { @views[@view].change_screen_size }
135
+ @semaphore.synchronize do
136
+ @views[@view].change_screen_size
137
+ @statusline.change_screen_size
138
+ end
125
139
  end
126
140
  end
127
141
  Signal.trap('INT') do
128
- Thread.new do
129
- @semaphore.synchronize { cleanup }
142
+ Thread.new do
143
+ @semaphore.synchronize { Util.alert('Type :quit<enter> to exit.') }
130
144
  end
131
145
  end
132
146
  end
@@ -134,10 +148,15 @@ module Zashoku
134
148
  def cleanup
135
149
  Zashoku.client.disconnect
136
150
  @key_thread&.exit
151
+ Zashoku.command_server('stop') if Zashoku::CConf[:app][:persistent_daemon]
137
152
  Curses.close_screen
138
- Util.put_yaml(HISTORY, @cmdline.history)
153
+ if Zashoku::Conf.save?
154
+ Util.put_yaml(CMD_HISTORY, @cmdline.history)
155
+ Util.put_yaml(SRCH_HISTORY, @searchline.history)
156
+ end
157
+ ensure
139
158
  Term.show_cursor
140
- exit
159
+ exit!
141
160
  end
142
161
 
143
162
  def init_screen
@@ -152,6 +171,10 @@ module Zashoku
152
171
  Zashoku.command(mod: mod, meth: meth, args: args)
153
172
  elsif @views.key?(mod) && @views[mod].respond_to?(meth)
154
173
  @views[mod].send(meth, *args)
174
+ elsif @views.key?(mod)
175
+ raise "#{mod} has no method '#{meth}'"
176
+ else
177
+ raise "module '#{mod}' not loaded"
155
178
  end
156
179
  end
157
180
 
@@ -159,10 +182,16 @@ module Zashoku
159
182
  cmd = @cmdline.read
160
183
  return unless cmd
161
184
  return builtin_command(*cmd.split) if COMMANDS.key?(cmd.split.first)
162
-
185
+ raise "no such command" if cmd.split.length == 1
163
186
  command(*cmd.split) unless cmd.empty?
164
- rescue
165
- Util.alert('Error')
187
+ rescue StandardError => e
188
+ Zashoku.logger.debug("#{cmd.split} raised an error '#{e}'")
189
+ Util.alert("Error: #{e}")
190
+ end
191
+
192
+ def search(*)
193
+ srchterm = @searchline.read
194
+ command(@view, :search, srchterm)
166
195
  end
167
196
 
168
197
  def handle_event(event)
@@ -179,8 +208,12 @@ module Zashoku
179
208
  send(COMMANDS[cmd], *args)
180
209
  end
181
210
 
182
- def map_key(key, mod, command, *args)
183
- Zashoku.conf.set(['keymaps', mod, key], "#{command} #{args.join(' ')}")
211
+ def map_key(key, mod, *command)
212
+ Zashoku.conf.set(['keymaps', mod, key], command.join(' '))
213
+ end
214
+
215
+ def print_version
216
+ Util.alert("zashoku v#{Zashoku::Version.join('.')}")
184
217
  end
185
218
 
186
219
  def scan_keyboard!
@@ -202,7 +235,7 @@ module Zashoku
202
235
  end
203
236
 
204
237
  mod, meth, *args = cmd.split
205
- mod = mod == 'current_view' ? @view : mod
238
+ mod = mod == '$current_view' ? @view : mod
206
239
  args.map! do |arg|
207
240
  if arg.chr == '$'
208
241
  arg = arg[1..-1]
@@ -214,7 +247,11 @@ module Zashoku
214
247
  arg
215
248
  end
216
249
  end
217
- command(mod, meth, *args)
250
+ begin
251
+ command(mod, meth, *args)
252
+ rescue Exception => e
253
+ Zashoku.logger.debug("#{[mod, meth, args].join(', ')} raised #{e}")
254
+ end
218
255
  end
219
256
  end
220
257
 
data/lib/zashoku.rb CHANGED
@@ -1,22 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative 'core/options'
4
+ require_relative 'constants'
4
5
 
5
6
  module Zashoku
6
- Version = [1, 3, 2].freeze
7
- Root = File.expand_path('../', __dir__)
8
-
9
- AppRoot = Root unless const_defined?(:AppRoot)
10
- AppName = 'zashoku' unless const_defined?(:AppName)
11
- ViewerModules = [] unless const_defined?(:ViewerModules)
12
- DaemonModules = [] unless const_defined?(:DaemonModules)
13
- Host = 'localhost' unless const_defined?(:Host)
14
- Port = 26_119 unless const_defined?(:Port)
15
-
16
- LoadPaths = [
17
- File.join(Zashoku::AppRoot, 'modules')
18
- ].freeze
19
-
20
7
  autoload :Generator, File.join(Root, 'lib/generator')
21
8
  autoload :Viewer, File.join(Root, 'lib/viewer')
22
9
  autoload :Daemon, File.join(Root, 'lib/daemon')
@@ -32,25 +19,48 @@ module Zashoku
32
19
  end
33
20
 
34
21
  def self.main(args)
35
- options = Options.parse(args)
22
+ @options = Options.parse(args)
36
23
  Zashoku.modules = []
37
24
 
38
- if options[:generate]
39
- Generator.generate(options[:template], options[:generate_name])
40
- elsif options[:server_command]
41
- command_server(options[:server_command])
25
+ if @options[:generate]
26
+ Generator.generate(@options[:template], @options[:generate_name])
27
+ elsif @options[:server_command]
28
+ print command_server(@options[:server_command])[:payload]
42
29
  else
30
+ unless command_server('up?')[:status]
31
+ @options[:daemon] = true
32
+ command_server('start')
33
+ sleep(0.2) until command_server('up?')[:status]
34
+ end
43
35
  Viewer.new.run
44
36
  end
45
37
  end
46
38
 
39
+ def self.start_daemon
40
+ if @options[:daemon]
41
+ fork {
42
+ Process.daemon()
43
+ Daemon.new.listen
44
+ }
45
+ else
46
+ Daemon.new.listen
47
+ end
48
+ end
49
+
47
50
  def self.command_server(command)
48
51
  case command
49
52
  when 'start'
50
- Daemon.new.listen
53
+ start_daemon
54
+ when 'restart'
55
+ command_server('stop')
56
+ start_daemon
51
57
  else
52
58
  require_relative 'core/net/client'
53
- print Net::Client.command(Zashoku::Host, Zashoku::Port, command)
59
+ Net::Client.command(
60
+ Zashoku::CConf[:app][:net][:host],
61
+ Zashoku::CConf[:app][:net][:port],
62
+ command
63
+ )
54
64
  end
55
65
  end
56
66
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: zashoku
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.2
4
+ version: 1.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - annacrombie
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-10-20 00:00:00.000000000 Z
11
+ date: 2017-11-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: curses
@@ -120,6 +120,7 @@ files:
120
120
  - "./README.md"
121
121
  - "./config/daemon.yml"
122
122
  - "./config/view.yml"
123
+ - "./lib/constants.rb"
123
124
  - "./lib/core/config/config.rb"
124
125
  - "./lib/core/config/daemon_config.rb"
125
126
  - "./lib/core/config/view_config.rb"
@@ -135,6 +136,7 @@ files:
135
136
  - "./lib/core/statusline/statusline.rb"
136
137
  - "./lib/core/statusline/widget.rb"
137
138
  - "./lib/core/util/folder_listen.rb"
139
+ - "./lib/core/util/matcher.rb"
138
140
  - "./lib/core/util/readline.rb"
139
141
  - "./lib/core/util/term.rb"
140
142
  - "./lib/core/util/util.rb"