csv-editor 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: fd5c303e0caeb77eb22d4cf57b9ca6126306c11de9a5e34cd1a9708d5501afa3
4
+ data.tar.gz: 11a15413cdabf43c0fac5b15ffc1d061ca28f3a411fc86d909e167374ed9310c
5
+ SHA512:
6
+ metadata.gz: '08bc45ac87edbc4d21b2a9979e809224a9a49bc1e44e3ecf65724c316953382673b04bcc4652cc51bbd191df65ebc8e60d3abf644b83709b761683fe8582da50'
7
+ data.tar.gz: ec89e515578517eb8f1f1ee9632982bb66532b65c08a2efb96a6291ed89154614e0d911d3da78dae7a1ebaba089ae27dfea33b2ed36f12c4cb346b49bd66fccb
data/.gitignore ADDED
@@ -0,0 +1,59 @@
1
+ *.gem
2
+ *.rbc
3
+ /.config
4
+ /coverage/
5
+ /InstalledFiles
6
+ /pkg/
7
+ /spec/reports/
8
+ /spec/examples.txt
9
+ /test/tmp/
10
+ /test/version_tmp/
11
+ /tmp/
12
+
13
+ # Used by dotenv library to load environment variables.
14
+ # .env
15
+
16
+ # Ignore Byebug command history file.
17
+ .byebug_history
18
+
19
+ ## Specific to RubyMotion:
20
+ .dat*
21
+ .repl_history
22
+ build/
23
+ *.bridgesupport
24
+ build-iPhoneOS/
25
+ build-iPhoneSimulator/
26
+
27
+ ## Specific to RubyMotion (use of CocoaPods):
28
+ #
29
+ # We recommend against adding the Pods directory to your .gitignore. However
30
+ # you should judge for yourself, the pros and cons are mentioned at:
31
+ # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
32
+ #
33
+ # vendor/Pods/
34
+
35
+ ## Documentation cache and generated files:
36
+ /.yardoc/
37
+ /_yardoc/
38
+ /doc/
39
+ /rdoc/
40
+
41
+ ## Environment normalization:
42
+ /.bundle/
43
+ /vendor/bundle
44
+ /lib/bundler/man/
45
+
46
+ # for a library or gem, you might want to ignore these files since the code is
47
+ # intended to run in multiple environments; otherwise, check them in:
48
+ # Gemfile.lock
49
+ # .ruby-version
50
+ # .ruby-gemset
51
+
52
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
53
+ .rvmrc
54
+
55
+ # Used by RuboCop. Remote config files pulled in from inherit_from directive.
56
+ # .rubocop-https?--*
57
+
58
+ # Emacs
59
+ *~
data/.ruby-gemset ADDED
@@ -0,0 +1 @@
1
+ csv-editor
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 3.3.0
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 dougyouch
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 all
13
+ 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 THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,2 @@
1
+ # csv-editor
2
+ Command line tools for editing CSV files
data/bin/csv-edit ADDED
@@ -0,0 +1,119 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Purpose: use the command line to edit a CSV file
4
+
5
+ if ARGV[0] == '-h'
6
+ puts "Usage: csv-edit <CSV FILE>"
7
+ exit(0)
8
+ end
9
+
10
+ require 'csv-utils'
11
+ require 'tty-prompt'
12
+ require 'io/console'
13
+
14
+ csv_file = ARGV[0]
15
+ raise("#{csv_file} not found") unless File.exist?(csv_file)
16
+
17
+ def screen_width
18
+ @screen_width ||= (IO.console.winsize[1] - 10)
19
+ end
20
+
21
+ def escape_csv_value(value)
22
+ value
23
+ .gsub("\r", "\\r")
24
+ .gsub("\n", "\\n")
25
+ .gsub("\t", "\\t")
26
+ end
27
+
28
+ def csv_row_to_s(row_number, row)
29
+ str = "#{row_number}. "
30
+ sep = ''
31
+ row.each_with_index do |(k, v), idx|
32
+ if idx == 0 || v.to_s != ''
33
+ str += "#{sep}#{k}: #{escape_csv_value(v)}"
34
+ sep = ', '
35
+ end
36
+
37
+ break if str.size >= screen_width
38
+ end
39
+
40
+ if str.size > screen_width
41
+ return str[0..screen_width] + ' ...'
42
+ end
43
+
44
+ str
45
+ end
46
+
47
+ def add_row(csv_iterator)
48
+ csv_iterator.headers.each_with_object({}) { |header, obj| obj[header] = '' }
49
+ end
50
+
51
+ def pick_csv_row(prompt, rows, starting_row_idx, max_rows_to_display=100_000)
52
+ choices = [{name: '<< Add Row >>', value: nil}]
53
+ rows.each_with_index do |row, idx|
54
+ next unless idx >= starting_row_idx
55
+
56
+ row_number = idx + 1
57
+ choices << {name: csv_row_to_s(row_number, row), value: row}
58
+
59
+ break if choices.size > max_rows_to_display
60
+ end
61
+
62
+ prompt.select(('Pick row to edit'), choices)
63
+ end
64
+
65
+ def edit_row(prompt, row)
66
+ done = false
67
+ while !done
68
+ choices = [{name: '<< Done >>', value: true}]
69
+
70
+ row.each do |column_name, column_value|
71
+ name = "#{column_name}: #{column_value}"
72
+ choices << {name: name, value: column_name}
73
+ end
74
+
75
+ choice = prompt.select('Edit?', choices)
76
+ if choice == true
77
+ done = true
78
+ break
79
+ end
80
+
81
+ new_value = prompt.ask("#{choice}: ", value: row[choice].to_s)
82
+ row[choice] = new_value
83
+ end
84
+
85
+ row
86
+ end
87
+
88
+ csv_iterator = CSVUtils::CSVIterator.new(csv_file)
89
+ rows = csv_iterator.to_a
90
+
91
+ prompt = TTY::Prompt.new
92
+
93
+ prompt.on(:keypress) do |event|
94
+ if event.value == "\u0013" # CTRL-s
95
+ new_csv_file = csv_file + '.' + Time.now.strftime('%Y%m%dT%H%M%S') + '.csv'
96
+ puts "\nsaving to #{new_csv_file}"
97
+ CSV.open(new_csv_file, 'wb') do |out|
98
+ out << csv_iterator.headers
99
+ rows.each do |row|
100
+ out << row.values
101
+ end
102
+ end
103
+ exit(0)
104
+ elsif event.value == "\u0011" # CTRL-q
105
+ puts "\nquiting"
106
+ exit(0)
107
+ end
108
+ end
109
+
110
+ while true
111
+ row = pick_csv_row(prompt, rows, 0, 100)
112
+
113
+ if row.nil?
114
+ row = add_row(csv_iterator)
115
+ rows << row
116
+ end
117
+
118
+ edit_row(prompt, row)
119
+ end
data/bin/csv-edit-row ADDED
@@ -0,0 +1,68 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Purpose: use the command line to edit 1 row of a CSV file
4
+
5
+ if ARGV[0] == '-h'
6
+ puts "Usage: csv-edit-row <CSV FILE> [<ROW>]"
7
+ puts " * if <ROW> is not specified a new row is added to bottom of the csv file"
8
+ exit(0)
9
+ end
10
+
11
+ require 'csv-utils'
12
+ require 'tty-prompt'
13
+
14
+ csv_file = ARGV[0]
15
+ row_number = ARGV[1].to_i
16
+ raise("#{csv_file} not found") unless File.exist?(csv_file)
17
+ raise("CSV row number not specified") unless row_number >= 0
18
+
19
+ csv_iterator = CSVUtils::CSVIterator.new(csv_file)
20
+ raise("CSV row number exceeds max rows") if row_number > csv_iterator.size
21
+
22
+ cnt = 0
23
+ row =
24
+ if row_number == 0
25
+ csv_iterator.headers.each_with_object({}) { |header, obj| obj[header] = '' }
26
+ else
27
+ csv_iterator.detect { |_| cnt += 1; cnt == row_number }
28
+ end
29
+
30
+ prompt = TTY::Prompt.new
31
+
32
+ prompt.on(:keypress) do |event|
33
+ if event.value == "\u0013" # CTRL-s
34
+ new_csv_file = csv_file + '.' + Time.now.strftime('%Y%m%dT%H%M%S') + '.csv'
35
+ puts "\nsaving to #{new_csv_file}"
36
+ CSV.open(new_csv_file, 'w') do |out|
37
+ out << csv_iterator.headers
38
+ csv_iterator.each_with_index do |csv_row, idx|
39
+ if (idx + 1) == row_number
40
+ out << row.values
41
+ else
42
+ out << csv_row.values
43
+ end
44
+ end
45
+
46
+ if row_number == 0
47
+ out << row.values
48
+ end
49
+ end
50
+ exit(0)
51
+ elsif event.value == "\u0011" # CTRL-q
52
+ puts "\nquiting"
53
+ exit(0)
54
+ end
55
+ end
56
+
57
+ while true
58
+ choices = []
59
+ row.each do |column_name, column_value|
60
+ name = "#{column_name}: #{column_value}"
61
+ choices << {name: name, value: column_name}
62
+ end
63
+
64
+ choice = prompt.select((row_number == 0 ? 'Add?' : 'Edit?'), choices)
65
+ new_value = prompt.ask("#{choice}: ", value: row[choice].to_s)
66
+
67
+ row[choice] = new_value
68
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = 'csv-editor'
5
+ s.version = '0.1.5'
6
+ s.licenses = ['MIT']
7
+ s.summary = 'CSV Editor'
8
+ s.description = 'Command line CSV file editor'
9
+ s.authors = ['Doug Youch']
10
+ s.email = 'dougyouch@gmail.com'
11
+ s.homepage = 'https://github.com/dougyouch/csv-editor'
12
+ s.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
13
+ s.bindir = 'bin'
14
+ s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
15
+
16
+ s.add_runtime_dependency 'csv-utils'
17
+ s.add_runtime_dependency 'tty-prompt'
18
+ end
metadata ADDED
@@ -0,0 +1,80 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: csv-editor
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.5
5
+ platform: ruby
6
+ authors:
7
+ - Doug Youch
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2024-07-06 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: csv-utils
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: tty-prompt
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: Command line CSV file editor
42
+ email: dougyouch@gmail.com
43
+ executables:
44
+ - csv-edit
45
+ - csv-edit-row
46
+ extensions: []
47
+ extra_rdoc_files: []
48
+ files:
49
+ - ".gitignore"
50
+ - ".ruby-gemset"
51
+ - ".ruby-version"
52
+ - LICENSE
53
+ - README.md
54
+ - bin/csv-edit
55
+ - bin/csv-edit-row
56
+ - csv-editor.gemspec
57
+ homepage: https://github.com/dougyouch/csv-editor
58
+ licenses:
59
+ - MIT
60
+ metadata: {}
61
+ post_install_message:
62
+ rdoc_options: []
63
+ require_paths:
64
+ - lib
65
+ required_ruby_version: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ required_rubygems_version: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ requirements: []
76
+ rubygems_version: 3.2.3
77
+ signing_key:
78
+ specification_version: 4
79
+ summary: CSV Editor
80
+ test_files: []