tty-file 0.9.0 → 0.10.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 +4 -4
- data/CHANGELOG.md +15 -0
- data/README.md +144 -75
- data/lib/tty-file.rb +1 -1
- data/lib/tty/file.rb +237 -155
- data/lib/tty/file/compare_files.rb +70 -0
- data/lib/tty/file/create_file.rb +28 -14
- data/lib/tty/file/differ.rb +40 -20
- data/lib/tty/file/download_file.rb +2 -2
- data/lib/tty/file/version.rb +1 -1
- metadata +10 -8
@@ -0,0 +1,70 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "differ"
|
4
|
+
|
5
|
+
module TTY
|
6
|
+
module File
|
7
|
+
class CompareFiles
|
8
|
+
extend Forwardable
|
9
|
+
|
10
|
+
def initialize(format: :unified, header: true, context_lines: 5,
|
11
|
+
verbose: true, color: :green, noop: false, diff_colors: nil)
|
12
|
+
@format = format
|
13
|
+
@header = header
|
14
|
+
@context_lines = context_lines
|
15
|
+
@verbose = verbose
|
16
|
+
@color = color
|
17
|
+
@noop = noop
|
18
|
+
@diff_colors = diff_colors
|
19
|
+
end
|
20
|
+
|
21
|
+
# Compare files
|
22
|
+
#
|
23
|
+
# @api public
|
24
|
+
def call(file_a, file_b, file_a_path, file_b_path)
|
25
|
+
differ = Differ.new(format: @format, context_lines: @context_lines)
|
26
|
+
block_size = file_a.lstat.blksize
|
27
|
+
file_a_chunk = file_a.read(block_size)
|
28
|
+
file_b_chunk = file_b.read(block_size)
|
29
|
+
hunks = differ.(file_a_chunk, file_b_chunk)
|
30
|
+
|
31
|
+
return "" if file_a_chunk.empty? && file_b_chunk.empty?
|
32
|
+
return "No differences found\n" if hunks.empty?
|
33
|
+
|
34
|
+
output = []
|
35
|
+
|
36
|
+
if %i[unified context old].include?(@format) && @header
|
37
|
+
output << "#{differ.delete_char * 3} #{file_a_path}\n"
|
38
|
+
output << "#{differ.add_char * 3} #{file_b_path}"
|
39
|
+
end
|
40
|
+
|
41
|
+
output << "\n" unless hunks =~ /\A\n+@@/
|
42
|
+
output << hunks
|
43
|
+
while !file_a.eof? && !file_b.eof?
|
44
|
+
output << differ.(file_a.read(block_size), file_b.read(block_size))
|
45
|
+
end
|
46
|
+
color_diff_lines(output.join)
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
# @api private
|
52
|
+
def color_diff_lines(hunks)
|
53
|
+
return hunks unless @color && @format == :unified
|
54
|
+
|
55
|
+
newline = "\n"
|
56
|
+
hunks.lines.map do |line|
|
57
|
+
if matched = line.to_s.match(/^(\+[^+]*?)\n/)
|
58
|
+
@diff_colors[:green].(matched[1]) + newline
|
59
|
+
elsif matched = line.to_s.match(/^(\-[^-].*?)\n/)
|
60
|
+
@diff_colors[:red].(matched[1]) + newline
|
61
|
+
elsif matched = line.to_s.match(/^(@@.+?@@)\n/)
|
62
|
+
@diff_colors[:cyan].(matched[1]) + newline
|
63
|
+
else
|
64
|
+
line
|
65
|
+
end
|
66
|
+
end.join
|
67
|
+
end
|
68
|
+
end # CompareFiles
|
69
|
+
end # File
|
70
|
+
end # TTY
|
data/lib/tty/file/create_file.rb
CHANGED
@@ -6,18 +6,21 @@ module TTY
|
|
6
6
|
module File
|
7
7
|
class CreateFile
|
8
8
|
|
9
|
-
attr_reader :base, :relative_path, :content, :
|
9
|
+
attr_reader :base, :relative_path, :content, :prompt, :context
|
10
10
|
|
11
|
-
def initialize(base, relative_path, content,
|
11
|
+
def initialize(base, relative_path, content, context: nil, force: false,
|
12
|
+
skip: false, verbose: true, noop: false, color: :green,
|
13
|
+
quiet: true)
|
12
14
|
@base = base
|
13
15
|
@content = content
|
14
|
-
@
|
16
|
+
@context = context || @base
|
17
|
+
@force = force
|
18
|
+
@skip = skip
|
19
|
+
@noop = noop
|
20
|
+
@verbose = verbose
|
21
|
+
@color = color
|
15
22
|
@relative_path = convert_encoded_path(relative_path)
|
16
|
-
@prompt = TTY::Prompt.new
|
17
|
-
end
|
18
|
-
|
19
|
-
def context
|
20
|
-
options[:context] || @base
|
23
|
+
@prompt = TTY::Prompt.new(quiet: quiet)
|
21
24
|
end
|
22
25
|
|
23
26
|
def exist?
|
@@ -59,10 +62,10 @@ module TTY
|
|
59
62
|
if exist?
|
60
63
|
if identical?
|
61
64
|
notify(:identical, :cyan)
|
62
|
-
elsif
|
65
|
+
elsif @force
|
63
66
|
notify(:force, :yellow)
|
64
|
-
yield unless
|
65
|
-
elsif
|
67
|
+
yield unless @noop
|
68
|
+
elsif @skip
|
66
69
|
notify(:skip, :yellow)
|
67
70
|
else
|
68
71
|
notify(:collision, :red)
|
@@ -70,15 +73,16 @@ module TTY
|
|
70
73
|
end
|
71
74
|
else
|
72
75
|
notify(:create, :green)
|
73
|
-
yield unless
|
76
|
+
yield unless @noop
|
74
77
|
end
|
75
78
|
end
|
76
79
|
|
77
80
|
# Notify console about performed action
|
81
|
+
#
|
78
82
|
# @api private
|
79
83
|
def notify(name, color)
|
80
84
|
base.__send__(:log_status, name, relative_path,
|
81
|
-
|
85
|
+
verbose: @verbose, color: @color ? color : false)
|
82
86
|
end
|
83
87
|
|
84
88
|
# Display conflict resolution menu and gather answer
|
@@ -87,13 +91,23 @@ module TTY
|
|
87
91
|
def file_collision(relative_path, content)
|
88
92
|
choices = [
|
89
93
|
{ key: "y", name: "yes, overwrite", value: :yes },
|
94
|
+
{ key: "d", name: "diff, compare files", value: :diff },
|
90
95
|
{ key: "n", name: "no, do not overwrite", value: :no },
|
91
96
|
{ key: "q", name: "quit, abort", value: :quit }
|
92
97
|
]
|
93
|
-
answer = prompt.expand("Overwrite #{relative_path}?", choices)
|
98
|
+
while (answer = prompt.expand("Overwrite #{relative_path}?", choices)) == :diff do
|
99
|
+
show_diff
|
100
|
+
end
|
94
101
|
interpret_answer(answer)
|
95
102
|
end
|
96
103
|
|
104
|
+
# Display difference between old and new file
|
105
|
+
#
|
106
|
+
# @api private
|
107
|
+
def show_diff
|
108
|
+
print base.__send__(:diff_files, relative_path, content, verbose: @verbose)
|
109
|
+
end
|
110
|
+
|
97
111
|
# @api private
|
98
112
|
def interpret_answer(answer)
|
99
113
|
case answer
|
data/lib/tty/file/differ.rb
CHANGED
@@ -2,7 +2,6 @@
|
|
2
2
|
|
3
3
|
require "diff/lcs"
|
4
4
|
require "diff/lcs/hunk"
|
5
|
-
require "enumerator"
|
6
5
|
|
7
6
|
module TTY
|
8
7
|
module File
|
@@ -10,11 +9,9 @@ module TTY
|
|
10
9
|
# Create a Differ
|
11
10
|
#
|
12
11
|
# @api public
|
13
|
-
def initialize(
|
14
|
-
@
|
15
|
-
@
|
16
|
-
@format = options.fetch(:format, :unified)
|
17
|
-
@context_lines = options.fetch(:context_lines, 3)
|
12
|
+
def initialize(format: :unified, context_lines: 3)
|
13
|
+
@format = format
|
14
|
+
@context_lines = context_lines
|
18
15
|
end
|
19
16
|
|
20
17
|
# Find character difference between two strings
|
@@ -24,30 +21,53 @@ module TTY
|
|
24
21
|
# difference found
|
25
22
|
#
|
26
23
|
# @api public
|
27
|
-
def call
|
28
|
-
|
24
|
+
def call(string_a, string_b)
|
25
|
+
string_a_lines = convert_to_lines(string_a)
|
26
|
+
string_b_lines = convert_to_lines(string_b)
|
27
|
+
diffs = Diff::LCS.diff(string_a_lines, string_b_lines)
|
29
28
|
return "" if diffs.empty?
|
30
29
|
|
31
|
-
hunks
|
30
|
+
hunks = extract_hunks(diffs, string_a_lines, string_b_lines)
|
32
31
|
format_hunks(hunks)
|
33
32
|
end
|
34
33
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
34
|
+
# Diff add char
|
35
|
+
#
|
36
|
+
# @api public
|
37
|
+
def add_char
|
38
|
+
case @format
|
39
|
+
when :old
|
40
|
+
">"
|
41
|
+
when :unified
|
42
|
+
"+"
|
43
|
+
else
|
44
|
+
"*"
|
45
|
+
end
|
39
46
|
end
|
40
47
|
|
41
|
-
|
42
|
-
|
48
|
+
# Diff delete char
|
49
|
+
#
|
50
|
+
# @api public
|
51
|
+
def delete_char
|
52
|
+
case @format
|
53
|
+
when :old
|
54
|
+
"<"
|
55
|
+
when :unified
|
56
|
+
"-"
|
57
|
+
else
|
58
|
+
"*"
|
59
|
+
end
|
43
60
|
end
|
44
61
|
|
45
|
-
|
46
|
-
|
62
|
+
private
|
63
|
+
|
64
|
+
# @api private
|
65
|
+
def convert_to_lines(string)
|
66
|
+
string.split(/\n/).map(&:chomp)
|
47
67
|
end
|
48
68
|
|
49
|
-
# @api
|
50
|
-
def extract_hunks(diffs)
|
69
|
+
# @api private
|
70
|
+
def extract_hunks(diffs, string_a_lines, string_b_lines)
|
51
71
|
file_length_difference = 0
|
52
72
|
|
53
73
|
diffs.map do |piece|
|
@@ -58,7 +78,7 @@ module TTY
|
|
58
78
|
end
|
59
79
|
end
|
60
80
|
|
61
|
-
# @api
|
81
|
+
# @api private
|
62
82
|
def format_hunks(hunks)
|
63
83
|
output = []
|
64
84
|
hunks.each_cons(2) do |prev_hunk, current_hunk|
|
@@ -14,10 +14,10 @@ module TTY
|
|
14
14
|
|
15
15
|
# @options
|
16
16
|
#
|
17
|
-
def initialize(url, dest_path,
|
17
|
+
def initialize(url, dest_path, limit: nil)
|
18
18
|
@uri = URI.parse(url)
|
19
19
|
@dest_path = dest_path
|
20
|
-
@limit =
|
20
|
+
@limit = limit || DEFAULT_REDIRECTS
|
21
21
|
end
|
22
22
|
|
23
23
|
# Download a file
|
data/lib/tty/file/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tty-file
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.10.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Piotr Murach
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-07-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: pastel
|
@@ -16,28 +16,28 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 0.
|
19
|
+
version: '0.8'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 0.
|
26
|
+
version: '0.8'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: tty-prompt
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '0.
|
33
|
+
version: '0.22'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '0.
|
40
|
+
version: '0.22'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: diff-lcs
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -109,20 +109,22 @@ files:
|
|
109
109
|
- README.md
|
110
110
|
- lib/tty-file.rb
|
111
111
|
- lib/tty/file.rb
|
112
|
+
- lib/tty/file/compare_files.rb
|
112
113
|
- lib/tty/file/create_file.rb
|
113
114
|
- lib/tty/file/differ.rb
|
114
115
|
- lib/tty/file/digest_file.rb
|
115
116
|
- lib/tty/file/download_file.rb
|
116
117
|
- lib/tty/file/read_backward_file.rb
|
117
118
|
- lib/tty/file/version.rb
|
118
|
-
homepage: https://
|
119
|
+
homepage: https://ttytoolkit.org
|
119
120
|
licenses:
|
120
121
|
- MIT
|
121
122
|
metadata:
|
122
123
|
allowed_push_host: https://rubygems.org
|
124
|
+
bug_tracker_uri: https://github.com/piotrmurach/tty-file/issues
|
123
125
|
changelog_uri: https://github.com/piotrmurach/tty-file/blob/master/CHANGELOG.md
|
124
126
|
documentation_uri: https://www.rubydoc.info/gems/tty-file
|
125
|
-
homepage_uri: https://
|
127
|
+
homepage_uri: https://ttytoolkit.org
|
126
128
|
source_code_uri: https://github.com/piotrmurach/tty-file
|
127
129
|
post_install_message:
|
128
130
|
rdoc_options: []
|