How do I use erl_tidy and erl_lint? - erlang

I know the docs explain these tools, but I don't understand the explanation. Can someone provide an example or two?

Of erl_tidy, the simplest way - and the most direct, if you have one running in your source directory all the time anyway, is to use it directly from Eshell, as in
$ erl
1> m(erl_tidy).
% output snipped
2> erl_tidy:dir(). % recursively tidy the present directory and its children
% output snipped
3> erl_tidy:dir("", [{recursive, false}]). % just the present directory
reading module `./bad.erl'.
made backup of file `./bad.erl'.
writing to file `./bad.erl'.
4>
In this case, bad.erl went from
-module(bad).
-compile(export_all).
bad(0)->1;bad(1)->2;bad(N)->3.bad()->0.
to the tidied
-module(bad).
-compile(export_all).
bad ( 0 ) -> 1 ; bad ( 1 ) -> 2 ; bad ( N ) -> 3 . bad ( ) -> 0 .
... well, it's not a magician :-)
erl_tidy can also be invoked through arguments to erl, as in
$ # unix prompt
$ erl -s erl_tidy dir
tidying directory `./wesnoth'.
tidying directory `./wesnoth/Vix'.
tidying directory `./wesnoth/Vix/utils'.
...
erl_lint however is completely different. To understand how to use it, first understand what's going on in this string evaluation example. erl_lint is designed to act on an intermediate representation of Erlang source, not on strings of it.

Related

How to print the starting position of pattern in grep

In python's regex (re) library I can do re.search("<pattern>", string).start() to get the start of the pattern (if pattern exists).
How can I do the same in the unix command line tool grep?
E.g. If pattern= "th.n" and the string is "somethingwrong", I expect to see the number 5 (considering 1-based but 4 in a 0-based would be ok)
Thank you!
For example:
echo "abcdefghij" | grep -aob "e"
outputs :
4:e
Here:
-b to gets the byte offset
-a tells grep to use the input as text
-o outputs the findings
With your example:
echo ""somethingwrong"" | grep -aob "th.n"
4:thin
This works great on multiple matches:
echo "abcdefghiqsdqdqdfjjklqsdljkhqsdlf" | grep -aob "f"
5:f
16:f
32:f
Maybe a Perl one-liner would be a happy medium between having to write a Python program and the simplicity of a standard Unix tool.
Given this file:
$ cat foo.txt
This thing
that thing
Not here
another thing way over here that has another thing and a third thing
thank you.
You could run this Perl one-liner:
$ perl -lne'while(/th.n/g){print $.," ",$-[0]," ",$_;}' foo.txt
1 5 This thing
2 5 that thing
4 8 another thing way over here that has another thing and a third thing
4 45 another thing way over here that has another thing and a third thing
4 63 another thing way over here that has another thing and a third thing
5 0 thank you.
Also, the greplike search tool ack (that I wrote)has a --column option to display the column:
$ ack th.n --column foo.txt /dev/null
foo.txt
1:6:This thing
2:6:that thing
4:9:another thing way over here that has another thing and a third thing
5:1:thank you.
Or with the --nogroup option so the filename appears on each line.
$ ack th.n --column --nogroup foo.txt /dev/null
foo.txt:1:6:This thing
foo.txt:2:6:that thing
foo.txt:4:9:another thing way over here that has another thing and a third thing
foo.txt:5:1:thank you.
I had to add the search of /dev/null because ack's output would be different if there was only one file being searched.
ripgrep has a --column option, too.
$ rg --column --line-number th.n foo.txt
1:6:This thing
2:6:that thing
4:9:another thing way over here that has another thing and a third thing
5:1:thank you.

Value from binding in LFE interpreter using Erlang

I'd like to use Lisp Flavored Erlang as a scripting extension language for an Erlang application. If you want, in a similar way GNU Emacs is configured and extended via Emacs Lisp.
I know that the argument is wide and structured; but in the specific case of this question I'd like being able to read a binding name (or variable, if you prefer) defined in LFE from Erlang code.
I'm not an expert of LFE internal architecture (which is an excellent example of software engineering and Erlang programming), but I was not able to find an answer neither in the sources nor in the documentation.
Looking at sources I can see that LFE contains both a compiler that target Erlang VM and an interpreter.
The latter is the one I'm trying to use.
If I start Erlang shell/REPL in LFE installation path (on my system $HOME/opt/lfe):
$ cd /path/to/LFE-install-dir
$ erl -pa ./ebin
I'm able to calculate a value:
1> {ok, Expr} = lfe_io:read_string("(+ 1 10)").
{ok,['+',1,10]}
2> Result = lfe_eval:expr(Expr).
11
This is a first step, but not exactly what I want. I'd like rather to bind a variable and read its value; that's my issue:
3> {ok, Expr2} = lfe_io:read_string("(set a 10)").
{ok,[set,a,10]}
4> lfe_eval:expr(Expr2).
** exception error: {unbound_func,{set,2}}
in function lfe_eval:eval_expr/2
Why set is recognized as an unbound function? In LFE REPL this expression is valid:
Erlang/OTP 17 [erts-6.4] [source] [64-bit] [smp:4:4] ...
LFE Shell V6.4 (abort with ^G)
> (set a 10)
10
> a
10
I'm obviously using the API in the wrong way. How can I read the content of a and/or properly initialize the LFE interpreter?
(If this is explained somewhere, please provide the reference).
I won't attempt to answer completely your broader question about the "best practices" of adding scripting. It seems to me that choosing between "hook-based" solution (in which you define hook implementations by name convention and they are automatically recognized) and "explicit api" solution (in which you use functions predefinied in the scripting enviroment to register your hooks or otherwise call configuration functions) is largely a matter of taste. Explicit calls like (set-connection-timeout-handler ...) may be more readable, easier to debug (no misspelling problems, no surprises on api changes), easier to document, and a bit more flexible, but more, well, explicit.
Building from your simple variable definition example, here are a few ways you could get started going further the "interpreted" path:
1> {ok, Expr} = lfe_io:read_string("'((a 10))").
{ok,[quote,[[a,10]]]}
2> lfe_eval:expr (Expr).
[[a,10]]
3> EvalAll = fun (Conf) -> {ok, E} = lfe_io:read_string("'(" ++ Conf ++ ")"), lfe_eval:expr(E) end.
#Fun<erl_eval.6.90072148>
4> EvalAll ("(a 10) (b 11)").
[[a,10],[b,11]]
5> EvalAllL = fun (Conf) -> {ok, E} = lfe_io:read_string("(list " ++ Conf ++ ")"), lfe_eval:expr(E) end.
#Fun<erl_eval.6.90072148>
6> [{f, F}] = EvalAllL ("(tuple 'f (lambda (x) (+ 10 x)))").
[{f,#Fun<lfe_eval.12.2018457>}]
7> F (12).
22
8> G = fun (X) -> X * 2 end.
#Fun<erl_eval.6.90072148>
9> lfe_eval:expr (element (2, lfe_io:read_string ("(g 15)")), lfe_eval:add_lexical_func(g, 1, G, lfe_env:new ())).
30
A simple way is use to the 'lfe' command to run LFE scripts. The 'lfe' behaves in similar fashion to 'bash' in that you can use it to run scripts. The 'lfec' script defined in bin/lfec is a good example of this. It is an LFE shell script which parses it arguments and run the LFE compiler.

How can I tail -F a log file(truncate aware) in lua?

I'd like to make the output of tailf or tail -F, or something similar available to me in Lua without blocking or locking. If the file gets truncated or log rotated, the program will detect it and will return to the start. This seems to be a level 1 question but looks strange to me. I just can't figure it out. Does anyone could share some code?
Two ideas come to mind, you can just pipe the output of tail -F directly into your script execution. From there you can just read it in from stdin. Perhaps something like this:
local c = 0
for line in io.stdin:lines() do
c = c + 1
print(c, line)
end
A problem with this is that tail uses stderr to report file truncation so the script won't see it unless you find some way to redirect stderr to stdin.
The other idea is to use io.popen and force the stderr->stdin redirection before the main loop. You can then use any standard pattern matcher to check for tail truncation.
local tailin = io.popen('tail -F '..(...)..' 2>&1', 'r')
local c = 0
for line in tailin:lines() do
c = c + 1
print(c, line)
c = line:match 'truncated' and 0 or c
end
Note that both approaches are blocking btw.

Showing full expected and value information when ?_assertEqual fails

I'm coding a unit test where a (rather lengthy) binary is generated, and I want to assert that the generated binary equals the one I expect to be generated. I'm running eunit through "rebar eunit".
Thing is, when this assertion fails, the output is abreviated with "...", and I want to see the complete output so I can spot where the difference is.
I'm now using "?debugFmt()" as a temporary solution, but I'd like to know if there's an alternative to it (a config option or argument somewhere that can be applied to "?_assertEqual()" so the output is only shown when the assertion fails).
Thanks in advance!
EDIT: Due to legoscia's answer, I'm including a test sample using a test generator, with multiple asserts:
can_do_something(SetupData) ->
% ... some code ...
[?_assertEqual(Expected1, Actual1), ?_assertEqual(Expected2, Actual2)].
The best I can think of for actually showing the value in the console is something like this:
Actual =:= Expected orelse ?assert(?debugFmt("~p is not ~p", [Actual, Expected]))
?debugFmt returns ok, which is not true, so the assertion will always fail.
Alternatively, to use it as a test generator, the entire thing can be put inside ?_assert:
?_assert(Actual =:= Expected orelse ?debugFmt("~p is not ~p", [Actual, Expected]))
The way I usually achieve this is by having Eunit output XML files (in "Surefire" format, AKA "Junit" format). The XML files have much higher limits for term print depth, and thus probably contain the information you need.
Add this to your rebar.config:
{eunit_opts,
[verbose,
%% eunit truncates output from tests - capture full output in
%% XML files in .eunit
{report,{eunit_surefire,[{dir,"."}]}}]}.
Then you can find the results for module foo in .eunit/TEST-foo.xml. I find the files quite readable in a text editor.
1). Open your eunit sources. In my system:
cd /usr/lib/erlang/lib/eunit-2.3.2/src
2). Edit eunit_lib.erl in such way:
diff
54c54
< format_exception(Exception, 20).
---
> format_exception(Exception, 99999).
3). sudo erlc -I ../include eunit_lib.erl
4). mv eunit_lib.beam ../ebin
5). Have a good day))
This PR introduces print_depth option to eunit:test/2:
eunit:test(my_test, [{print_depth, 200}]).
It should be available starting from OTP-23.
Setting print_depth to a larger number will decrease truncation of the output.

Do not merge the context of contiguous matches with grep

If I run grep -C 1 match over the following file:
a
b
match1
c
d
e
match2
f
match3
g
I get the following output:
b
match1
c
--
e
match2
f
match3
g
As you can see, since the context around the contiguous matches "match2" and "match3" overlap, they are merged. However, I would prefer to get one context description for each match, possibly duplicating lines from the input in the context reporting. In this case, what I would like is:
b
match1
c
--
e
match2
f
--
f
match3
g
What would be the best way to achieve this? I would prefer solutions which are general enough to be trivially adaptable to other grep options (different values for -A, -B, -C, or entirely different flags). Ideally, I was hoping that there was a clever way to do that just with grep....
I don't think it is possible to do that using plain grep.
the sed construct below works to some extent, now I only need to figure out how to add the "--" separator
$ sed -n -e '/match/{x;1!p;g;$!N;p;D;}' -e h log
b
match1
c
e
match2
f
f
match3
g
I don't think this is possible using plain grep.
Have you ever used Python? In my opinion it's a perfect language for such tasks (this code snippet will work for both Python 2.7 and 3.x):
with open("your_file_name") as f:
lines = [line.rstrip() for line in f.readlines()]
for num, line in enumerate(lines):
if "match" in line:
if num > 0:
print(lines[num - 1])
print(line)
if num < len(lines) - 1:
print(lines[num + 1])
if num < len(lines) - 2:
print("--")
This gives me:
b
match1
c
--
e
match2
f
--
f
match3
g
I'd suggest to patch grep instead of working around it. In GNU grep 2.9 in src/main.cpp:
933 /* We print the SEP_STR_GROUP separator only if our output is
934 discontiguous from the last output in the file. */
935 if ((out_before || out_after) && used && p != lastout && group_separator)
936 {
937 PR_SGR_START_IF(sep_color);
938 fputs (group_separator, stdout);
939 PR_SGR_END_IF(sep_color);
940 fputc('\n', stdout);
941 }
942
A simple additional flag would suffice here.
Edit: Well, d'oh, it is of course not THAT simple since grep would not reproduce the context, just add a few more separators. Due to the linearity of grep, the whole patch is probably not that easy. Nevertheless, if you have a good case for the patch, it could be worth it.
This does not appear possible with grep or GNU grep. However it is possible with standard POSIX tools and a good shell like bash as leverage to obtain the desired output.
Note: neither python nor perl should be necessary for the solution. Worst case, use awk or sed.
One solution I rapidly prototyped is something like this (it does involve overhead of re-reading the file, and this solution depends on whether this overhead is OK, and the give-away is the original question's use of -1 as fixed number of lines of context which allows simple use of head & tail) :
$ OIFS="$IFS"; lines=`grep -n match greptext.txt | /bin/cut -f1 -d:`;
for l in $lines;
do IFS=""; match=`/bin/tail -n +$(($l-1)) greptext.txt | /bin/head -3`;
echo $match; echo "---";
done; IFS="$OIFS"
This might have some corner case associated with it, and this resets IFS when perhaps not necessary, though it is a hint for trying to use the power of POSIX shell & tools rather than a high level interpreter to get the desired output.
Opinion: All good operating systems have: grep, awk, sed, tr, cut, head, tail, more, less, vi as built-ins. On the best operating systems, these are in /bin.

Resources