[ANN] Hex formatter and ~h sigil for Elixir

1,400 views
Skip to first unread message

me.m...@gmail.com

unread,
Aug 12, 2014, 3:05:11 PM8/12/14
to elixir-l...@googlegroups.com
https://github.com/miwee/hexfmt

I'm particularly interested in getting feedback on the ~h sigil part:

takes a String containing hex characters [0..9, A..F], and converts it into an Elixir binary of 8-bit hex numbers

iex> ~h{12345678}
<<18, 52, 86, 120>>
 

takes a String in form of comma separated values, and converts it into an String containing hex characters [0..9, A..F]

iex> ~h{18, 52, 86, 120}x
"12345678"

is this useful enough to be included as default?


Recently inspect got :base option for hex etc. display. Can something similar like below can be achieved with that

Returns a hex string visual representation of a given list or binary. No need to insert leading '0', just to see the contents of a list.

iex> HexFmt.hexify(<<18, 52, 86, 120>>)
"<<0x12, 0x34, 0x56, 0x78>>"

iex> HexFmt.hexify('1!')
"[0x31, 0x21]"

This is useful in logging binary data (not strings, but actual binary data)

thanks,
miwee

Paulo Almeida

unread,
Aug 21, 2014, 5:24:27 AM8/21/14
to elixir-l...@googlegroups.com
You can pass binaries: :as_binaries to inspect to print in bit syntax without inserting a <<0>>

iex(1)> inspect("Hello", binaries: :as_binaries)
"<<72, 101, 108, 108, 111>>"

It's not in hex, but maybe this could be combined with the new :base option. Something like:

iex(15)> inspect("Hello", binaries: :as_binaries, base: :hex)
<<0x48, 0x65, 0x6C, 0x6C, 0x6F>>

miwee

unread,
Aug 21, 2014, 8:49:02 AM8/21/14
to elixir-l...@googlegroups.com
iex(15)> inspect("Hello", binaries: :as_binaries, base: :hex)
<<0x48, 0x65, 0x6C, 0x6C, 0x6F>>

The above will not work. It will only give decimal values.

base: :hex works for integer values only

iex(5)> inspect(128, base: :hex)
"0x80"

probably, a new option `binaries: :as_hex_binaries`, can be added which gives equivalent result of Hexfmt.hexify. As I said, I find it extremely useful in debugging binary protocols like modbus rtu.

thanks
miwee

Paulo Almeida

unread,
Aug 21, 2014, 1:03:14 PM8/21/14
to elixir-l...@googlegroups.com
I meant it as a proposed behavior. Extending the base: option to binaries/string and char_lists instead of just integers. 

miwee

unread,
Aug 22, 2014, 3:52:11 AM8/22/14
to elixir-l...@googlegroups.com
+1 for this proposed behavior

thanks
miwee

José Valim

unread,
Aug 22, 2014, 8:29:12 AM8/22/14
to elixir-l...@googlegroups.com
If base is hex, we should definitely use this information and try to print binaries using two bytes for each digit.

No need for a new option. Can someone please submit a pull request?
--
You received this message because you are subscribed to the Google Groups "elixir-lang-talk" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-ta...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


--


José Valim
Skype: jv.ptec
Founder and Lead Developer

miwee

unread,
Aug 22, 2014, 4:06:19 PM8/22/14
to elixir-l...@googlegroups.com, jose....@plataformatec.com.br
I'm new to this, but will try doing that. it may take some time.

Meanwhile I'm getting issue in using HexSigil part as a comparison inside case statement. Could someone please help, what is happening here, and how to correct it.

iex(1)> import HexSigil
nil
iex(2)> a1 = ~h{0x0A, 0x0B}x
"0A0B"
iex(3)> b1 = "some data"
"some data"
iex(4)> case b1 do
...(4)> a1 -> IO.puts "this works"
...(4)> end
this works
:ok
iex(5)> case b1 do               
...(5)> ~h{0x0A, 0x0B}x -> IO.puts "no works"
...(5)> end
** (CompileError) iex:6: cannot invoke remote function HexSigil.sigil_h/2 inside match
    (elixir) src/elixir_translator.erl:234: :elixir_translator.translate/2
    (stdlib) lists.erl:1352: :lists.mapfoldl/3
    (elixir) src/elixir_clauses.erl:158: anonymous fn/3 in :elixir_clauses.wrap_export_fun/2
    (elixir) src/elixir_clauses.erl:26: :elixir_clauses.match/3
    (elixir) src/elixir_clauses.erl:35: :elixir_clauses.clause/7
    (elixir) src/elixir_clauses.erl:82: anonymous fn/5 in :elixir_clauses.do_clauses/4
    (stdlib) lists.erl:1352: :lists.mapfoldl/3
iex(5)>
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-talk+unsubscribe@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

Mikhail

unread,
Aug 23, 2014, 2:07:59 AM8/23/14
to elixir-l...@googlegroups.com
case is a pattern match and it is allowed to use only limited count of functions like is_*. Just use cond instead.

--
Sincerely,
Mikhail S. Pobolovets
sty...@gmail.com | skype: styx.mp | http://gplus.to/styx.mp


To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-ta...@googlegroups.com.

miwee

unread,
Aug 23, 2014, 1:58:49 PM8/23/14
to elixir-l...@googlegroups.com
thanks mikhail. cond works

but default sigils are supported inside case condition:

iex(1)> b1 = "some data"
"some data"
iex(2)> case b1 do
...(2)> ~s{some data} -> "This works too!"
...(2)> end
"This works too!"

So, probably the case pattern match limitation is with user written sigils.

Eric Meadows-Jönsson

unread,
Aug 24, 2014, 10:40:29 AM8/24/14
to elixir-l...@googlegroups.com
Your sigil needs to be a macro to work in matches, it is currently defined as a function.
--
Eric Meadows-Jönsson
Reply all
Reply to author
Forward
0 new messages