terminal-file-picker 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cd5a569d7a6b4c67c640aef2acf33f800441b44bd780cd3d3330b396fdb0ff7a
4
- data.tar.gz: 6fe26dd58337aa9e21a535c52bf2d96c582c5fd3c531a6e67cd4f69503211f80
3
+ metadata.gz: f07dbb5a7aa9a96128b360a8c326301aac7cad3783a9962bf7a99b9921f769bb
4
+ data.tar.gz: 49164b98d2645238d09777eda25d28272089a7e2d7f6cc12c6d2b2352e1ccfba
5
5
  SHA512:
6
- metadata.gz: 6b857a6b4a7d337d5d080d399135957323480b6ef0e76f3c89ece5951f064fd314d3b287ea7893e14ed7e91979042a97d205bc432e8e261494f2c488cb86b807
7
- data.tar.gz: 27c8dfc8ed0ce2208bf0f169795fac5d528757d2c4bed3d019bf33320cffeab67fadaa71760e4cf77df639b2f8f2727f53e59800d17d9ece24a6342fc3b36140
6
+ metadata.gz: ca6b198dada64c7612e21130f9a01b6f960008c91eacdd5a4b6315d845bc7f6d2da64b28fe4cec4ca72e5be3be097d6788ff2a2b4214c5f0736e7d071cedf814
7
+ data.tar.gz: 032e125883ceac5aeb4ab844602640aff05c02026b30a1b1f04d12cfaaaccfdd303592bc7aa93e132d18945af00a37142a3e81763aa660f09f4d59621038c490
data/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/terminal-file-picker.svg)](https://badge.fury.io/rb/terminal-file-picker)
4
4
 
5
- <img alt="Gif showing usage" src="https://raw.githubusercontent.com/ilkutkutlar/terminal-file-picker/master/usage.gif" width=70%>
5
+ <img alt="Gif showing usage" src="https://raw.githubusercontent.com/ilkutkutlar/terminal-file-picker/main/usage.gif" width=70%>
6
6
 
7
7
  This gem shows an interactive terminal file picker to user, allowing them to browse their files with arrow keys and file. The picked file path is then returned to the calling program. The file picker is completely text-based and can be used with a terminal or terminal emulator. It is essentially a terminal version of a GUI file choosing dialogue.
8
8
 
@@ -25,15 +25,15 @@ gem 'terminal-file-picker'
25
25
  # Simple Usage
26
26
 
27
27
  ```rb
28
- # Only required argument is the "root path". The user starts
29
- # navigating from the root path and the returned path of
30
- # the chosen file is relative to this root path.
28
+ # Only required argument is the "root path". The user will
29
+ # start navigating from the root path once file picker is invoked.
30
+ # Root path can be either absolute or relative.
31
31
  picker = FilePicker.new('.')
32
32
 
33
- # This brings up the interactive file picker. Once the user
34
- # has picked a file, the picker is cleared from screen and
35
- # the chosen file path returned.
36
33
 
34
+ # `pick_file` brings up the interactive file picker. Once the user
35
+ # has picked a file, the picker is cleared from screen and
36
+ # the chosen file path (as an absolute path) is returned.
37
37
  # If user picks a directory, instead of returning its path,
38
38
  # the files inside the chosen directory is shown instead.
39
39
  puts(picker.pick_file)
@@ -0,0 +1,70 @@
1
+ require 'pry'
2
+
3
+ # Functions related to retrieving and formatting
4
+ # information related to directories and their contents.
5
+ class FileBrowserModel
6
+ attr_accessor :selected, :page, :current_path, :files
7
+
8
+ def initialize(starting_path, options = {})
9
+ @options = options
10
+ @current_path = starting_path
11
+ @page = 0
12
+ @selected = 0
13
+ @files = order_files(files_in_dir)
14
+ end
15
+
16
+ def files_in_dir
17
+ date_format = @options.fetch(:date_format, '%d/%m/%Y')
18
+ time_format = @options.fetch(:time_format, '%H:%M')
19
+
20
+ Dir.entries(@current_path).map do |f|
21
+ file_path = File.join(@current_path, f)
22
+
23
+ name = add_indicator(f)
24
+
25
+ size_bytes = File.size(file_path)
26
+
27
+ mtime = File.mtime(file_path)
28
+ date_mod = mtime.strftime(date_format)
29
+ time_mod = mtime.strftime(time_format)
30
+
31
+ [name, size_bytes, date_mod, time_mod]
32
+ end
33
+ end
34
+
35
+ # Order files such that '.' and '..' come before
36
+ # all the other files.
37
+ def order_files(files)
38
+ # Put "." and ".." at the start
39
+ groups = files.group_by do |f|
40
+ if f.first == './' || f.first == '../'
41
+ :dots
42
+ else
43
+ :files
44
+ end
45
+ end
46
+
47
+ # Sort so that "." comes before ".."
48
+ (groups[:dots] || []).sort.reverse + (groups[:files] || [])
49
+ end
50
+
51
+ # Absolute path of the currently selected file
52
+ def selected_absolute_path
53
+ selected_file_name = @files[@selected].first
54
+ # This may not be the absolute path (e.g. file_name may be '.')
55
+ selected_full_path = File.join(@current_path, selected_file_name)
56
+ File.absolute_path(selected_full_path)
57
+ end
58
+
59
+ def path_rel_to_start(file_name)
60
+ File.join(@current_path, file_name)
61
+ end
62
+
63
+ private
64
+
65
+ def add_indicator(file_name)
66
+ return "#{file_name}/" if File.directory?(path_rel_to_start(file_name))
67
+
68
+ file_name
69
+ end
70
+ end
@@ -1,24 +1,24 @@
1
+ require 'pry'
1
2
  require 'tty-cursor'
2
3
  require 'tty-reader'
3
4
  require_relative 'file_browser_view'
4
5
  require_relative 'helper'
6
+ require_relative 'file_browser_model'
5
7
 
6
8
  # Responsible for keeping the state of the interactive file picker.
7
9
  # Also responds to user input to modify the state and redraw
8
10
  # file picker to reflect new state.
9
11
  class FilePicker
10
- def initialize(dir_path, options = {})
11
- @root_path = dir_path
12
- @dir = FileBrowserView.new(options)
12
+ def initialize(start_dir_path, options = {})
13
+ @model = FileBrowserModel.new(start_dir_path, options)
14
+ @view = FileBrowserView.new(options)
13
15
  @reader = TTY::Reader.new(interrupt: :exit)
14
16
  @reader.subscribe(self)
15
- @user_have_picked = false
16
- @page = 0
17
17
  @cursor = TTY::Cursor
18
+ @user_have_picked = false
18
19
 
19
- @date_format = options.fetch(:date_format, '%d/%m/%Y')
20
- @time_format = options.fetch(:time_format, '%H:%M')
21
- change_directory(dir_path)
20
+ absolute_start_path = File.absolute_path(start_dir_path)
21
+ change_directory(absolute_start_path)
22
22
  end
23
23
 
24
24
  def pick_file
@@ -30,22 +30,22 @@ class FilePicker
30
30
  end
31
31
 
32
32
  print(@cursor.clear_screen_down)
33
- full_path_of_selected
33
+ @model.selected_absolute_path
34
34
  end
35
35
 
36
36
  def keydown(_event)
37
- @selected += 1 unless selected_at_bottom?
37
+ @model.selected += 1 unless selected_at_bottom?
38
38
  if selected_below_page?
39
- @page += 1
39
+ @model.page += 1
40
40
  print(@cursor.clear_screen_down)
41
41
  end
42
42
  redraw(true)
43
43
  end
44
44
 
45
45
  def keyup(_event)
46
- @selected -= 1 unless selected_at_top?
46
+ @model.selected -= 1 unless selected_at_top?
47
47
  if selected_above_page?
48
- @page -= 1
48
+ @model.page -= 1
49
49
  print(@cursor.clear_screen_down)
50
50
  end
51
51
  redraw(true)
@@ -54,8 +54,10 @@ class FilePicker
54
54
  def keypress(event)
55
55
  case event.value
56
56
  when "\r"
57
- if File.directory?(full_path_of_selected)
58
- change_directory(full_path_of_selected)
57
+ selected = @model.selected_absolute_path
58
+
59
+ if File.directory?(selected)
60
+ change_directory(selected)
59
61
  print(@cursor.clear_screen_down)
60
62
  # Cache keeps a rendering of current directory.
61
63
  # Going to a new directory, so needs to refresh
@@ -69,78 +71,35 @@ class FilePicker
69
71
 
70
72
  private
71
73
 
74
+ def change_directory(absolute_file_path)
75
+ @model.current_path = absolute_file_path
76
+ @model.page = 0
77
+ @model.selected = 0
78
+ @model.files = @model.order_files(@model.files_in_dir)
79
+ end
80
+
72
81
  def redraw(use_cache)
73
- rendered = @dir.render(@current_path, @files, @selected, @page, use_cache)
82
+ rendered = @view.render(@model.current_path,
83
+ @model.files,
84
+ @model.selected,
85
+ @model.page,
86
+ use_cache)
74
87
  Helper.print_in_place(rendered)
75
88
  end
76
89
 
77
90
  def selected_at_top?
78
- @selected.zero?
91
+ @model.selected.zero?
79
92
  end
80
93
 
81
94
  def selected_at_bottom?
82
- @selected == @files.length - 1
95
+ @model.selected == @model.files.length - 1
83
96
  end
84
97
 
85
98
  def selected_above_page?
86
- @selected < (@page * @dir.files_per_page)
99
+ @model.selected < (@model.page * @view.files_per_page)
87
100
  end
88
101
 
89
102
  def selected_below_page?
90
- @selected > (@page * @dir.files_per_page) + @dir.files_per_page - 1
91
- end
92
-
93
- def files_in_dir(dir_path)
94
- Dir.entries(dir_path).map do |f|
95
- size_bytes = File.size(full_path(f))
96
-
97
- mtime = File.mtime(full_path(f))
98
- date_mod = mtime.strftime(@date_format)
99
- time_mod = mtime.strftime(@time_format)
100
-
101
- name = file_display_name(f)
102
-
103
- [name, size_bytes, date_mod, time_mod]
104
- end
105
- end
106
-
107
- def change_directory(full_path)
108
- @page = 0
109
- @selected = 0
110
- @current_path = full_path
111
- @files = order_files(files_in_dir(@current_path))
112
- end
113
-
114
- def order_files(files)
115
- # Put "." and ".." at the start
116
- groups = files.group_by do |f|
117
- if f.first == '.' || f.first == '..'
118
- :dots
119
- else
120
- :files
121
- end
122
- end
123
-
124
- # Sort so that "." comes before ".."
125
- (groups[:dots] || []).sort + (groups[:files] || [])
126
- end
127
-
128
- def full_path(file_name)
129
- return @current_path if file_name == '.'
130
- return "#{@current_path}#{file_name}" if @current_path[-1] == '/'
131
-
132
- "#{@current_path}/#{file_name}"
133
- end
134
-
135
- def full_path_of_selected
136
- full_path(@files[@selected].first)
137
- end
138
-
139
- def file_display_name(file_name)
140
- if File.directory?(full_path(file_name))
141
- return "#{file_name}/" unless ['.', '..'].include?(file_name)
142
- end
143
-
144
- file_name
103
+ @model.selected > (@model.page * @view.files_per_page) + @view.files_per_page - 1
145
104
  end
146
105
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: terminal-file-picker
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ilkut Kutlar
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-06-13 00:00:00.000000000 Z
11
+ date: 2020-08-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: pastel
@@ -105,6 +105,7 @@ extra_rdoc_files: []
105
105
  files:
106
106
  - README.md
107
107
  - lib/terminal-file-picker.rb
108
+ - lib/terminal-file-picker/file_browser_model.rb
108
109
  - lib/terminal-file-picker/file_browser_view.rb
109
110
  - lib/terminal-file-picker/file_picker.rb
110
111
  - lib/terminal-file-picker/helper.rb