tty-tree 0.1.0 → 0.2.0

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.
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"