zashoku 1.3.2 → 1.5.0

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