liberator 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/lib/dir.rb ADDED
@@ -0,0 +1,12 @@
1
+ class Dir
2
+ def self.real_entries(path)
3
+ Dir.entries(path).select do |entry|
4
+ absolute_path = path + '/' + entry
5
+ !File.symlink?(absolute_path) && entry != '.' && entry != '..'
6
+ end
7
+ end
8
+
9
+ def self.size(path)
10
+ `du -ks "#{path}"`.split("\t").first.to_i if Dir.exists? path
11
+ end
12
+ end
@@ -0,0 +1,45 @@
1
+ module Liberator
2
+ class Controller
3
+ def initialize(view=nil)
4
+ @view = view
5
+ @directory = Directory.new Dir.pwd
6
+ render
7
+ end
8
+
9
+ def listen
10
+ loop do
11
+ handle_key @view.capture_keystroke unless @view.nil?
12
+ end
13
+ end
14
+
15
+ def handle_key(key)
16
+ case key
17
+ when 'q'
18
+ @view.close
19
+ exit
20
+ when 'j'
21
+ @directory.select_next_entry
22
+ render
23
+ when 'k'
24
+ @directory.select_previous_entry
25
+ render
26
+ when 10
27
+ if File.directory? @directory.selected_entry[:path]
28
+ @directory = Directory.new @directory.selected_entry[:path]
29
+ render
30
+ end
31
+ when 'h'
32
+ @directory = @directory.parent
33
+ render
34
+ when 'x'
35
+ @directory.delete_selected_entry if @view.confirm_delete
36
+ @directory.refresh
37
+ render
38
+ end
39
+ end
40
+
41
+ def render
42
+ @view.refresh(@directory.path, @directory.entries, @directory.selected_index) unless @view.nil?
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,48 @@
1
+ module Liberator
2
+ class Directory
3
+ attr_reader :path, :entries, :selected_index
4
+ def initialize(path)
5
+ @path = File.expand_path path
6
+ cache_entries
7
+ end
8
+
9
+ def selected_entry
10
+ @entries[@selected_index]
11
+ end
12
+
13
+ def select_previous_entry
14
+ @selected_index -= 1 if @selected_index > 0
15
+ end
16
+
17
+ def select_next_entry
18
+ @selected_index += 1 unless @selected_index >= @entries.size-1
19
+ end
20
+
21
+ def parent
22
+ Directory.new File.expand_path(@path + '/..')
23
+ end
24
+
25
+ def delete_selected_entry
26
+ FileUtils.rm_rf selected_entry[:path]
27
+ end
28
+
29
+ def refresh
30
+ @entries = Dir.real_entries(@path).collect do |entry|
31
+ absolute_path = @path + '/' + entry
32
+
33
+ if File.file? absolute_path
34
+ size = File.size absolute_path
35
+ elsif File.directory? absolute_path
36
+ size = Dir.size absolute_path
37
+ else
38
+ next
39
+ end
40
+
41
+ { path: absolute_path, size: size }
42
+ end
43
+ @entries = @entries.compact.sort_by { |entry| 1.0/entry[:size].to_f }
44
+ @selected_index = 0
45
+ end
46
+ alias_method :cache_entries, :refresh
47
+ end
48
+ end
@@ -0,0 +1,89 @@
1
+ module Liberator
2
+ class View
3
+ GIGABYTE = 1048576
4
+ MEGABYTE = 1024
5
+
6
+ def initialize
7
+ # Initialize curses view.
8
+ Curses.init_screen
9
+ Curses.noecho
10
+ Curses.curs_set 0
11
+ Curses.cbreak
12
+ @height = Curses.stdscr.maxy
13
+ @width = Curses.stdscr.maxx
14
+
15
+ @entry_window = Curses::Window.new @height-1, @width, 0, 0
16
+
17
+ @status_bar = Curses::Window.new 1, @width, @height-1, 0
18
+ @status_bar.standout
19
+
20
+ @scroll_offset = 0
21
+ end
22
+
23
+ def refresh(directory, entries, selected_index)
24
+ height = @entry_window.maxy
25
+
26
+ # Clear the screen manually, since clear function causes blinking.
27
+ @entry_window.setpos 0, 0
28
+ height.times { @entry_window.deleteln }
29
+
30
+ # Figure out what to draw based on the selected entry and height of the window.
31
+ if selected_index < height-1
32
+ visible_range = (0...height)
33
+ elsif selected_index == entries.size-1 # last item selected
34
+ visible_range = (entries.size-height..entries.size)
35
+ else
36
+ visible_range = (selected_index-height+2..selected_index+1)
37
+ end
38
+
39
+ entries[visible_range].each_with_index do |entry, index|
40
+ # Turn on highlighting, if this entry is selected.
41
+ @entry_window.standout if index+visible_range.begin == selected_index
42
+
43
+ # Get the file/directory name, without its full path.
44
+ name = entry[:path][entry[:path].rindex('/')+1..-1]
45
+ name += '/' if File.directory? entry[:path]
46
+
47
+ # Add the row to the window, appending a right-justified human-readable size.
48
+ @entry_window << name + formatted_size(entry[:size]).rjust(@entry_window.maxx - name.length)
49
+
50
+ # Stop highlighting.
51
+ @entry_window.standend
52
+ end
53
+
54
+ update_status_bar directory
55
+ end
56
+
57
+ def update_status_bar(content)
58
+ @status_bar.setpos 0, 0
59
+ formatted_content = content.ljust @width
60
+ @status_bar << formatted_content
61
+
62
+ @status_bar.refresh
63
+ end
64
+
65
+ def formatted_size(size)
66
+ if size > GIGABYTE
67
+ "#{size / GIGABYTE} GB"
68
+ elsif size > MEGABYTE
69
+ "#{size / MEGABYTE} MB"
70
+ else
71
+ "#{size} KB"
72
+ end
73
+ end
74
+
75
+ def capture_keystroke
76
+ @entry_window.getch
77
+ end
78
+
79
+ def confirm_delete
80
+ update_status_bar "Really delete? (y to confirm)"
81
+ capture_keystroke == 'y'
82
+ end
83
+
84
+ def close
85
+ # Clean up curses view.
86
+ Curses.close_screen
87
+ end
88
+ end
89
+ end
data/lib/liberator.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require 'curses'
2
+ require 'fileutils'
2
3
 
3
4
  require_relative 'dir'
4
5
  require_relative 'liberator/directory'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: liberator
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -20,7 +20,11 @@ executables:
20
20
  extensions: []
21
21
  extra_rdoc_files: []
22
22
  files:
23
+ - lib/dir.rb
23
24
  - lib/liberator.rb
25
+ - lib/liberator/controller.rb
26
+ - lib/liberator/directory.rb
27
+ - lib/liberator/view.rb
24
28
  - bin/liberator
25
29
  homepage: https://github.com/jmacdonald/liberator
26
30
  licenses: []