ned 0.0.1 → 0.0.2

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.
data/lib/ned_old.rb ADDED
@@ -0,0 +1,193 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'ned/command'
4
+ require 'ned/config'
5
+ require 'ned/context'
6
+ require 'ned/strings'
7
+ require 'ned/validators'
8
+ require 'ned/version'
9
+
10
+ Dir["#{__dir__}/ned/commands/**/*.rb"].sort.each { |f| require f }
11
+
12
+ module Ned
13
+ def self.help(error_output)
14
+ error_output.puts <<~EOF
15
+ A stream editor.
16
+
17
+ Usage: ned [file] [options ...]
18
+
19
+ Options:
20
+ EOF
21
+
22
+ lines = [
23
+ [' --help', 'Print this message.'],
24
+ [' --version', 'Print version.']
25
+ ]
26
+ max = lines[0][0].length
27
+ Ned::Config.all.each do |config|
28
+ next if config.hidden?
29
+
30
+ line = "#{config.short}, #{config.long} #{config.params}"
31
+ lines << [line, config.description]
32
+ max = [max, line.length].max
33
+ end
34
+
35
+ lines.each do |line|
36
+ error_output.puts " #{line[0].ljust(max)} #{line[1]}"
37
+ end
38
+ end
39
+
40
+ def self.failure(error_output, message)
41
+ error_output.puts "fatal: #{message}\n\n"
42
+ help(error_output)
43
+ end
44
+
45
+ def self.run(input: $stdin, output: $stdout, error_output: $stderr, args: ARGV)
46
+ args = args.map do |arg|
47
+ Ned::Strings.unescape!(arg.dup)
48
+ end
49
+
50
+ if args.include?('--help')
51
+ help(error_output)
52
+ return 0
53
+ end
54
+
55
+ if args.include?('--version')
56
+ output.puts("Ned version #{Ned::VERSION}")
57
+ return 0
58
+ end
59
+
60
+ inputs = []
61
+ while args.first && !args.first.match(/^-./)
62
+ arg = args.shift
63
+
64
+ if arg == '-'
65
+ inputs << input
66
+ else
67
+ unless File.exist?(arg)
68
+ failure(error_output, "no such file: #{arg}")
69
+ return 1
70
+ end
71
+ inputs << arg
72
+ end
73
+ end
74
+
75
+ if input.tty? && (inputs.empty? || (inputs.size == 1 && inputs[0] == input))
76
+ failure(error_output, 'no input')
77
+ return 1
78
+ end
79
+
80
+ inputs = inputs.unshift(input) if !input.tty? && !inputs.index(input)
81
+
82
+ if inputs.count(input) > 1
83
+ failure(error_output, "can't read from standard in twice, silly")
84
+ return 1
85
+ end
86
+
87
+ if inputs.size > 1
88
+ failure(error_output, "more than one input not yet supported")
89
+ return 1
90
+ end
91
+
92
+ commands = []
93
+
94
+ while arg = args.shift
95
+ config = Ned::Config.all.find do |config|
96
+ arg.start_with?(config.short) || arg == config.long || arg.start_with?("#{config.long}=")
97
+ end
98
+
99
+ unless config
100
+ failure(error_output, "invalid option: #{arg}")
101
+ return 1
102
+ end
103
+
104
+ params = []
105
+
106
+ if arg.start_with?("#{config.long}=")
107
+ params << arg["#{config.long}=".size..-1]
108
+ elsif arg.start_with?(config.short) && arg != config.short
109
+ params << arg[config.short.size..-1]
110
+ else
111
+ while !args.empty? && !args.first.start_with?('-')
112
+ arg = args.shift
113
+ if arg.start_with? '\\-'
114
+ arg = arg[1..-1]
115
+ end
116
+ params << arg
117
+ end
118
+ end
119
+
120
+ valid = config.validate(*params)
121
+ if valid.nil?
122
+ if config.params.nil?
123
+ failure(error_output, "invalid param for #{config.name}. found: #{params}, expected none")
124
+ return 1
125
+ else
126
+ failure(error_output, "invalid param for #{config.name}. found: #{params}, expected: #{config.params}")
127
+ return 1
128
+ end
129
+ end
130
+
131
+ commands << Ned::Command.new(config, valid)
132
+ end
133
+
134
+ if commands.any?(&:all?)
135
+ lines = inputs.flat_map do |i|
136
+ if i.is_a? String
137
+ IO.readlines(i, sep="\n")
138
+ else
139
+ i.readlines(sep="\n")
140
+ end
141
+ end
142
+ process_all(commands, lines, output)
143
+ else
144
+ process_each(commands, inputs, output)
145
+ end
146
+
147
+ 0
148
+ end
149
+
150
+ def self.process_all(commands, lines, output)
151
+ final_newline = lines[-1]&.[](-1) == "\n" ? "\n" : ''
152
+
153
+ lines = lines.map { |line| line.chomp("\n") }
154
+ context = Context.new(lines, 0)
155
+ commands.each do |command|
156
+ command.execute(context)
157
+ end
158
+ last = context.lines.length - 1
159
+ context.lines.each_with_index do |line, index|
160
+ output.print "#{line}#{index == last ? final_newline : "\n"}"
161
+ end
162
+ end
163
+
164
+ def self.process_each(commands, inputs, output)
165
+ input = inputs[0]
166
+
167
+ if input.is_a? String
168
+ input = File.open(input)
169
+ end
170
+
171
+ current = input.gets(sep="\n")
172
+ next_line = input.gets(sep="\n")
173
+ index = 0
174
+
175
+ while current
176
+ final_newline = current[-1]&.[](-1) == "\n" ? "\n" : ''
177
+ context = Context.new([current.chomp("\n")], index)
178
+ commands.each do |command|
179
+ command.execute(context)
180
+ end
181
+ index = context.start_index + context.lines.size
182
+ last = context.lines.length - 1
183
+ context.lines.each_with_index do |line, index|
184
+ output.print "#{line}#{index == last && next_line.nil? ? final_newline : "\n"}"
185
+ end
186
+
187
+ current = next_line
188
+ next_line = input.gets(sep="\n")
189
+ end
190
+
191
+ input.close
192
+ end
193
+ end
data/ned.gemspec CHANGED
@@ -8,8 +8,8 @@ Gem::Specification.new do |spec|
8
8
  spec.authors = ["Nick Dower"]
9
9
  spec.email = ["nicholasdower@gmail.com"]
10
10
 
11
- spec.summary = "A command line editor."
12
- spec.description = "A command line editor"
11
+ spec.summary = "A stream editor."
12
+ spec.description = "A stream editor"
13
13
  spec.homepage = "https://github.com/nicholasdower/ned"
14
14
  spec.license = "MIT"
15
15
 
@@ -5,4 +5,10 @@ puts <<~EOF
5
5
 
6
6
  ```
7
7
  #{`bundle exec ned --help 2>&1`}```
8
+
9
+ ## Installation
10
+
11
+ ```
12
+ gem install ned
13
+ ```
8
14
  EOF
@@ -0,0 +1,29 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'files' do
4
+ test_failure 'no input', args: '-s', stdin: nil, stderr: 'fatal: no input'
5
+
6
+ test_failure 'no such file', args: 'foo -s', stdin: nil, stderr: 'fatal: no such file: foo'
7
+
8
+ test_failure 'multiple files', args: 'spec/support/file spec/support/file -s', stdin: nil, stderr: 'fatal: more than one input not yet supported'
9
+
10
+ test_failure 'no input, standard in as file arg', args: '- -s', stdin: nil, stderr: 'fatal: no input'
11
+
12
+ test_failure 'standard in as file arg multiple times', args: '- - -s', stdin: '', stderr: "fatal: can't read from standard in twice, silly"
13
+
14
+ context 'all lines read' do
15
+ test_success 'standard in', stdin: "two\none\n", args: '-s', stdout: "one\ntwo\n"
16
+
17
+ test_success 'standard in as file arg', stdin: "two\none\n", args: '- -s', stdout: "one\ntwo\n"
18
+
19
+ test_success 'single file', stdin: nil, args: 'spec/support/file -s', stdout: "one\nthree\ntwo\n"
20
+ end
21
+
22
+ context 'lines read one at a time' do
23
+ test_success 'standard in', stdin: "two\none\n", args: '-a 1', stdout: "two1\none1\n"
24
+
25
+ test_success 'standard in as file arg', stdin: "two\none\n", args: '- -a 1', stdout: "two1\none1\n"
26
+
27
+ test_success 'single file', stdin: nil, args: 'spec/support/file -a 1', stdout: "one1\ntwo1\nthree1\n"
28
+ end
29
+ end
metadata CHANGED
@@ -1,16 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ned
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nick Dower
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-05-29 00:00:00.000000000 Z
11
+ date: 2022-06-07 00:00:00.000000000 Z
12
12
  dependencies: []
13
- description: A command line editor
13
+ description: A stream editor
14
14
  email:
15
15
  - nicholasdower@gmail.com
16
16
  executables:
@@ -25,30 +25,32 @@ files:
25
25
  - bin/ned
26
26
  - lib/ned.rb
27
27
  - lib/ned/command.rb
28
+ - lib/ned/command_registry.rb
28
29
  - lib/ned/commands/append.rb
29
30
  - lib/ned/commands/backward.rb
30
- - lib/ned/commands/grep.rb
31
31
  - lib/ned/commands/head.rb
32
32
  - lib/ned/commands/index.rb
33
33
  - lib/ned/commands/join.rb
34
- - lib/ned/commands/only.rb
35
34
  - lib/ned/commands/prepend.rb
35
+ - lib/ned/commands/print.rb
36
36
  - lib/ned/commands/quote.rb
37
- - lib/ned/commands/replace.rb
37
+ - lib/ned/commands/read.rb
38
38
  - lib/ned/commands/sort.rb
39
39
  - lib/ned/commands/tail.rb
40
40
  - lib/ned/commands/uniq.rb
41
- - lib/ned/commands/visual.rb
42
- - lib/ned/config.rb
43
- - lib/ned/context.rb
41
+ - lib/ned/string.rb
44
42
  - lib/ned/strings.rb
45
- - lib/ned/validators.rb
46
43
  - lib/ned/version.rb
44
+ - lib/ned_old.rb
45
+ - lib/ned_old/commands/grep.rb
46
+ - lib/ned_old/commands/only.rb
47
+ - lib/ned_old/commands/replace.rb
48
+ - lib/ned_old/commands/visual.rb
47
49
  - ned.gemspec
48
50
  - scripts/generate_readme
49
51
  - scripts/release
50
52
  - scripts/test
51
- - todo
53
+ - spec_old/file_spec.rb
52
54
  homepage: https://github.com/nicholasdower/ned
53
55
  licenses:
54
56
  - MIT
@@ -74,5 +76,5 @@ requirements: []
74
76
  rubygems_version: 3.3.3
75
77
  signing_key:
76
78
  specification_version: 4
77
- summary: A command line editor.
79
+ summary: A stream editor.
78
80
  test_files: []
data/lib/ned/config.rb DELETED
@@ -1,73 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Ned
4
- class Config
5
- class << self
6
- attr_reader :all
7
- end
8
-
9
- @all = []
10
-
11
- def self.add(name:, description:, short:, long:, params:, validator:, execute:, all: nil, hidden: false)
12
- @all.each do |config|
13
- if config.short.start_with?(short) || short.start_with?(config.short)
14
- raise "Cannot add command #{name}. Flag conflicts with #{config.name}."
15
- end
16
-
17
- if config.long.start_with?(long) || long.start_with?(config.long)
18
- raise "Cannot add command #{name}. Flag conflicts with #{config.name}."
19
- end
20
- end
21
-
22
- @all << Config.new(
23
- name: name,
24
- description: description,
25
- short: short,
26
- long: long,
27
- params: params,
28
- validator: validator,
29
- execute: execute,
30
- all: all,
31
- hidden: hidden
32
- )
33
- end
34
-
35
- attr_reader :name, :description, :short, :long, :params
36
-
37
- def initialize(name:, description:, short:, long:, params:, validator:, execute:, all: nil, hidden: false)
38
- @name = name
39
- @description = description
40
- @short = short
41
- @long = long
42
- @params = params
43
- @validator = validator
44
- @execute = execute
45
- @hidden = hidden
46
-
47
- all = all || false
48
- if [true, false].include? all
49
- @all = lambda { |*params| all }
50
- elsif all.is_a? Proc
51
- @all = all
52
- else
53
- raise "Invalid all type for #{name}: #{all.class}"
54
- end
55
- end
56
-
57
- def validate(*args)
58
- @validator.call(*args)
59
- end
60
-
61
- def all?(params)
62
- @all.call(*params)
63
- end
64
-
65
- def hidden?
66
- @hidden
67
- end
68
-
69
- def execute(*args)
70
- @execute.call(*args)
71
- end
72
- end
73
- end
data/lib/ned/context.rb DELETED
@@ -1,10 +0,0 @@
1
- module Ned
2
- class Context
3
- attr_accessor :lines, :start_index
4
-
5
- def initialize(lines, start_index)
6
- @lines = lines
7
- @start_index = start_index
8
- end
9
- end
10
- end
@@ -1,19 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Ned
4
- class Validators
5
- def self.none
6
- lambda { |*params| params.length == 0 ? [] : nil }
7
- end
8
-
9
- def self.num(min, max = nil, &block)
10
- lambda do |*params|
11
- max = min unless max
12
-
13
- return nil if params.length < min || params.length > max
14
-
15
- block.nil? ? params : yield(*params)
16
- end
17
- end
18
- end
19
- end
data/todo DELETED
@@ -1,15 +0,0 @@
1
- add support for a ~/.ned/ dir
2
- implement highlight
3
- add color
4
- add support for more escape sequences, see https://github.com/ruby/ruby/blob/master/doc/syntax/literals.rdoc#label-Strings
5
- add support for operating on one or more files
6
- add support for editing files in place
7
- handle --
8
- add ljust
9
- maybe add ability to highlight columns, not just full lines
10
- write readme
11
- add support for to_set
12
- add support for overriding existing commands
13
- add support for ommitting short or long flags
14
- add support for uniq with count?
15
- consider giving commands a way to operate on entire line with newline. currently can't replicate tr.