tty-tree 0.1.0 → 0.2.0

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
- SHA1:
3
- metadata.gz: b7ed240a5a6239047b55b961fa170aaa28df6109
4
- data.tar.gz: b5363c4033cf2218c69d4a0174d1348d2dca5ab7
2
+ SHA256:
3
+ metadata.gz: 53e2981f489110b90e65e7205454e15b1bea811f29063fc5f165c68a2a4a6b5f
4
+ data.tar.gz: ca58a44574af6db9502106a7f6f292125f0b4f156401b3f69e6d4001b602831f
5
5
  SHA512:
6
- metadata.gz: 0c873142481cc06042c4d6f1e3de114f91b372ddd52bca933a84f1a2ba3abedcaa86b0d35d75e4ed5cffe6a13ae5040576dc29e3d04a806a81730e82b6e372dc
7
- data.tar.gz: 18c3d908b3a7c8e0e0205ccf908e9594237ccaece938c567ed5dd7bf86e0f300993cc8e139b5953d405b488cad2c36340c77f55dcd6245033d01d2b4e0c8a9c2
6
+ metadata.gz: bc7fa766eb270b8324b5c9241d7fa0869c4e63273ea57809a8d66c982b13e4db501173c88a1201003e71b7db6f629577a971e0bc97abe3feae9a1e9e6c7d6b63
7
+ data.tar.gz: 4508c2b82e085d0e3deca12fb62d74c9c20d4453367286add7e0e3b9a3b6e1f4aab27ae99fec2194957d6e0dcc2d5160172f7cbfa9d985099d9ba7589f9aedc9
@@ -1,7 +1,13 @@
1
1
  # Change log
2
2
 
3
+ ## [v0.2.0] - 2018-09-01
4
+
5
+ ### Changed
6
+ * Change to Ruby >= 2.0
7
+
3
8
  ## [v0.1.0] - 2017-05-01
4
9
 
5
10
  * Initial implementation and release
6
11
 
12
+ [v0.2.0]: https://github.com/piotrmurach/tty-tree/compare/v0.1.0...v0.2.0
7
13
  [v0.1.0]: https://github.com/piotrmurach/tty-tree/compare/v0.1.0
data/README.md CHANGED
@@ -1,3 +1,7 @@
1
+ <div align="center">
2
+ <a href="https://piotrmurach.github.io/tty" target="_blank"><img width="130" src="https://cdn.rawgit.com/piotrmurach/tty/master/images/tty.png" alt="tty logo" /></a>
3
+ </div>
4
+
1
5
  # TTY::Tree [![Gitter](https://badges.gitter.im/Join%20Chat.svg)][gitter]
2
6
 
3
7
  [![Gem Version](https://badge.fury.io/rb/tty-tree.svg)][gem]
@@ -237,4 +241,4 @@ Bug reports and pull requests are welcome on GitHub at https://github.com/piotrm
237
241
 
238
242
  ## Copyright
239
243
 
240
- Copyright (c) 2017 Piotr Murach. See LICENSE for further details.
244
+ Copyright (c) 2017-2018 Piotr Murach. See LICENSE for further details.
@@ -1,3 +1 @@
1
- # encoding: utf-8
2
-
3
1
  require_relative 'tty/tree'
@@ -1,4 +1,3 @@
1
- # encoding: utf-8
2
1
  # frozen_string_literal: true
3
2
 
4
3
  require_relative 'tree/node'
@@ -1,4 +1,3 @@
1
- # encoding: utf-8
2
1
  # frozen_string_literal: true
3
2
 
4
3
  require 'pathname'
@@ -1,4 +1,3 @@
1
- # encoding: utf-8
2
1
  # frozen_string_literal: true
3
2
 
4
3
  require 'forwardable'
@@ -1,4 +1,3 @@
1
- # encoding: utf-8
2
1
  # frozen_string_literal: true
3
2
 
4
3
  module TTY
@@ -1,4 +1,3 @@
1
- # encoding: utf-8
2
1
  # frozen_string_literal: true
3
2
 
4
3
  require 'pathname'
@@ -1,7 +1,7 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: true
2
2
 
3
3
  module TTY
4
4
  class Tree
5
- VERSION = "0.1.0"
5
+ VERSION = "0.2.0"
6
6
  end # Tree
7
7
  end # TTY
@@ -0,0 +1,71 @@
1
+ # encoding: utf-8
2
+
3
+ if RUBY_VERSION > '1.9' and (ENV['COVERAGE'] || ENV['TRAVIS'])
4
+ require 'simplecov'
5
+ require 'coveralls'
6
+
7
+ SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
8
+ SimpleCov::Formatter::HTMLFormatter,
9
+ Coveralls::SimpleCov::Formatter
10
+ ]
11
+
12
+ SimpleCov.start do
13
+ command_name 'spec'
14
+ add_filter 'spec'
15
+ end
16
+ end
17
+
18
+ require 'bundler/setup'
19
+ require 'tty/tree'
20
+ require 'fileutils'
21
+
22
+ module TestHelpers
23
+ module Paths
24
+ def gem_root
25
+ File.expand_path("#{File.dirname(__FILE__)}/..")
26
+ end
27
+
28
+ def dir_path(*args)
29
+ path = File.join(gem_root, *args)
30
+ FileUtils.mkdir_p(path)
31
+ File.realpath(path)
32
+ end
33
+
34
+ def tmp_path(*args)
35
+ File.join(dir_path('tmp'), *args)
36
+ end
37
+
38
+ def fixtures_path(*args)
39
+ File.join(dir_path('spec/fixtures'), *args)
40
+ end
41
+
42
+ def within_dir(target, &block)
43
+ ::Dir.chdir(target, &block)
44
+ end
45
+ end
46
+ end
47
+
48
+ RSpec.configure do |config|
49
+ config.include(TestHelpers::Paths)
50
+ # config.example_status_persistence_file_path = ".rspec_status"
51
+
52
+ config.expect_with :rspec do |c|
53
+ c.syntax = :expect
54
+ end
55
+
56
+ config.mock_with :rspec do |mocks|
57
+ mocks.verify_partial_doubles = true
58
+ end
59
+
60
+ config.disable_monkey_patching!
61
+
62
+ config.warnings = true
63
+
64
+ if config.files_to_run.one?
65
+ config.default_formatter = 'doc'
66
+ end
67
+
68
+ config.order = :random
69
+
70
+ Kernel.srand config.seed
71
+ end
@@ -0,0 +1,173 @@
1
+ # encoding: utf-8
2
+ # frozen_string_literal: true
3
+
4
+ RSpec.describe TTY::Tree::DirectoryRenderer do
5
+ it "renders directory as path" do
6
+ tree = within_dir(fixtures_path) do
7
+ TTY::Tree.new('dir1')
8
+ end
9
+
10
+ expect(tree.render).to eq([
11
+ "dir1\n",
12
+ "├── config.dat\n",
13
+ "├── dir2\n",
14
+ "│ ├── dir3\n",
15
+ "│ │ └── file3-1.txt\n",
16
+ "│ └── file2-1.txt\n",
17
+ "├── file1-1.txt\n",
18
+ "└── file1-2.txt\n",
19
+ ].join)
20
+ end
21
+
22
+ it "renders hash data as path " do
23
+ data = {
24
+ dir1: [
25
+ 'config.dat',
26
+ { dir2: [
27
+ { dir3: [ 'file3-1.txt' ] },
28
+ 'file2-1.txt'
29
+ ]
30
+ },
31
+ 'file1-1.txt',
32
+ 'file1-2.txt'
33
+ ]
34
+ }
35
+
36
+ tree = TTY::Tree.new(data)
37
+
38
+ expect(tree.render).to eq([
39
+ "dir1\n",
40
+ "├── config.dat\n",
41
+ "├── dir2\n",
42
+ "│ ├── dir3\n",
43
+ "│ │ └── file3-1.txt\n",
44
+ "│ └── file2-1.txt\n",
45
+ "├── file1-1.txt\n",
46
+ "└── file1-2.txt\n",
47
+ ].join)
48
+ end
49
+
50
+ it "correctly renders orphaned directory as path" do
51
+ tree = within_dir(fixtures_path) do
52
+ TTY::Tree.new('orphan_dir')
53
+ end
54
+
55
+ expect(tree.render).to eq([
56
+ "orphan_dir\n",
57
+ "├── a.txt\n",
58
+ "├── b.txt\n",
59
+ "└── data\n",
60
+ " ├── data1.bin\n",
61
+ " ├── data2.sql\n",
62
+ " └── data3.inf\n",
63
+ ].join)
64
+ end
65
+
66
+ it "correctly renders hash with orphaned directory as path" do
67
+ data = {
68
+ orphan_dir: [
69
+ 'a.txt',
70
+ 'b.txt',
71
+ { data: [
72
+ 'data1.bin',
73
+ 'data2.sql',
74
+ 'data3.inf'
75
+ ]
76
+ }
77
+ ]
78
+ }
79
+
80
+ tree = TTY::Tree.new(data)
81
+
82
+ expect(tree.render).to eq([
83
+ "orphan_dir\n",
84
+ "├── a.txt\n",
85
+ "├── b.txt\n",
86
+ "└── data\n",
87
+ " ├── data1.bin\n",
88
+ " ├── data2.sql\n",
89
+ " └── data3.inf\n",
90
+ ].join)
91
+ end
92
+
93
+ it "renders directory as path without indentation" do
94
+ tree = within_dir(fixtures_path) do
95
+ TTY::Tree.new('dir1')
96
+ end
97
+
98
+ expect(tree.render(indent: 0)).to eq([
99
+ "dir1\n",
100
+ "├── config.dat\n",
101
+ "├── dir2\n",
102
+ "│├── dir3\n",
103
+ "││└── file3-1.txt\n",
104
+ "│└── file2-1.txt\n",
105
+ "├── file1-1.txt\n",
106
+ "└── file1-2.txt\n",
107
+ ].join)
108
+ end
109
+
110
+ it "renders directory without hidden files" do
111
+ tree = within_dir(fixtures_path) do
112
+ TTY::Tree.new('hidden_dir', show_hidden: true)
113
+ end
114
+
115
+ expect(tree.render).to eq([
116
+ "hidden_dir\n",
117
+ "├── .with_dot\n",
118
+ "│ └── config.dat\n",
119
+ "├── dir1\n",
120
+ "│ ├── .file1.2\n",
121
+ "│ ├── dir1.1\n",
122
+ "│ │ └── .file1.1.1\n",
123
+ "│ ├── dir1.2\n",
124
+ "│ │ └── file1.2.1\n",
125
+ "│ └── file1.1\n",
126
+ "└── dir2\n",
127
+ " └── .file2.1\n",
128
+ ].join)
129
+ end
130
+
131
+ it "renders directory with only dirs" do
132
+ tree = within_dir(fixtures_path) do
133
+ TTY::Tree.new('hidden_dir', only_dirs: true)
134
+ end
135
+
136
+ expect(tree.render).to eq([
137
+ "hidden_dir\n",
138
+ "├── dir1\n",
139
+ "│ ├── dir1.1\n",
140
+ "│ └── dir1.2\n",
141
+ "└── dir2\n",
142
+ ].join)
143
+ end
144
+
145
+ it "renders directory with only dirs including hidden ones" do
146
+ tree = within_dir(fixtures_path) do
147
+ TTY::Tree.new('hidden_dir', only_dirs: true, show_hidden: true)
148
+ end
149
+
150
+ expect(tree.render).to eq([
151
+ "hidden_dir\n",
152
+ "├── .with_dot\n",
153
+ "├── dir1\n",
154
+ "│ ├── dir1.1\n",
155
+ "│ └── dir1.2\n",
156
+ "└── dir2\n",
157
+ ].join)
158
+ end
159
+
160
+ it "doesn't show dirs with files exceeding limit" do
161
+ tree = within_dir(fixtures_path) do
162
+ TTY::Tree.new('large_dir', file_limit: 4)
163
+ end
164
+
165
+ expect(tree.render).to eq([
166
+ "large_dir\n",
167
+ "├── huge_dir\n",
168
+ "├── large1\n",
169
+ "├── large2\n",
170
+ "└── large3\n",
171
+ ].join)
172
+ end
173
+ end
@@ -0,0 +1,122 @@
1
+ # encoding: utf-8
2
+ # frozen_string_literal: true
3
+
4
+ RSpec.describe TTY::Tree::HashWalker do
5
+ it "walks hash data and collects nodes" do
6
+ data = {
7
+ dir1: [
8
+ 'config.dat',
9
+ { dir2: [
10
+ { dir3: [ 'file3-1.txt' ] },
11
+ 'file2-1.txt'
12
+ ]
13
+ },
14
+ 'file1-1.txt',
15
+ 'file1-2.txt'
16
+ ]
17
+ }
18
+
19
+ walker = TTY::Tree::HashWalker.new
20
+
21
+ walker.traverse(data)
22
+
23
+ expect(walker.nodes).to eq([
24
+ TTY::Tree::Node.new('dir1', '', '', 0),
25
+ TTY::Tree::Node.new('config.dat', 'dir1', '', 1),
26
+ TTY::Tree::Node.new('dir2', 'dir1', '', 1),
27
+ TTY::Tree::Node.new('dir3', 'dir1/dir2', ':pipe', 2),
28
+ TTY::Tree::LeafNode.new('file3-1.txt', 'dir1/dir2/dir3', ':pipe:pipe', 3),
29
+ TTY::Tree::LeafNode.new('file2-1.txt', 'dir1/dir2', ':pipe', 2),
30
+ TTY::Tree::Node.new('file1-1.txt', 'dir1', '', 1),
31
+ TTY::Tree::LeafNode.new('file1-2.txt', 'dir1', '', 1),
32
+ ])
33
+
34
+ expect(walker.nodes.map(&:full_path).map(&:to_s)).to eq([
35
+ "dir1",
36
+ "dir1/config.dat",
37
+ "dir1/dir2",
38
+ "dir1/dir2/dir3",
39
+ "dir1/dir2/dir3/file3-1.txt",
40
+ "dir1/dir2/file2-1.txt",
41
+ "dir1/file1-1.txt",
42
+ "dir1/file1-2.txt",
43
+ ])
44
+ end
45
+
46
+ it "walks path tree and collects nodes up to max level" do
47
+ data = {
48
+ dir1: [
49
+ 'config.dat',
50
+ { dir2: [
51
+ { dir3: [ 'file3-1.txt' ] },
52
+ 'file2-1.txt'
53
+ ]
54
+ },
55
+ 'file1-1.txt',
56
+ 'file1-2.txt'
57
+ ]
58
+ }
59
+
60
+ walker = TTY::Tree::HashWalker.new(level: 2)
61
+
62
+ walker.traverse(data)
63
+
64
+ expect(walker.nodes.map(&:full_path).map(&:to_s)).to eq([
65
+ "dir1",
66
+ "dir1/config.dat",
67
+ "dir1/dir2",
68
+ "dir1/dir2/file2-1.txt",
69
+ "dir1/file1-1.txt",
70
+ "dir1/file1-2.txt",
71
+ ])
72
+ end
73
+
74
+ it "doesn't walks path tree exceeding file limit" do
75
+ data = {
76
+ orphan_dir: [
77
+ 'a.txt',
78
+ 'b.txt',
79
+ { data: [
80
+ 'data1.bin',
81
+ 'data2.sql',
82
+ 'data3.inf',
83
+ 'data4.csv'
84
+ ]
85
+ }
86
+ ]
87
+ }
88
+
89
+ walker = TTY::Tree::HashWalker.new(file_limit: 3)
90
+
91
+ walker.traverse(data)
92
+
93
+ expect(walker.nodes.map(&:full_path).map(&:to_s)).to eq([
94
+ "orphan_dir",
95
+ "orphan_dir/a.txt",
96
+ "orphan_dir/b.txt",
97
+ "orphan_dir/data"
98
+ ])
99
+ end
100
+
101
+ it "counts files & dirs" do
102
+ data = {
103
+ dir1: [
104
+ 'config.dat',
105
+ { dir2: [
106
+ { dir3: [ 'file3-1.txt' ] },
107
+ 'file2-1.txt'
108
+ ]
109
+ },
110
+ 'file1-1.txt',
111
+ 'file1-2.txt'
112
+ ]
113
+ }
114
+ walker = TTY::Tree::HashWalker.new
115
+
116
+ walker.traverse(data)
117
+
118
+ expect(walker.files_count).to eq(5)
119
+
120
+ expect(walker.dirs_count).to eq(2)
121
+ end
122
+ end
@@ -0,0 +1,85 @@
1
+ # encoding: utf-8
2
+ # frozen_string_literal: true
3
+
4
+ RSpec.describe TTY::Tree, '#new' do
5
+ it "exposes [] as instance creation & accepts Dir" do
6
+ tree = TTY::Tree[::File.join(Dir.pwd, 'lib')]
7
+
8
+ expect(tree.nodes).to_not be_empty
9
+ end
10
+
11
+ it "exposes [] as instance creation & accepts Pathname" do
12
+ tree = TTY::Tree[Pathname.pwd.join('lib')]
13
+
14
+ expect(tree.nodes).to_not be_empty
15
+ end
16
+
17
+ it "provides DSL for creating tree" do
18
+ tree = TTY::Tree.new do
19
+ node 'dir1' do
20
+ node 'config.dat'
21
+ node 'dir2' do
22
+ node 'dir3' do
23
+ leaf 'file3-1.txt'
24
+ end
25
+ leaf 'file2-1.txt'
26
+ end
27
+ node 'file1-1.txt'
28
+ leaf 'file1-2.txt'
29
+ end
30
+ end
31
+
32
+ expect(tree.nodes).to eq([
33
+ TTY::Tree::Node.new('dir1', '', '', 0),
34
+ TTY::Tree::Node.new('config.dat', 'dir1', '', 1),
35
+ TTY::Tree::Node.new('dir2', 'dir1', '', 1),
36
+ TTY::Tree::Node.new('dir3', 'dir1/dir2', ':pipe', 2),
37
+ TTY::Tree::LeafNode.new('file3-1.txt', 'dir1/dir2/dir3', ':pipe:pipe', 3),
38
+ TTY::Tree::LeafNode.new('file2-1.txt', 'dir1/dir2', ':pipe', 2),
39
+ TTY::Tree::Node.new('file1-1.txt', 'dir1', '', 1),
40
+ TTY::Tree::LeafNode.new('file1-2.txt', 'dir1', '', 1),
41
+ ])
42
+ end
43
+
44
+ it "provides DSL for creating orphaned tree" do
45
+ tree = TTY::Tree.new do
46
+ node 'orphan_dir' do
47
+ node 'a.txt'
48
+ node 'b.txt'
49
+ leaf 'data' do
50
+ node 'data1.bin'
51
+ node 'data2.sql'
52
+ leaf 'data3.inf'
53
+ end
54
+ end
55
+ end
56
+
57
+ expect(tree.nodes).to eq([
58
+ TTY::Tree::Node.new("orphan_dir", '', '', 0),
59
+ TTY::Tree::Node.new("a.txt", 'orphan_dir', '', 1),
60
+ TTY::Tree::Node.new("b.txt", 'orphan_dir', '', 1),
61
+ TTY::Tree::LeafNode.new("data", 'orphan_dir', '', 1),
62
+ TTY::Tree::Node.new("data1.bin", 'orphan_dir/data', ':space', 2),
63
+ TTY::Tree::Node.new("data2.sql", 'orphan_dir/data', ':space', 2),
64
+ TTY::Tree::LeafNode.new("data3.inf", 'orphan_dir/data', ':space', 2)
65
+ ])
66
+ end
67
+
68
+ it "yields current node to DSL tree node" do
69
+ yielded = []
70
+
71
+ TTY::Tree.new do
72
+ node 'dir1' do |dir1|
73
+ yielded << dir1
74
+ node 'dir2' do |dir2|
75
+ yielded << dir2
76
+ end
77
+ end
78
+ end
79
+
80
+ expect(yielded).to eq([
81
+ TTY::Tree::Node.new("dir1", '', '', 0),
82
+ TTY::Tree::Node.new("dir2", 'dir1', '', 1)
83
+ ])
84
+ end
85
+ end
@@ -0,0 +1,36 @@
1
+ # encoding: utf-8
2
+ # frozen_string_literal: true
3
+
4
+ RSpec.describe TTY::Tree::Node do
5
+ it "provides directory stats" do
6
+ dir = fixtures_path('dir1')
7
+ node = TTY::Tree::Node.new(dir, '', '', 0)
8
+
9
+ expect(node.directory?).to eq(true)
10
+ expect(node.file?).to eq(false)
11
+ expect(node.symlink?).to eq(false)
12
+ expect(node.socket?).to eq(false)
13
+ expect(node.pipe?).to eq(false)
14
+ end
15
+
16
+ it "informs if node is hidden" do
17
+ file = fixtures_path('hidden', 'dir1', '.file1.2')
18
+ node = TTY::Tree::Node.new(file, '', '', 0)
19
+
20
+ expect(node.hidden?).to eq(true)
21
+ end
22
+
23
+ it "compares two nodes for equality" do
24
+ node_a = TTY::Tree::Node.new('dir1', '', '', 0)
25
+ node_b = TTY::Tree::Node.new('dir1', '', '', 0)
26
+
27
+ expect(node_a).to eq(node_b)
28
+ end
29
+
30
+ it "compares two nodes for inequlity" do
31
+ node_a = TTY::Tree::Node.new('dir1', '', '', 0)
32
+ node_b = TTY::Tree::Node.new('dir2', '', '', 0)
33
+
34
+ expect(node_a).to_not eq(node_b)
35
+ end
36
+ end
@@ -0,0 +1,65 @@
1
+ # encoding: utf-8
2
+
3
+ RSpec.describe TTY::Tree::NumberRenderer do
4
+ it "renders directory as numbers" do
5
+ tree = within_dir(fixtures_path) do
6
+ TTY::Tree.new('dir1')
7
+ end
8
+
9
+ expect(tree.render(as: :number)).to eq([
10
+ "dir1\n",
11
+ "1.1 config.dat\n",
12
+ "1.2 dir2\n",
13
+ " 2.3 dir3\n",
14
+ " 3.4 file3-1.txt\n",
15
+ " 2.5 file2-1.txt\n",
16
+ "1.6 file1-1.txt\n",
17
+ "1.7 file1-2.txt\n",
18
+ ].join)
19
+ end
20
+
21
+ it "renders hash data as numbers" do
22
+ data = {
23
+ dir1: [
24
+ 'config.dat',
25
+ { dir2: [
26
+ { dir3: [ 'file3-1.txt' ] },
27
+ 'file2-1.txt'
28
+ ]
29
+ },
30
+ 'file1-1.txt',
31
+ 'file1-2.txt'
32
+ ]
33
+ }
34
+
35
+ tree = TTY::Tree.new(data)
36
+
37
+ expect(tree.render(as: :number)).to eq([
38
+ "dir1\n",
39
+ "1.1 config.dat\n",
40
+ "1.2 dir2\n",
41
+ " 2.3 dir3\n",
42
+ " 3.4 file3-1.txt\n",
43
+ " 2.5 file2-1.txt\n",
44
+ "1.6 file1-1.txt\n",
45
+ "1.7 file1-2.txt\n",
46
+ ].join)
47
+ end
48
+
49
+ it "renders directory as numbers without indentation" do
50
+ tree = within_dir(fixtures_path) do
51
+ TTY::Tree.new('dir1')
52
+ end
53
+
54
+ expect(tree.render(as: :number, indent: 0)).to eq([
55
+ "dir1\n",
56
+ "1.1 config.dat\n",
57
+ "1.2 dir2\n",
58
+ "2.3 dir3\n",
59
+ "3.4 file3-1.txt\n",
60
+ "2.5 file2-1.txt\n",
61
+ "1.6 file1-1.txt\n",
62
+ "1.7 file1-2.txt\n",
63
+ ].join)
64
+ end
65
+ end
@@ -0,0 +1,127 @@
1
+ # encoding: utf-8
2
+ # frozen_string_literal: true
3
+
4
+ RSpec.describe TTY::Tree::PathWalker do
5
+ it "walks path tree and collects nodes" do
6
+ walker = TTY::Tree::PathWalker.new
7
+
8
+ within_dir(fixtures_path) do
9
+ walker.traverse('dir1')
10
+ end
11
+
12
+ expect(walker.nodes).to eq([
13
+ TTY::Tree::Node.new('dir1', '', '', 0),
14
+ TTY::Tree::Node.new('dir1/config.dat', 'dir1', '', 1),
15
+ TTY::Tree::Node.new('dir2', 'dir1', '', 1),
16
+ TTY::Tree::Node.new('dir3', 'dir1/dir2', ':pipe', 2),
17
+ TTY::Tree::LeafNode.new('dir1/dir2/dir3/file3-1.txt', 'dir1/dir2/dir3', ':pipe:pipe', 3),
18
+ TTY::Tree::LeafNode.new('dir1/dir2/file2-1.txt', 'dir1/dir2', ':pipe', 2),
19
+ TTY::Tree::Node.new('dir1/file1-1.txt', 'dir1', '', 1),
20
+ TTY::Tree::LeafNode.new('dir1/file1-2.txt', 'dir1', '', 1),
21
+ ])
22
+
23
+ expect(walker.nodes.map(&:full_path).map(&:to_s)).to eq([
24
+ "dir1",
25
+ "dir1/config.dat",
26
+ "dir1/dir2",
27
+ "dir1/dir2/dir3",
28
+ "dir1/dir2/dir3/file3-1.txt",
29
+ "dir1/dir2/file2-1.txt",
30
+ "dir1/file1-1.txt",
31
+ "dir1/file1-2.txt",
32
+ ])
33
+ end
34
+
35
+ it "walks orphaned path tree and collects nodes" do
36
+ walker = TTY::Tree::PathWalker.new
37
+
38
+ within_dir(fixtures_path) do
39
+ walker.traverse('orphan_dir')
40
+ end
41
+
42
+ expect(walker.nodes).to eq([
43
+ TTY::Tree::Node.new("orphan_dir", '', '', 0),
44
+ TTY::Tree::Node.new("orphan_dir/a.txt", 'orphan_dir', '', 1),
45
+ TTY::Tree::Node.new("orphan_dir/b.txt", 'orphan_dir', '', 1),
46
+ TTY::Tree::LeafNode.new("data", 'orphan_dir', '', 1),
47
+ TTY::Tree::Node.new("orphan_dir/data/data1.bin", 'orphan_dir/data', ':space', 2),
48
+ TTY::Tree::Node.new("orphan_dir/data/data2.sql", 'orphan_dir/data', ':space', 2),
49
+ TTY::Tree::LeafNode.new("orphan_dir/data/data3.inf", 'orphan_dir/data', ':space', 2)
50
+ ])
51
+
52
+ expect(walker.nodes.map(&:full_path).map(&:to_s)).to eq([
53
+ "orphan_dir",
54
+ "orphan_dir/a.txt",
55
+ "orphan_dir/b.txt",
56
+ "orphan_dir/data",
57
+ "orphan_dir/data/data1.bin",
58
+ "orphan_dir/data/data2.sql",
59
+ "orphan_dir/data/data3.inf"
60
+ ])
61
+ end
62
+
63
+ it "walks path tree and collects nodes limited by the level" do
64
+ walker = TTY::Tree::PathWalker.new(level: 2)
65
+
66
+ within_dir(fixtures_path) do
67
+ walker.traverse('dir1')
68
+ end
69
+
70
+ expect(walker.nodes.map(&:full_path).map(&:to_s)).to eq([
71
+ "dir1",
72
+ "dir1/config.dat",
73
+ "dir1/dir2",
74
+ "dir1/dir2/file2-1.txt",
75
+ "dir1/file1-1.txt",
76
+ "dir1/file1-2.txt",
77
+ ])
78
+ end
79
+
80
+ it "doesn't walk paths exceeding file limit" do
81
+ walker = TTY::Tree::PathWalker.new(file_limit: 4)
82
+
83
+ within_dir(fixtures_path) do
84
+ walker.traverse('large_dir')
85
+ end
86
+
87
+ expect(walker.nodes.map(&:full_path).map(&:to_s)).to eq([
88
+ "large_dir",
89
+ "large_dir/huge_dir",
90
+ "large_dir/large1",
91
+ "large_dir/large2",
92
+ "large_dir/large3"
93
+ ])
94
+ end
95
+
96
+ it "counts files & dirs" do
97
+ walker = TTY::Tree::PathWalker.new
98
+
99
+ within_dir(fixtures_path) do
100
+ walker.traverse('dir1')
101
+ end
102
+
103
+ expect(walker.files_count).to eq(5)
104
+
105
+ expect(walker.dirs_count).to eq(2)
106
+ end
107
+
108
+ it "counts files & dirs including max level limit" do
109
+ walker = TTY::Tree::PathWalker.new(level: 2)
110
+
111
+ within_dir(fixtures_path) do
112
+ walker.traverse('dir1')
113
+ end
114
+
115
+ expect(walker.files_count).to eq(4)
116
+
117
+ expect(walker.dirs_count).to eq(1)
118
+ end
119
+
120
+ it "raises when walking non-directory" do
121
+ walker = TTY::Tree::PathWalker.new
122
+
123
+ expect {
124
+ walker.traverse('unknown-dir')
125
+ }.to raise_error(ArgumentError, /unknown-dir is not a directory path/)
126
+ end
127
+ end
@@ -1,4 +1,3 @@
1
- # coding: utf-8
2
1
  lib = File.expand_path('../lib', __FILE__)
3
2
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
3
  require 'tty/tree/version'
@@ -14,13 +13,14 @@ Gem::Specification.new do |spec|
14
13
  spec.homepage = "https://piotrmurach.github.io/tty"
15
14
  spec.license = "MIT"
16
15
 
17
- spec.files = `git ls-files -z`.split("\x0").reject do |f|
18
- f.match(%r{^(test|spec|features)/})
19
- end
16
+ spec.files = Dir['{lib,spec}/**/*.rb', '{bin,tasks}/*', 'tty-tree.gemspec']
17
+ spec.files += Dir['README.md', 'CHANGELOG.md', 'LICENSE.txt', 'Rakefile']
20
18
  spec.bindir = "exe"
21
19
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
22
20
  spec.require_paths = ["lib"]
23
21
 
22
+ spec.required_ruby_version = '>= 2.0.0'
23
+
24
24
  spec.add_development_dependency "bundler", "~> 1.14"
25
25
  spec.add_development_dependency "rake", "~> 10.0"
26
26
  spec.add_development_dependency "rspec", "~> 3.0"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tty-tree
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Piotr Murach
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-05-01 00:00:00.000000000 Z
11
+ date: 2018-09-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -59,16 +59,10 @@ executables: []
59
59
  extensions: []
60
60
  extra_rdoc_files: []
61
61
  files:
62
- - ".gitignore"
63
- - ".rspec"
64
- - ".travis.yml"
65
62
  - CHANGELOG.md
66
- - CODE_OF_CONDUCT.md
67
- - Gemfile
68
63
  - LICENSE.txt
69
64
  - README.md
70
65
  - Rakefile
71
- - appveyor.yml
72
66
  - bin/console
73
67
  - bin/setup
74
68
  - lib/tty-tree.rb
@@ -79,6 +73,13 @@ files:
79
73
  - lib/tty/tree/number_renderer.rb
80
74
  - lib/tty/tree/path_walker.rb
81
75
  - lib/tty/tree/version.rb
76
+ - spec/spec_helper.rb
77
+ - spec/unit/directory_renderer_spec.rb
78
+ - spec/unit/hash_walker_spec.rb
79
+ - spec/unit/new_spec.rb
80
+ - spec/unit/node_spec.rb
81
+ - spec/unit/number_renderer_spec.rb
82
+ - spec/unit/path_walker_spec.rb
82
83
  - tasks/console.rake
83
84
  - tasks/coverage.rake
84
85
  - tasks/spec.rake
@@ -95,7 +96,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
95
96
  requirements:
96
97
  - - ">="
97
98
  - !ruby/object:Gem::Version
98
- version: '0'
99
+ version: 2.0.0
99
100
  required_rubygems_version: !ruby/object:Gem::Requirement
100
101
  requirements:
101
102
  - - ">="
@@ -103,9 +104,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
103
104
  version: '0'
104
105
  requirements: []
105
106
  rubyforge_project:
106
- rubygems_version: 2.5.1
107
+ rubygems_version: 2.7.3
107
108
  signing_key:
108
109
  specification_version: 4
109
110
  summary: Print directory or structured data in a tree like format.
110
111
  test_files: []
111
- has_rdoc:
data/.gitignore DELETED
@@ -1,12 +0,0 @@
1
- /.bundle/
2
- /.yardoc
3
- /Gemfile.lock
4
- /_yardoc/
5
- /coverage/
6
- /doc/
7
- /pkg/
8
- /spec/reports/
9
- /tmp/
10
-
11
- # rspec failure tracking
12
- .rspec_status
data/.rspec DELETED
@@ -1,3 +0,0 @@
1
- --color
2
- --require spec_helper
3
- --warnings
@@ -1,24 +0,0 @@
1
- ---
2
- language: ruby
3
- sudo: false
4
- before_install: gem install bundler -v 1.14.6
5
- bundler_args: --without tools
6
- script: "bundle exec rake ci"
7
- rvm:
8
- - 2.0.0
9
- - 2.1.10
10
- - 2.2.6
11
- - 2.3.3
12
- - 2.4.0
13
- - ruby-head
14
- - jruby-9000
15
- - jruby-head
16
- matrix:
17
- allow_failures:
18
- - rvm: ruby-head
19
- - rvm: jruby-head
20
- fast_finish: true
21
- branches:
22
- only: master
23
- notifications:
24
- email: false
@@ -1,74 +0,0 @@
1
- # Contributor Covenant Code of Conduct
2
-
3
- ## Our Pledge
4
-
5
- In the interest of fostering an open and welcoming environment, we as
6
- contributors and maintainers pledge to making participation in our project and
7
- our community a harassment-free experience for everyone, regardless of age, body
8
- size, disability, ethnicity, gender identity and expression, level of experience,
9
- nationality, personal appearance, race, religion, or sexual identity and
10
- orientation.
11
-
12
- ## Our Standards
13
-
14
- Examples of behavior that contributes to creating a positive environment
15
- include:
16
-
17
- * Using welcoming and inclusive language
18
- * Being respectful of differing viewpoints and experiences
19
- * Gracefully accepting constructive criticism
20
- * Focusing on what is best for the community
21
- * Showing empathy towards other community members
22
-
23
- Examples of unacceptable behavior by participants include:
24
-
25
- * The use of sexualized language or imagery and unwelcome sexual attention or
26
- advances
27
- * Trolling, insulting/derogatory comments, and personal or political attacks
28
- * Public or private harassment
29
- * Publishing others' private information, such as a physical or electronic
30
- address, without explicit permission
31
- * Other conduct which could reasonably be considered inappropriate in a
32
- professional setting
33
-
34
- ## Our Responsibilities
35
-
36
- Project maintainers are responsible for clarifying the standards of acceptable
37
- behavior and are expected to take appropriate and fair corrective action in
38
- response to any instances of unacceptable behavior.
39
-
40
- Project maintainers have the right and responsibility to remove, edit, or
41
- reject comments, commits, code, wiki edits, issues, and other contributions
42
- that are not aligned to this Code of Conduct, or to ban temporarily or
43
- permanently any contributor for other behaviors that they deem inappropriate,
44
- threatening, offensive, or harmful.
45
-
46
- ## Scope
47
-
48
- This Code of Conduct applies both within project spaces and in public spaces
49
- when an individual is representing the project or its community. Examples of
50
- representing a project or community include using an official project e-mail
51
- address, posting via an official social media account, or acting as an appointed
52
- representative at an online or offline event. Representation of a project may be
53
- further defined and clarified by project maintainers.
54
-
55
- ## Enforcement
56
-
57
- Instances of abusive, harassing, or otherwise unacceptable behavior may be
58
- reported by contacting the project team at [email]. All
59
- complaints will be reviewed and investigated and will result in a response that
60
- is deemed necessary and appropriate to the circumstances. The project team is
61
- obligated to maintain confidentiality with regard to the reporter of an incident.
62
- Further details of specific enforcement policies may be posted separately.
63
-
64
- Project maintainers who do not follow or enforce the Code of Conduct in good
65
- faith may face temporary or permanent repercussions as determined by other
66
- members of the project's leadership.
67
-
68
- ## Attribution
69
-
70
- This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71
- available at [http://contributor-covenant.org/version/1/4][version]
72
-
73
- [homepage]: http://contributor-covenant.org
74
- [version]: http://contributor-covenant.org/version/1/4/
data/Gemfile DELETED
@@ -1,19 +0,0 @@
1
- source 'https://rubygems.org'
2
-
3
- gemspec
4
-
5
- group :test do
6
- gem 'benchmark-ips', '~> 2.0.0'
7
- gem 'simplecov', '~> 0.10.0'
8
- gem 'coveralls', '~> 0.8.2'
9
- gem 'term-ansicolor', '=1.3.2'
10
- end
11
-
12
- group :tools do
13
- gem 'byebug', platform: :mri
14
- end
15
-
16
- group :metrics do
17
- gem 'yard', '~> 0.8.7'
18
- gem 'yardstick', '~> 0.9.9'
19
- end
@@ -1,23 +0,0 @@
1
- ---
2
- install:
3
- - SET PATH=C:\Ruby%ruby_version%\bin;%PATH%
4
- - ruby --version
5
- - gem --version
6
- - bundle install
7
- build: off
8
- test_script:
9
- - bundle exec rake ci
10
- environment:
11
- matrix:
12
- - ruby_version: "193"
13
- - ruby_version: "200"
14
- - ruby_version: "200-x64"
15
- - ruby_version: "21"
16
- - ruby_version: "21-x64"
17
- - ruby_version: "22"
18
- - ruby_version: "22-x64"
19
- - ruby_version: "23"
20
- - ruby_version: "23-x64"
21
- matrix:
22
- allow_failures:
23
- - ruby_version: "193"