]> git.cworth.org Git - sup/blob - lib/sup/modes/file-browser-mode.rb
rejigger alignment of messages when using 'n' and 'p'
[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     jump_to_start
42     buffer.mark_dirty
43   end
44
45   def view
46      name, f = @files[curpos - RESERVED_ROWS]
47     return unless f && f.file?
48
49     begin
50       BufferManager.spawn f.to_s, TextMode.new(f.read)
51     rescue SystemCallError => e
52       BufferManager.flash e.message
53     end
54   end
55
56   def select_file_or_follow_directory
57     name, f = @files[curpos - RESERVED_ROWS]
58     return unless f
59
60     if f.directory? && f.to_s != "."
61       if f.readable?
62         @dirs.push f
63         reload
64       else
65         BufferManager.flash "Permission denied - #{f.realpath}"
66       end
67     else
68       begin
69         @value = f.realpath.to_s
70         @done = true
71       rescue SystemCallError => e
72         BufferManager.flash e.message
73       end
74     end
75   end
76
77   def regen_text
78     @files = 
79       begin
80         cwd.entries.sort_by do |f|
81           [f.directory? ? 0 : 1, f.basename.to_s]
82         end
83       rescue SystemCallError => e
84         BufferManager.flash "Error: #{e.message}"
85         [Pathname.new("."), Pathname.new("..")]
86       end.map do |f|
87       real_f = cwd + f
88       name = f.basename.to_s +
89         case
90         when real_f.symlink?
91           "@"
92         when real_f.directory?
93           "/"
94         else
95           ""
96         end
97       [name, real_f]
98     end
99
100     size_width = @files.max_of { |name, f| f.human_size.length }
101     time_width = @files.max_of { |name, f| f.human_time.length }
102
103     @text = ["#{cwd}:"] + @files.map do |name, f|
104       sprintf "%#{time_width}s %#{size_width}s %s", f.human_time, f.human_size, name
105     end
106   end
107 end
108
109 end