]> git.cworth.org Git - sup/blob - lib/sup/mode.rb
move open3 require to correct file
[sup] / lib / sup / mode.rb
1 require 'open3'
2 module Redwood
3
4 class Mode
5   attr_accessor :buffer
6   @@keymaps = {}
7
8   def self.register_keymap keymap=nil, &b
9     keymap = Keymap.new(&b) if keymap.nil?
10     @@keymaps[self] = keymap
11   end
12
13   def initialize
14     @buffer = nil
15   end
16
17   def self.make_name s; s.gsub(/.*::/, "").camel_to_hyphy; end
18   def name; Mode.make_name self.class.name; end
19
20   def self.load_all_modes dir
21     Dir[File.join(dir, "*.rb")].each do |f|
22       $stderr.puts "## loading mode #{f}"
23       require f
24     end
25   end
26
27   def killable?; true; end
28   def unsaved?; false end
29   def draw; end
30   def focus; end
31   def blur; end
32   def cancel_search!; end
33   def in_search?; false end
34   def status; ""; end
35   def resize rows, cols; end
36   def cleanup
37     @buffer = nil
38   end
39
40   def resolve_input c
41     ancestors.each do |klass| # try all keymaps in order of ancestry
42       next unless @@keymaps.member?(klass)
43       action = BufferManager.resolve_input_with_keymap c, @@keymaps[klass]
44       return action if action
45     end
46     nil
47   end
48
49   def handle_input c
50     action = resolve_input(c) or return false
51     send action
52     true
53   end
54
55   def help_text
56     used_keys = {}
57     ancestors.map do |klass|
58       km = @@keymaps[klass] or next
59       title = "Keybindings from #{Mode.make_name klass.name}"
60       s = <<EOS
61 #{title}
62 #{'-' * title.display_length}
63
64 #{km.help_text used_keys}
65 EOS
66       begin
67         used_keys.merge! km.keysyms.to_boolean_h
68       rescue ArgumentError
69         raise km.keysyms.inspect
70       end
71       s
72     end.compact.join "\n"
73   end
74
75 ### helper functions
76
77   def save_to_file fn
78     if File.exists? fn
79       return unless BufferManager.ask_yes_or_no "File exists. Overwrite?"
80     end
81     begin
82       File.open(fn, "w") { |f| yield f }
83       BufferManager.flash "Successfully wrote #{fn}."
84     rescue SystemCallError, IOError => e
85       BufferManager.flash "Error writing to file: #{e.message}"
86     end
87   end
88
89   def pipe_to_process command
90     Open3.popen3(command) do |input, output, error|
91       err, data, * = IO.select [error], [input], nil
92
93       unless err.empty?
94         message = err.first.read
95         if message =~ /^\s*$/
96           warn "error running #{command} (but no error message)"
97           BufferManager.flash "Error running #{command}!"
98         else
99           warn "error running #{command}: #{message}"
100           BufferManager.flash "Error: #{message}"
101         end
102         return
103       end
104
105       data = data.first
106       data.sync = false # buffer input
107
108       yield data
109       data.close # output will block unless input is closed
110
111       ## BUG?: shows errors or output but not both....
112       data, * = IO.select [output, error], nil, nil
113       data = data.first
114
115       if data.eof
116         BufferManager.flash "'#{command}' done!"
117         nil
118       else
119         data.read
120       end
121     end
122   end
123 end
124
125 end