pleasant_path 1.0.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 +7 -0
- data/.gitignore +9 -0
- data/.travis.yml +5 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +79 -0
- data/Rakefile +23 -0
- data/lib/pleasant_path.rb +7 -0
- data/lib/pleasant_path/array.rb +27 -0
- data/lib/pleasant_path/file.rb +42 -0
- data/lib/pleasant_path/io.rb +29 -0
- data/lib/pleasant_path/pathname.rb +261 -0
- data/lib/pleasant_path/string.rb +73 -0
- data/lib/pleasant_path/version.rb +3 -0
- data/pleasant_path.gemspec +27 -0
- metadata +114 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: d6e26d3eb1ea19b636f25d9920be3aeb772175ce
|
4
|
+
data.tar.gz: 46c754d3523b1436d029fe0a0877e70a508becf7
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 35f15a1f476b2dc68a1979fe72df5feed7b7cf41949eb98391379a36d92a40d1a3d6c72ea193965401796fa59b3e9021e70448321c6c7c7573c3d19d65ad563a
|
7
|
+
data.tar.gz: 69be2fb1dcfa1362aac1d56fedc5558b7800506ab1b5ae58c5b3e573cbc39188c0641323a0f1cdbe7f2396b6ecf67aca76d867169cecfb3c05ba28000ef8ac25
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2016 Jonathan Hefner
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
# pleasant_path
|
2
|
+
|
3
|
+
A [fluent API] for pleasant file IO, written as extensions to core Ruby
|
4
|
+
objects. See method listing below or browse the [full documentation].
|
5
|
+
|
6
|
+
[fluent API]: https://en.wikipedia.org/wiki/Fluent_interface
|
7
|
+
[full documentation]: http://www.rubydoc.info/gems/pleasant_path/
|
8
|
+
|
9
|
+
|
10
|
+
## Examples
|
11
|
+
|
12
|
+
```ruby
|
13
|
+
# Dedup lines in a file
|
14
|
+
"line_items.txt".path.edit_lines(&:uniq)
|
15
|
+
|
16
|
+
# Filter lines across multiple files
|
17
|
+
"logs/*.txt".glob.each do |log|
|
18
|
+
log.read_lines.grep(/Error/).append_to_file('errors.txt')
|
19
|
+
end
|
20
|
+
```
|
21
|
+
|
22
|
+
|
23
|
+
## API Methods
|
24
|
+
|
25
|
+
- Pathname
|
26
|
+
- [^](http://www.rubydoc.info/gems/pleasant_path/Pathname%3A%5E)
|
27
|
+
- [append_file](http://www.rubydoc.info/gems/pleasant_path/Pathname%3Aappend_file)
|
28
|
+
- [append_lines](http://www.rubydoc.info/gems/pleasant_path/Pathname%3Aappend_lines)
|
29
|
+
- [append_text](http://www.rubydoc.info/gems/pleasant_path/Pathname%3Aappend_text)
|
30
|
+
- [delete!](http://www.rubydoc.info/gems/pleasant_path/Pathname%3Adelete%21)
|
31
|
+
- [dir_empty?](http://www.rubydoc.info/gems/pleasant_path/Pathname%3Adir_empty%3F)
|
32
|
+
- [dirs](http://www.rubydoc.info/gems/pleasant_path/Pathname%3Adirs)
|
33
|
+
- [dirs_r](http://www.rubydoc.info/gems/pleasant_path/Pathname%3Adirs_r)
|
34
|
+
- [edit_lines](http://www.rubydoc.info/gems/pleasant_path/Pathname%3Aedit_lines)
|
35
|
+
- [edit_text](http://www.rubydoc.info/gems/pleasant_path/Pathname%3Aedit_text)
|
36
|
+
- [files](http://www.rubydoc.info/gems/pleasant_path/Pathname%3Afiles)
|
37
|
+
- [files_r](http://www.rubydoc.info/gems/pleasant_path/Pathname%3Afiles_r)
|
38
|
+
- [make_dir](http://www.rubydoc.info/gems/pleasant_path/Pathname%3Amake_dir)
|
39
|
+
- [make_dirname](http://www.rubydoc.info/gems/pleasant_path/Pathname%3Amake_dirname)
|
40
|
+
- [move](http://www.rubydoc.info/gems/pleasant_path/Pathname%3Amove)
|
41
|
+
- [move_into](http://www.rubydoc.info/gems/pleasant_path/Pathname%3Amove_into)
|
42
|
+
- [parentname](http://www.rubydoc.info/gems/pleasant_path/Pathname%3Aparentname)
|
43
|
+
- [read_lines](http://www.rubydoc.info/gems/pleasant_path/Pathname%3Aread_lines)
|
44
|
+
- [to_pathname](http://www.rubydoc.info/gems/pleasant_path/Pathname%3Ato_pathname)
|
45
|
+
- [touch_file](http://www.rubydoc.info/gems/pleasant_path/Pathname%3Atouch_file)
|
46
|
+
- [write_lines](http://www.rubydoc.info/gems/pleasant_path/Pathname%3Awrite_lines)
|
47
|
+
- [write_text](http://www.rubydoc.info/gems/pleasant_path/Pathname%3Awrite_text)
|
48
|
+
- String
|
49
|
+
- [/](http://www.rubydoc.info/gems/pleasant_path/String%3A%2F)
|
50
|
+
- [^](http://www.rubydoc.info/gems/pleasant_path/String%3A%5E)
|
51
|
+
- [append_to_file](http://www.rubydoc.info/gems/pleasant_path/String%3Aappend_to_file)
|
52
|
+
- [glob](http://www.rubydoc.info/gems/pleasant_path/String%3Aglob)
|
53
|
+
- [to_pathname](http://www.rubydoc.info/gems/pleasant_path/String%3Ato_pathname)
|
54
|
+
- [write_to_file](http://www.rubydoc.info/gems/pleasant_path/String%3Awrite_to_file)
|
55
|
+
- Array
|
56
|
+
- [append_to_file](http://www.rubydoc.info/gems/pleasant_path/Array%3Aappend_to_file)
|
57
|
+
- [write_to_file](http://www.rubydoc.info/gems/pleasant_path/Array%3Awrite_to_file)
|
58
|
+
- File
|
59
|
+
- [edit_lines](http://www.rubydoc.info/gems/pleasant_path/File.edit_lines)
|
60
|
+
- [edit_text](http://www.rubydoc.info/gems/pleasant_path/File.edit_text)
|
61
|
+
- IO
|
62
|
+
- [read_lines](http://www.rubydoc.info/gems/pleasant_path/IO%3Aread_lines)
|
63
|
+
- [write_lines](http://www.rubydoc.info/gems/pleasant_path/IO%3Awrite_lines)
|
64
|
+
|
65
|
+
|
66
|
+
## Installation
|
67
|
+
|
68
|
+
$ gem install pleasant_path
|
69
|
+
|
70
|
+
|
71
|
+
## Development
|
72
|
+
|
73
|
+
Run `rake test` to run the tests. You can also run `rake irb` for an
|
74
|
+
interactive prompt that pre-loads the project code.
|
75
|
+
|
76
|
+
|
77
|
+
## License
|
78
|
+
|
79
|
+
[MIT License](http://opensource.org/licenses/MIT)
|
data/Rakefile
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
require "rake/testtask"
|
3
|
+
require "yard"
|
4
|
+
|
5
|
+
|
6
|
+
YARD::Rake::YardocTask.new(:doc) do |t|
|
7
|
+
end
|
8
|
+
|
9
|
+
desc "Launch IRB with this gem pre-loaded"
|
10
|
+
task :irb do
|
11
|
+
require "pleasant_path"
|
12
|
+
require "irb"
|
13
|
+
ARGV.clear
|
14
|
+
IRB.start
|
15
|
+
end
|
16
|
+
|
17
|
+
Rake::TestTask.new(:test) do |t|
|
18
|
+
t.libs << "test"
|
19
|
+
t.libs << "lib"
|
20
|
+
t.test_files = FileList['test/**/*_test.rb']
|
21
|
+
end
|
22
|
+
|
23
|
+
task :default => :test
|
@@ -0,0 +1,27 @@
|
|
1
|
+
class Array
|
2
|
+
|
3
|
+
# Writes the array as lines to the given file, and returns the array.
|
4
|
+
# A new line character (<code>$/</code>) is written after each line.
|
5
|
+
# The file is overwritten if it already exists. Any necessary parent
|
6
|
+
# directories are created if they do not exist.
|
7
|
+
#
|
8
|
+
# @param file [String, Pathname]
|
9
|
+
# @return [Array]
|
10
|
+
def write_to_file(file)
|
11
|
+
file.to_pathname.write_lines(self)
|
12
|
+
self
|
13
|
+
end
|
14
|
+
|
15
|
+
# Appends the array as lines to the given file, and returns the array.
|
16
|
+
# A new line character (<code>$/</code>) is written after each line.
|
17
|
+
# The file is created if it does not exist. Any necessary parent
|
18
|
+
# directories are created if they do not exist.
|
19
|
+
#
|
20
|
+
# @param file [String, Pathname]
|
21
|
+
# @return [Array]
|
22
|
+
def append_to_file(file)
|
23
|
+
file.to_pathname.append_lines(self)
|
24
|
+
self
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
class File
|
2
|
+
|
3
|
+
# Reads from the specified file its contents as a string, and yields
|
4
|
+
# the string to the given block for editing. Writes the return value
|
5
|
+
# of the block back to the file, overwriting previous contents.
|
6
|
+
# Returns the file's new contents.
|
7
|
+
#
|
8
|
+
# @param filename [String, Pathname]
|
9
|
+
# @yield [text] edits current file contents
|
10
|
+
# @yieldparam text [String] current contents
|
11
|
+
# @yieldreturn [String] new contents
|
12
|
+
# @return [String]
|
13
|
+
def self.edit_text(filename)
|
14
|
+
self.open(filename, 'r+') do |f|
|
15
|
+
text = yield f.read
|
16
|
+
f.seek(0, IO::SEEK_SET)
|
17
|
+
f.write(text)
|
18
|
+
text
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# Reads from the specified file its contents as an array of lines, and
|
23
|
+
# yields the array to the given block for editing. Writes the return
|
24
|
+
# value of the block back to the file, overwriting previous contents.
|
25
|
+
# The <code>$/</code> global string specifies what end-of-line
|
26
|
+
# characters to use for both reading and writing. Returns the array
|
27
|
+
# of lines that comprises the file's new contents.
|
28
|
+
#
|
29
|
+
# @param filename [String, Pathname]
|
30
|
+
# @yield [lines] edits current file contents
|
31
|
+
# @yieldparam lines [Array<String>] current contents
|
32
|
+
# @yieldreturn [Array<String>] new contents
|
33
|
+
# @return [Array<String>]
|
34
|
+
def self.edit_lines(filename)
|
35
|
+
self.open(filename, 'r+') do |f|
|
36
|
+
lines = yield f.read_lines
|
37
|
+
f.seek(0, IO::SEEK_SET)
|
38
|
+
f.write_lines(lines)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
class IO
|
2
|
+
|
3
|
+
# Writes each string plus a succeeding new line character
|
4
|
+
# (<code>$/</code>) to the IO. Returns the lines unmodified.
|
5
|
+
#
|
6
|
+
# @param lines [Array<String>]
|
7
|
+
# @return [Array<String>]
|
8
|
+
def write_lines(lines)
|
9
|
+
lines.each do |line|
|
10
|
+
self.write(line)
|
11
|
+
self.write($/)
|
12
|
+
end
|
13
|
+
self.write('') # write something even if no lines
|
14
|
+
lines
|
15
|
+
end
|
16
|
+
|
17
|
+
# Reads from the IO all lines, and returns them as an array,
|
18
|
+
# end-of-line characters excluded. The <code>$/</code> global string
|
19
|
+
# specifies what end-of-line characters to look for.
|
20
|
+
#
|
21
|
+
# (Not to be confused with +IO#readlines+ which retains end-of-line
|
22
|
+
# characters in every string it returns.)
|
23
|
+
#
|
24
|
+
# @return [Array<String>]
|
25
|
+
def read_lines
|
26
|
+
self.readlines.each(&:chomp!)
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
@@ -0,0 +1,261 @@
|
|
1
|
+
class Pathname
|
2
|
+
|
3
|
+
# Returns the Pathname unmodified. Exists for parity with
|
4
|
+
# +String#to_pathname+.
|
5
|
+
#
|
6
|
+
# @return [Pathname]
|
7
|
+
def to_pathname
|
8
|
+
self
|
9
|
+
end
|
10
|
+
|
11
|
+
# Joins the parent (+dirname+) of the Pathname with the argument. The
|
12
|
+
# mnenomic for this operator is that the resultant path goes up one
|
13
|
+
# directory level from the original, then goes down to the directory
|
14
|
+
# specified by the argument.
|
15
|
+
#
|
16
|
+
# @example
|
17
|
+
# (Pathname.new("path/to/file1") ^ "file2").to_s #=> "path/to/file2"
|
18
|
+
#
|
19
|
+
# @param sibling [Pathname, String]
|
20
|
+
# @return [Pathname]
|
21
|
+
def ^(sibling)
|
22
|
+
self.dirname / sibling
|
23
|
+
end
|
24
|
+
|
25
|
+
# Returns the +basename+ of the Pathname's parent directory.
|
26
|
+
#
|
27
|
+
# @example
|
28
|
+
# Pathname.new("path/to/file").parentname.to_s #=> "to"
|
29
|
+
#
|
30
|
+
# @return [Pathname]
|
31
|
+
def parentname
|
32
|
+
self.dirname.basename
|
33
|
+
end
|
34
|
+
|
35
|
+
# Alias of +Pathname#directory?+.
|
36
|
+
#
|
37
|
+
# @return [Boolean]
|
38
|
+
alias :dir? :directory?
|
39
|
+
|
40
|
+
# True if the directory indicated by the Pathname contains no other
|
41
|
+
# directories or files.
|
42
|
+
#
|
43
|
+
# @return [Boolean]
|
44
|
+
def dir_empty?
|
45
|
+
self.children(false).empty?
|
46
|
+
end
|
47
|
+
|
48
|
+
# Returns the immediate (non-recursive) child directories of the
|
49
|
+
# directory indicated by the Pathname. Returned Pathnames are
|
50
|
+
# prefixed by the original Pathname.
|
51
|
+
#
|
52
|
+
# @return [Array<Pathname>]
|
53
|
+
def dirs
|
54
|
+
self.children.tap{|c| c.select!(&:dir?) }
|
55
|
+
end
|
56
|
+
|
57
|
+
# Returns the recursively descended child directories of the
|
58
|
+
# directory indicated by the Pathname. Returned Pathnames are
|
59
|
+
# prefixed by the original Pathname.
|
60
|
+
#
|
61
|
+
# @return [Array<Pathname>]
|
62
|
+
def dirs_r
|
63
|
+
self.find.select(&:dir?).tap(&:shift)
|
64
|
+
end
|
65
|
+
|
66
|
+
# Returns the immediate (non-recursive) child files of the directory
|
67
|
+
# indicated by the Pathname. Returned Pathnames are prefixed by the
|
68
|
+
# original Pathname.
|
69
|
+
#
|
70
|
+
# @return [Array<Pathname>]
|
71
|
+
def files
|
72
|
+
self.children.tap{|c| c.select!(&:file?) }
|
73
|
+
end
|
74
|
+
|
75
|
+
# Returns the recursively descended child files of the directory
|
76
|
+
# indicated by the Pathname. Returned Pathnames are prefixed by the
|
77
|
+
# original Pathname.
|
78
|
+
#
|
79
|
+
# @return [Array<Pathname>]
|
80
|
+
def files_r
|
81
|
+
self.find.select(&:file?)
|
82
|
+
end
|
83
|
+
|
84
|
+
# Alias of +Pathname#mkpath+, but this method returns the Pathname.
|
85
|
+
#
|
86
|
+
# @return [Pathname]
|
87
|
+
def make_dir
|
88
|
+
self.mkpath
|
89
|
+
self
|
90
|
+
end
|
91
|
+
|
92
|
+
# Creates the parent (+dirname+) directories of the Pathname if they
|
93
|
+
# do not exist, and returns the Pathname.
|
94
|
+
#
|
95
|
+
# @return [Pathname]
|
96
|
+
def make_dirname
|
97
|
+
self.dirname.make_dir
|
98
|
+
self
|
99
|
+
end
|
100
|
+
|
101
|
+
# Updates the modification time (mtime) and access time (atime) of the
|
102
|
+
# file indicated by the Pathname, and returns the Pathname. Creates
|
103
|
+
# the file and any necessary parent directories if they do not exist.
|
104
|
+
# See also +FileUtils.touch+.
|
105
|
+
#
|
106
|
+
# @return [Pathname]
|
107
|
+
def touch_file
|
108
|
+
self.make_dirname
|
109
|
+
FileUtils.touch(self)
|
110
|
+
self
|
111
|
+
end
|
112
|
+
|
113
|
+
# Recursively deletes the directory or file indicated by the Pathname,
|
114
|
+
# and returns the Pathname. Similar to +Pathname#rmtree+, but does
|
115
|
+
# not raise an exception if the file does not exist.
|
116
|
+
#
|
117
|
+
# @return [Pathname]
|
118
|
+
def delete!
|
119
|
+
self.rmtree if self.exist?
|
120
|
+
self
|
121
|
+
end
|
122
|
+
|
123
|
+
# Moves the file indicated by Pathname to the given destination, and
|
124
|
+
# returns that destination as a Pathname. Creates any necessary
|
125
|
+
# parent directories if they do not exist.
|
126
|
+
#
|
127
|
+
# @param destination [Pathname, String]
|
128
|
+
# @return [Pathname]
|
129
|
+
def move(destination)
|
130
|
+
destination = destination.to_pathname
|
131
|
+
destination.make_dirname
|
132
|
+
self.rename(destination)
|
133
|
+
destination
|
134
|
+
end
|
135
|
+
|
136
|
+
# Moves the file indicated by Pathname into the given directory, and
|
137
|
+
# returns the resultant path to the file as a Pathname. Creates any
|
138
|
+
# necessary parent directories if they do not exist.
|
139
|
+
#
|
140
|
+
# @param directory [Pathname, String]
|
141
|
+
# @return [Pathname]
|
142
|
+
def move_into(directory)
|
143
|
+
self.move(directory / self.basename)
|
144
|
+
end
|
145
|
+
|
146
|
+
# Writes given text to the file indicated by the Pathname, and returns
|
147
|
+
# the Pathname. The file is overwritten if it already exists. Any
|
148
|
+
# necessary parent directories are created if they do not exist.
|
149
|
+
#
|
150
|
+
# @param text [String]
|
151
|
+
# @return [Pathname]
|
152
|
+
def write_text(text)
|
153
|
+
self.make_dirname.open('w'){|f| f.write(text) }
|
154
|
+
self
|
155
|
+
end
|
156
|
+
|
157
|
+
# Appends given text to the file indicated by the Pathname, and
|
158
|
+
# returns the Pathname. The file is created if it does not exist.
|
159
|
+
# Any necessary parent directories are created if they do not exist.
|
160
|
+
#
|
161
|
+
# @param text [String]
|
162
|
+
# @return [Pathname]
|
163
|
+
def append_text(text)
|
164
|
+
self.make_dirname.open('a'){|f| f.write(text) }
|
165
|
+
self
|
166
|
+
end
|
167
|
+
|
168
|
+
# Writes given lines of text to the file indicated by the Pathname,
|
169
|
+
# and returns the Pathname. A new line character (<code>$/</code>) is
|
170
|
+
# written after each line. The file is overwritten if it already
|
171
|
+
# exists. Any necessary parent directories are created if they do not
|
172
|
+
# exist.
|
173
|
+
#
|
174
|
+
# @param lines [Array<String>]
|
175
|
+
# @return [Pathname]
|
176
|
+
def write_lines(lines)
|
177
|
+
self.make_dirname.open('w'){|f| f.write_lines(lines) }
|
178
|
+
self
|
179
|
+
end
|
180
|
+
|
181
|
+
# Appends given lines of text to the file indicated by the Pathname,
|
182
|
+
# and returns the Pathname. A new line character (<code>$/</code>) is
|
183
|
+
# written after each line. The file is created if it does not exist.
|
184
|
+
# Any necessary parent directories are created if they do not exist.
|
185
|
+
#
|
186
|
+
# @param lines [Array<String>]
|
187
|
+
# @return [Pathname]
|
188
|
+
def append_lines(lines)
|
189
|
+
self.make_dirname.open('a'){|f| f.write_lines(lines) }
|
190
|
+
self
|
191
|
+
end
|
192
|
+
|
193
|
+
# Alias of +Pathname#read+.
|
194
|
+
#
|
195
|
+
# @return [String]
|
196
|
+
alias :read_text :read
|
197
|
+
|
198
|
+
# Reads from the file indicated by the Pathname all lines, and returns
|
199
|
+
# them as an array, end-of-line characters excluded. The
|
200
|
+
# <code>$/</code> global string specifies what end-of-line characters
|
201
|
+
# to look for. See also +IO#read_lines+.
|
202
|
+
#
|
203
|
+
# (Not to be confused with +Pathname#readlines+ which retains
|
204
|
+
# end-of-line characters in every string it returns.)
|
205
|
+
#
|
206
|
+
# @return [Array<String>]
|
207
|
+
def read_lines
|
208
|
+
self.open('r'){|f| f.read_lines }
|
209
|
+
end
|
210
|
+
|
211
|
+
# Reads the contents of the file indicated by the Pathname into memory
|
212
|
+
# as a string, and yields the string to the given block for editing.
|
213
|
+
# Writes the return value of the block back to the file, overwriting
|
214
|
+
# previous contents. Returns the file's new contents. See also
|
215
|
+
# +File.edit_text+.
|
216
|
+
#
|
217
|
+
# @example Update YAML data file
|
218
|
+
# path.edit_text do |text|
|
219
|
+
# data = YAML.load(text)
|
220
|
+
# data['deeply']['nested']['key'] = 'new value'
|
221
|
+
# data.to_yaml
|
222
|
+
# end
|
223
|
+
#
|
224
|
+
# @yield [text] edits current file contents
|
225
|
+
# @yieldparam text [String] current contents
|
226
|
+
# @yieldreturn [String] new contents
|
227
|
+
# @return [String]
|
228
|
+
def edit_text(&block)
|
229
|
+
File.edit_text(self, &block)
|
230
|
+
end
|
231
|
+
|
232
|
+
# Reads the contents of the file indicated by the Pathname into memory
|
233
|
+
# as an array of lines, and yields the array to the given block for
|
234
|
+
# editing. Writes the return value of the block back to the file,
|
235
|
+
# overwriting previous contents. The <code>$/</code> global string
|
236
|
+
# specifies what end-of-line characters to use for both reading and
|
237
|
+
# writing. Returns the array of lines that comprises the file's new
|
238
|
+
# contents. See also +File.edit_lines+.
|
239
|
+
#
|
240
|
+
# @example Dedup lines of file
|
241
|
+
# path.edit_lines(&:uniq)
|
242
|
+
#
|
243
|
+
# @yield [lines] edits current file contents
|
244
|
+
# @yieldparam lines [Array<String>] current contents
|
245
|
+
# @yieldreturn [Array<String>] new contents
|
246
|
+
# @return [Array<String>]
|
247
|
+
def edit_lines(&block)
|
248
|
+
File.edit_lines(self, &block)
|
249
|
+
end
|
250
|
+
|
251
|
+
# Appends the contents of another file to the destination indicated by
|
252
|
+
# Pathname. Returns the destination Pathname.
|
253
|
+
#
|
254
|
+
# @param source [String, Pathname]
|
255
|
+
# @return [Pathname]
|
256
|
+
def append_file(source)
|
257
|
+
self.open('a'){|destination| IO::copy_stream(source, destination) }
|
258
|
+
self
|
259
|
+
end
|
260
|
+
|
261
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
class String
|
2
|
+
|
3
|
+
# Converts the string to a +Pathname+ object.
|
4
|
+
#
|
5
|
+
# @return [Pathname]
|
6
|
+
def to_pathname
|
7
|
+
Pathname.new(self)
|
8
|
+
end
|
9
|
+
|
10
|
+
# Alias of +String#to_pathname+.
|
11
|
+
#
|
12
|
+
# @return [Pathname]
|
13
|
+
alias :path :to_pathname
|
14
|
+
|
15
|
+
# Joins the string and the argument with a directory separator (a la
|
16
|
+
# +File.join+) and returns the result as a +Pathname+ object.
|
17
|
+
#
|
18
|
+
# @example
|
19
|
+
# ("path/to" / "file").to_s #=> "path/to/file"
|
20
|
+
#
|
21
|
+
# @param child [String]
|
22
|
+
# @return [Pathname]
|
23
|
+
def /(child)
|
24
|
+
self.path / child
|
25
|
+
end
|
26
|
+
|
27
|
+
# Treating the string as a path, joins the parent (+dirname+) of the
|
28
|
+
# path with the argument, and returns the result as a +Pathname+
|
29
|
+
# object. The mnenomic for this operator is that the resultant path
|
30
|
+
# goes up one directory level from the original, then goes down to the
|
31
|
+
# directory specified by the argument. See also +Pathname#^+.
|
32
|
+
#
|
33
|
+
# @example
|
34
|
+
# ("path/to/file1" ^ "file2").to_s #=> "path/to/file2"
|
35
|
+
#
|
36
|
+
# @param sibling [Pathname, String]
|
37
|
+
# @return [Pathname]
|
38
|
+
def ^(sibling)
|
39
|
+
self.path ^ sibling
|
40
|
+
end
|
41
|
+
|
42
|
+
# Treats the string as a filename pattern, and expands the pattern
|
43
|
+
# into matching paths as +Pathname+ objects. See also +Dir.glob+ and
|
44
|
+
# +Pathname.glob+.
|
45
|
+
#
|
46
|
+
# @return [Array<Pathname>]
|
47
|
+
def glob
|
48
|
+
Pathname.glob(self)
|
49
|
+
end
|
50
|
+
|
51
|
+
# Writes the string to the given file, and returns the string. The
|
52
|
+
# file is overwritten if it already exists. Any necessary parent
|
53
|
+
# directories are created if they do not exist.
|
54
|
+
#
|
55
|
+
# @param file [String, Pathname]
|
56
|
+
# @return [String]
|
57
|
+
def write_to_file(file)
|
58
|
+
file.to_pathname.write_text(self)
|
59
|
+
self
|
60
|
+
end
|
61
|
+
|
62
|
+
# Appends the string to the given file, and returns the string. The
|
63
|
+
# file is created if it does not exist. Any necessary parent
|
64
|
+
# directories are created if they do not exist.
|
65
|
+
#
|
66
|
+
# @param file [String, Pathname]
|
67
|
+
# @return [String]
|
68
|
+
def append_to_file(file)
|
69
|
+
file.to_pathname.append_text(self)
|
70
|
+
self
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'pleasant_path/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "pleasant_path"
|
8
|
+
spec.version = PleasantPath::VERSION
|
9
|
+
spec.authors = ["Jonathan Hefner"]
|
10
|
+
spec.email = ["jonathan.hefner@gmail.com"]
|
11
|
+
|
12
|
+
spec.summary = %q{A fluent API for pleasant file IO.}
|
13
|
+
spec.homepage = "https://github.com/jonathanhefner/pleasant_path"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
17
|
+
f.match(%r{^(test|spec|features)/})
|
18
|
+
end
|
19
|
+
spec.bindir = "exe"
|
20
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
21
|
+
spec.require_paths = ["lib"]
|
22
|
+
|
23
|
+
spec.add_development_dependency "bundler", "~> 1.13"
|
24
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
25
|
+
spec.add_development_dependency "minitest", "~> 5.0"
|
26
|
+
spec.add_development_dependency "yard", "~> 0.9"
|
27
|
+
end
|
metadata
ADDED
@@ -0,0 +1,114 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: pleasant_path
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jonathan Hefner
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-11-04 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.13'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.13'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: minitest
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '5.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '5.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: yard
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0.9'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0.9'
|
69
|
+
description:
|
70
|
+
email:
|
71
|
+
- jonathan.hefner@gmail.com
|
72
|
+
executables: []
|
73
|
+
extensions: []
|
74
|
+
extra_rdoc_files: []
|
75
|
+
files:
|
76
|
+
- ".gitignore"
|
77
|
+
- ".travis.yml"
|
78
|
+
- Gemfile
|
79
|
+
- LICENSE.txt
|
80
|
+
- README.md
|
81
|
+
- Rakefile
|
82
|
+
- lib/pleasant_path.rb
|
83
|
+
- lib/pleasant_path/array.rb
|
84
|
+
- lib/pleasant_path/file.rb
|
85
|
+
- lib/pleasant_path/io.rb
|
86
|
+
- lib/pleasant_path/pathname.rb
|
87
|
+
- lib/pleasant_path/string.rb
|
88
|
+
- lib/pleasant_path/version.rb
|
89
|
+
- pleasant_path.gemspec
|
90
|
+
homepage: https://github.com/jonathanhefner/pleasant_path
|
91
|
+
licenses:
|
92
|
+
- MIT
|
93
|
+
metadata: {}
|
94
|
+
post_install_message:
|
95
|
+
rdoc_options: []
|
96
|
+
require_paths:
|
97
|
+
- lib
|
98
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
99
|
+
requirements:
|
100
|
+
- - ">="
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '0'
|
103
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
104
|
+
requirements:
|
105
|
+
- - ">="
|
106
|
+
- !ruby/object:Gem::Version
|
107
|
+
version: '0'
|
108
|
+
requirements: []
|
109
|
+
rubyforge_project:
|
110
|
+
rubygems_version: 2.4.8
|
111
|
+
signing_key:
|
112
|
+
specification_version: 4
|
113
|
+
summary: A fluent API for pleasant file IO.
|
114
|
+
test_files: []
|