nxxd 1.0 → 1.1

Sign up to get free protection for your applications and to get access to all the features.
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: []