nxxd 1.0 → 1.1

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
2
  SHA256:
3
- metadata.gz: 5235dca5d1f46e13930f0d67076555a589a8966f4e83abf933a805ca722abbfe
4
- data.tar.gz: 16ee0e67f7b9b8d765639470d7aff99c8e4aa71a5668493808589fcd42089ccd
3
+ metadata.gz: 68a908962e81a416580c2987b7523f755e85e1963c20908420fb579710b6a865
4
+ data.tar.gz: b18d9db546926037e9646a22e6c8394fd6d4ff86ad048b8be22a697d07698a87
5
5
  SHA512:
6
- metadata.gz: b9b88cd360d0af386401df8eada33e03718790136ce709d4f5d74ea4f54311d2a22df54e7f6d157d6a8ed53a5d073ccf1958f40f582aa8d2cae3b4d7f74dc175
7
- data.tar.gz: 3e6a4f1b49aeef9867e80b0b900b99951a6b37d53d4b8f1ee82d37f9d58f773355f2a72d651e5df734022d942d7673d0c7af76f384f5a8cd564eb69ff2b2dadc
6
+ metadata.gz: d941c8d1202b8bcbf0b1b0507216665e1c1e81035ff224861e6183d8a82b4354b701a3231e14803c9e7d934dc75cbb1dd8d6210ca46c36f8275c3234d34a25af
7
+ data.tar.gz: abd20b6a161993d5ab0d8047623c8d137b7eec56512f72269a942feae25521ecd9549faceec3276e4df654008a84dcdf4c37b1c000ef5e473a74251850307380
data/README.md CHANGED
@@ -65,11 +65,16 @@ Here's an example:
65
65
 
66
66
  ```ruby
67
67
  require "nxxd"
68
-
69
68
  data = " !\"\#$%&'()*+,-./0123456789:;<=>?"
70
69
  Nxxd::Dump.new.run data do |l| puts l end
71
70
  ```
72
71
 
72
+ Or just:
73
+
74
+ ```ruby
75
+ puts Nxxd::Dump.new.run data
76
+ ```
77
+
73
78
  Reverse operation allows free address jumping.
74
79
  Both string and file output can be done.
75
80
 
@@ -90,6 +95,45 @@ end
90
95
  ```
91
96
 
92
97
 
98
+ ## Inside Neovim
99
+
100
+ If you're using Neovim and the Ruby provider
101
+ [ruby-nvim](https://github.com/BertramScharpf/ruby-nvim) (Not the official
102
+ neovim-ruby!), you probably prefer to pipe from and to buffers.
103
+
104
+ ```vim
105
+ rubyfile <nxxd/nvim>
106
+ vertical HexDump /etc/localtime
107
+ ```
108
+
109
+ In case you have a string in a Ruby variable, dump it like this:
110
+
111
+ ```vim
112
+ ruby t = "tränenüberströmt"
113
+ ruby Nxxd::Nvim.dump_data t
114
+ ```
115
+
116
+ You may dump a programs output as well:
117
+
118
+ ```vim
119
+ HexDump! echo QmF6aW5nYSEK | openssl enc -a -d
120
+ HexDump! dd if=/dev/urandom bs=16 count=4
121
+ ```
122
+
123
+ Pipe your editor lines to a program like this:
124
+
125
+ ```
126
+ 1 H4sIALDvomcAA7u3
127
+ 2 dt/7ewOIAX8tU5eA
128
+ 3 AAAA
129
+ ~
130
+ ~
131
+ :1,3HexPipe openssl enc -a -d | gzip -cd
132
+ ```
133
+
134
+ See the file [nxxd.txt](./vim/doc/nxxd.txt) for a full documentation.
135
+
136
+
93
137
  ## Colorization
94
138
 
95
139
  There is no and there will be no color support. Pipe the output to your
data/bin/nxxd CHANGED
@@ -15,26 +15,28 @@ module Nxxd
15
15
  NAME = "nxxd"
16
16
 
17
17
  OPTIONS = {
18
- "r" => [ :reverse, true, "Reverse operation, pack"],
19
- "o" => [ :output, :NAME, "Output file (- = stdout)"],
18
+ "r" => [ :reverse, true, "Reverse operation, pack"],
19
+ "o" => [ :output, :NAME, "Output file (- = stdout)"],
20
20
  "output" => "o",
21
- "f" => [ :full, true, "Full output (no squeeze)"],
21
+ "f" => [ :full, true, "Full output (no squeeze)"],
22
22
  "full" => "f",
23
- "a" => [ :full, false, "Abbreviate (squeeze duplicate lines)"],
24
- "p" => [ :plain, true, "Plain output (no comments, no C variables)"],
25
- "u" => [ :upper, true, "Upper case A-F"],
23
+ "a" => [ :full, false, "Abbreviate (squeeze duplicate lines)"],
24
+ "p" => [ :plain, true, "Plain output (no comments, no C variables)"],
25
+ "u" => [ :upper, true, "Upper case A-F"],
26
26
  "upper" => "u",
27
- "l" => [ :line_size, :NUM, "Line size"],
27
+ "l" => [ :line_size, :NUM, "Line size"],
28
28
  "line" => "l",
29
- "d" => [ :addr_len, :NUM, "Address length"],
29
+ "d" => [ :addr_len, :NUM, "Address length"],
30
30
  "addrs" => "d",
31
- "i" => [ :cnums, true, "C-style number literals"],
31
+ "i" => [ :cnums, true, "C-style number literals"],
32
32
  "include" => "i",
33
- "C" => [ :capitals, true, "Capitalize C variable names with -i"],
33
+ "C" => [ :capitals, true, "Capitalize C variable names with -i"],
34
34
  "capitalize" => "C",
35
- "h" => [ :help, :help, "Print this help message"],
35
+ "c" => [ :consecutive, true, "Consecutive undump (ignore addresses)"],
36
+ "consecutive" => "c",
37
+ "h" => [ :help, :help, "Print this help message"],
36
38
  "help" => "h",
37
- "v" => [ :version, :version, "Version information"],
39
+ "v" => [ :version, :version, "Version information"],
38
40
  "version" => "v",
39
41
  }
40
42
 
@@ -154,9 +156,9 @@ module Nxxd
154
156
 
155
157
  def run
156
158
  open_output do |o|
157
- if @opts[ :reverse] then
159
+ if @opts.delete :reverse then
158
160
  open_inputs do |f|
159
- Dump.reverse f, o
161
+ Dump.reverse f, o, **@opts
160
162
  end
161
163
  else
162
164
  cls = (@opts.delete :cnums) ? DumpNums : Dump
@@ -188,8 +190,8 @@ module Nxxd
188
190
  plain = @opts.delete :plain
189
191
  @inputs.each do |i|
190
192
  i = nil if i == "-"
191
- @opts[ :input] = i unless plain
192
193
  if i then
194
+ @opts[ :input] = i unless plain or @opts[ :reverse]
193
195
  File.open i, "r" do |f|
194
196
  yield f
195
197
  end
data/lib/nxxd/nvim.rb CHANGED
@@ -8,35 +8,12 @@ require "nxxd"
8
8
  raise "This file must be required from inside Neovim using the 'nvim' Rubygem."
9
9
 
10
10
 
11
- [
12
- "command -nargs=? -bang -complete=file -bar HexDump call rubyeval('Nxxd::Nvim.dump<bang> %q|<args>|')",
13
- "command -nargs=? -range=% -bang -complete=file -bar HexPack call rubyeval('Nxxd::Nvim.pack<bang> %q|<args>|, <line1>..<line2>')",
14
- ].each { |c| $vim.command c }
15
-
16
-
17
-
18
- module Kernel
19
- class <<self
20
- def popen_outerr a
21
- ro, wo = IO.pipe
22
- re, we = IO.pipe
23
- fork do
24
- ro.close
25
- re.close
26
- STDOUT.reopen wo
27
- STDERR.reopen we
28
- exec a
29
- end
30
- wo.close
31
- we.close
32
- yield ro, re
33
- Process.waitpid
34
- ensure
35
- ro.close
36
- re.close
37
- end
38
- end
39
- end
11
+ <<~'EOT'.each_line { |c| c.chomp! ; $vim.command c }
12
+ command -nargs=? -bang -complete=file HexDump ruby Nxxd::Nvim.dump<bang> <q-args>, <q-mods>
13
+ command -nargs=1 -range=% -complete=file HexPipe ruby Nxxd::Nvim.pipe <q-args>, <q-mods>, <line1>..<line2>
14
+ command -nargs=? -range=% -bang -complete=file -bar HexPack ruby Nxxd::Nvim.pack<bang> <q-args>, <range>, <line1>..<line2>
15
+ command -nargs=1 -range=% -complete=file HexFeed ruby Nxxd::Nvim.feed <q-args>, <line1>..<line2>
16
+ EOT
40
17
 
41
18
 
42
19
  module Nxxd
@@ -45,69 +22,142 @@ module Nxxd
45
22
 
46
23
  class <<self
47
24
 
48
- def dump a
49
- a ||= $vim.get_name 0
25
+ attr_accessor :split
26
+
27
+ private
28
+
29
+ def split_new mods
30
+ if mods.notempty? then
31
+ "#{mods} new"
32
+ else
33
+ case @split
34
+ when /\bvert/ then "vnew"
35
+ when /\bhor/ then "new"
36
+ else "enew"
37
+ end
38
+ end
39
+ end
40
+
41
+ public
42
+
43
+ def dump a, m
44
+ a = a.notempty?
45
+ a ||= cur_buf_name
50
46
  File.open a do |f|
51
- dump_file a, f
47
+ dump_data f, a, m
52
48
  end
53
49
  $vim.get_current_buf.set_var "origfile", a
54
50
  end
55
51
 
56
- def dump! a
57
- Kernel.popen_outerr a do |ro,re|
58
- dump_file a, ro
59
- e = re.read.lines.map { |x| x.chomp! ; "# #{x}" }
60
- $vim.put e, "l", false, true
52
+ def dump! a, m
53
+ a = a.notempty?
54
+ a ||= cur_buf_name_exec
55
+ pipe a, m, nil
56
+ end
57
+
58
+ def pipe a, m, range
59
+ popen a do |ro,re|
60
+ begin
61
+ if range then
62
+ # It would be nicer to write the lines as they are demanded. If
63
+ # you have an idea how this could easily be done, feel free to
64
+ # propose a patch. Putting this begin-end block into a Thread
65
+ # didn't work.
66
+ (Neovim::Lines.new $vim.get_current_buf, range).each { |l| ro.puts l }
67
+ end
68
+ ro.close_write
69
+ end
70
+ dump_data ro, a, m
71
+ re.each_line { |l|
72
+ l.chomp!
73
+ $vim.put [ "# #{l}"], "l", false, true
74
+ }
61
75
  end
62
76
  $?.success? or $vim.put [ "### Exit code: #{$?.exitstatus}"], "l", false, true
63
77
  end
64
78
 
65
- private
66
-
67
- def dump_file a, f
68
- $vim.command "enew"
79
+ def dump_data f, a = nil, m = nil
80
+ (split_new m).tap { |sc| $vim.command sc }
69
81
  $vim.set_option filetype: "xxd", buftype: "nofile"
70
82
  $vim.get_current_buf.set_name "[hex: #{a}]"
71
83
  (Dump.new input: a).run f do |l|
72
- $vim.put [l], "l", false, true
84
+ $vim.put [ l], "l", false, true
73
85
  end
74
86
  end
75
87
 
88
+ private
89
+
90
+ def cur_buf_name
91
+ # $vim.buf_get_name 0 # gives the full path
92
+ $vim.evaluate "bufname('%')"
93
+ end
94
+
95
+ def cur_buf_name_exec
96
+ r = cur_buf_name
97
+ r = File.join ".", r unless r.include? "/"
98
+ r
99
+ end
100
+
101
+ def popen cmd
102
+ re, we = IO.pipe
103
+ IO.popen cmd, "r+", err: we do |ro|
104
+ we.close
105
+ yield ro, re
106
+ end
107
+ ensure
108
+ re.close
109
+ end
110
+
76
111
  public
77
112
 
78
- def pack a, range
79
- pack_check a, range do |d|
113
+ def pack a, rarg, range
114
+ pack_check a, rarg, range do |d|
80
115
  raise "File exists. Overwrite with '!'." if File.exist? d
81
116
  end
82
117
  end
83
118
 
84
- def pack! a, range
85
- pack_check a, range do || end
119
+ def pack! a, rarg, range
120
+ pack_check a, rarg, range do || end
86
121
  end
87
122
 
88
123
  private
89
124
 
90
- def pack_check a, range
125
+ def pack_check a, rarg, range
91
126
  b = $vim.get_current_buf
92
127
  a = a.notempty?
93
- a ||= b.get_var "origfile" rescue nil
94
- a or raise "No file name given."
128
+ unless a then
129
+ a = b.get_var "origfile" rescue nil
130
+ a or raise "No file name given."
131
+ rarg.zero? or raise "No range allowed when using default output name."
132
+ end
95
133
  yield a
96
134
  File.open a, "w" do |f|
97
- r = Range.new b, range
135
+ r = Neovim::Lines.new b, range
98
136
  Nxxd::Dump.reverse r, f
99
137
  end
100
138
  end
101
139
 
102
- end
140
+ public
103
141
 
104
- class Range
105
- def initialize buf, range
106
- @buf, @range = buf, range
107
- end
108
- def each_line &block
109
- @buf.each @range, &block
142
+ def feed a, range
143
+ popen a do |ro,re|
144
+ r = Neovim::Lines.new $vim.get_current_buf, range
145
+ Nxxd::Dump.reverse r, ro, consecutive: true
146
+ ro.close_write
147
+ $vim.command "#{range.last}"
148
+ $vim.put [ ""], "l", true, true
149
+ ro.each_line { |l|
150
+ l.chomp!
151
+ $vim.put [ l], "l", false, true
152
+ }
153
+ re.each_line { |l|
154
+ l.chomp!
155
+ $vim.put [ "# #{l}"], "l", false, true
156
+ }
157
+ end
158
+ $?.success? or $vim.put [ "### Exit code: #{$?.exitstatus}"], "l", false, true
110
159
  end
160
+
111
161
  end
112
162
 
113
163
  end
data/lib/nxxd/version.rb CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  module Nxxd
6
6
 
7
- VERSION = "1.0".freeze
7
+ VERSION = "1.1".freeze
8
8
  AUTHOR = "(C) 2025 Bertram Scharpf <software@bertram-scharpf.de>"
9
9
  LICENSE = "BSD-2-Clause+"
10
10
 
data/lib/nxxd.rb CHANGED
@@ -15,6 +15,7 @@ module Nxxd
15
15
  i = 0
16
16
  while i < input.bytesize do
17
17
  b = input.byteslice i, @line_size
18
+ b.force_encoding Encoding::ASCII_8BIT # Ruby, shouldn't this rather be self-evident?
18
19
  yield b
19
20
  i += @line_size
20
21
  end
@@ -50,6 +51,7 @@ module Nxxd
50
51
  end
51
52
 
52
53
  def run input
54
+ block_given? or return [].tap { |r| run input do |l| r.push l end }
53
55
  addr = 0
54
56
  prev, repeat = nil, false
55
57
  yield "# #@input" if @input
@@ -83,7 +85,7 @@ module Nxxd
83
85
 
84
86
  class <<self
85
87
 
86
- def reverse input, output = nil
88
+ def reverse input, output = nil, consecutive: nil
87
89
  output ||= ""
88
90
  o = String === output ? (WriteChunksString.new output) : output
89
91
  o.set_encoding Encoding::ASCII_8BIT
@@ -91,27 +93,30 @@ module Nxxd
91
93
  input.each_line { |l|
92
94
  l.chomp!
93
95
  case l
94
- when /^\s*(?:#|$)/ then nil
95
- when /^\*/ then repeat = true
96
- when /^(?:(\h+):)?\s*((?:\h\h ?)*)/ then
97
- addr, nibs = $~.captures
98
- if addr then
99
- addr = $1.to_i 0x10
100
- if repeat then
101
- loop do
102
- s = addr - o.tell
103
- break if s <= 0
104
- o.write s >= r.length ? r : r[ 0, s]
105
- end
106
- repeat = false
107
- else
96
+ when /^\s*(?:#|$)/ then
97
+ nil
98
+ when /^\*/ then
99
+ consecutive and
100
+ raise "Addressless undump doesn't allow repeat specifications."
101
+ repeat = true
102
+ when /^(?:(\h+):)?\s*((?:\h\h ?)*)/ then
103
+ addr, nibs = $~.captures
104
+ if !consecutive && addr then
105
+ addr = $1.to_i 0x10
106
+ if repeat then
107
+ loop do
108
+ s = addr - o.tell
109
+ break if s <= 0
110
+ o.write s >= r.length ? r : r[ 0, s]
108
111
  end
109
- o.seek addr
112
+ repeat = false
110
113
  end
111
- r = (nibs.scan /\h\h/).map { |x| x.to_i 0x10 }.pack "C*"
112
- o.write r
113
- else
114
- raise "Uninterpretable hex dump: #{l.chomp}"
114
+ o.seek addr
115
+ end
116
+ r = (nibs.scan /\h\h/).map { |x| x.to_i 0x10 }.pack "C*"
117
+ o.write r
118
+ else
119
+ raise "Uninterpretable hex dump: #{l.chomp}"
115
120
  end
116
121
  }
117
122
  output
@@ -140,6 +145,7 @@ module Nxxd
140
145
  end
141
146
 
142
147
  def run input, &block
148
+ block_given? or return [].tap { |r| run input do |l| r.push l end }
143
149
  if @varname then
144
150
  yield "unsigned char #@varname[] = {"
145
151
  len = run_plain input, &block
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nxxd
3
3
  version: !ruby/object:Gem::Version
4
- version: '1.0'
4
+ version: '1.1'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bertram Scharpf
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2025-01-30 00:00:00.000000000 Z
10
+ date: 2025-02-05 00:00:00.000000000 Z
11
11
  dependencies: []
12
12
  description: 'Yet another Xxd reimplementation.
13
13
 
@@ -45,7 +45,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
45
45
  version: '0'
46
46
  requirements:
47
47
  - Just Ruby
48
- rubygems_version: 3.6.2
48
+ rubygems_version: 3.6.3
49
49
  specification_version: 4
50
50
  summary: Hex Dump Tool
51
51
  test_files: []