]> git.cworth.org Git - sup/blob - lib/sup/modes/file-browser-mode.rb
bugfix: thread correctly in resumed/killed draft messages
[sup] / lib / sup / modes / file-browser-mode.rb
1 require 'pathname'
2
3 module Redwood
4
5 ## meant to be spawned via spawn_modal!
6 class FileBrowserMode < LineCursorMode
7   RESERVED_ROWS = 1
8
9   register_keymap do |k|
10     k.add :back, "Go back to previous directory", "B"
11     k.add :view, "View file", "v"
12     k.add :select_file_or_follow_directory, "Select the highlighted file, or follow the directory", :enter
13     k.add :reload, "Reload file list", "R"
14   end
15
16   bool_reader :done
17   attr_reader :value
18
19   def initialize dir="."
20     @dirs = [Pathname.new(dir).realpath]
21     @done = false
22     @value = nil
23     regen_text
24     super :skip_top_rows => RESERVED_ROWS
25   end
26
27   def cwd; @dirs.last end
28   def lines; @text.length; end
29   def [] i; @text[i]; end
30
31 protected
32   
33   def back
34     return if @dirs.size == 1
35     @dirs.pop
36     reload
37   end
38
39   def reload
40     regen_text
41     buffer.mark_dirty
42   end
43
44   def view
45      name, f = @files[curpos - RESERVED_ROWS]
46     return unless f && f.file?
47
48     begin
49       BufferManager.spawn f.to_s, TextMode.new(f.readlines.join)
50     rescue SystemCallError => e
51       BufferManager.flash e.message
52     end
53   end
54
55   def select_file_or_follow_directory
56     name, f = @files[curpos - RESERVED_ROWS]
57     return unless f
58
59     if f.directory? && f.to_s != "."
60       if f.readable?
61         @dirs.push f
62         reload
63       else
64         BufferManager.flash "Permission denied - #{f.realpath}"
65       end
66     else
67       begin
68         @value = f.realpath.to_s
69         @done = true
70       rescue SystemCallError => e
71         BufferManager.flash e.message
72       end
73     end
74   end
75
76   def regen_text
77     @files = 
78       begin
79         cwd.entries.sort_by do |f|
80           [f.directory? ? 0 : 1, f.basename.to_s]
81         end
82       rescue SystemCallError => e
83         BufferManager.flash "Error: #{e.message}"
84         [Pathname.new("."), Pathname.new("..")]
85       end.map do |f|
86       real_f = cwd + f
87       name = f.basename.to_s +
88         case
89         when real_f.symlink?
90           "@"
91         when real_f.directory?
92           "/"
93         else
94           ""
95         end
96       [name, real_f]
97     end
98
99     size_width = @files.max_of { |name, f| f.human_size.length }
100     time_width = @files.max_of { |name, f| f.human_time.length }
101
102     @text = ["#{cwd}:"] + @files.map do |name, f|
103       sprintf "%#{time_width}s %#{size_width}s %s", f.human_time, f.human_size, name
104     end
105   end
106 end
107
108 end