liberator 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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: []