erl_tidy cannot determine module name for escript - erlang

I want use erl_tidy to format erlang code, including escript files.
But this comes out when I format one escript file (source) after adding -module(erl_pprint). :
1> erl_tidy:file("erl_pprint").
erl_pprint: error: cannot determine module name.
** exception exit: error
But When I remove the she-bang line #!/usr/bin/env escript, formatting goes well.
So how can I formatteing the code while keep the she-bang line?

You can't treat an escript file as a normal module and give it to erl_tidy. Perhaps you can drop the comment lines using "tail -n+2 erl_pprint > /tmp/erl_pprint.erl", run erl_tidy on the temp file, and then use "cat escript-header.txt /tmp/erl_pprint.erl > erl_pprint.new", if you create a file called escript-header.txt containing the leading shebang line (or lines).

Related

How can I compile an Erlang file with includes from the erl shell?

erlc -I <abspath-to-include-dir> <module>.erl on the command line correctly compiles <module>
But in the Erlang shell (erl), the following produces errors with "cannot find include file":
c(<module>, [{i, <abspath-to-include-dir>}]).
Why? Shouldn't the behavior of these two ways of compiling files be the same?
Try writing the path as a list of directories, as in {i, [".../here/", ".../there/"]}, even if it's just a single directory.

How to convert any GPX file to Xcode acceptable GPX file

I am trying to simulate a path in Xcode which has speed, latitude and longitude information.
There is a site which produces the same: http://www.bikehike.co.uk/mapview.php
I found one awk script which can convert this file to Xcode acceptable format: https://gist.github.com/scotbond/8a61cf1f4a43973e570b
Tried running this command in the terminal: awk -F script.awk bikehike_course >output.gpx
Where script.awk has the script, bikehike_course has the GPX file and output.gpx is the output file name
UPDATE
Tried: awk -f script.awk bikehike_course > output.gpx
Error: awk: syntax error at source line 1 source file adjust_gpx_to_apple_format.awk
context is
awk >>> ' <<<
awk: bailing out at source line 24
I think the syntax of the GPS file is broken.
The script on adjust_gpx_to_apple_format.awk on github is a call of awk with the awk script provided as parameter (in shell syntax).
Thus, the name adjust_gpx_to_apple_format.awk is somehow misleading.
Either the awk ' at the beginning and ' $1' at the end has to be removed. In this case,
awk -f adjust_gpx_to_apple_format.awk
should work (as the script looks like a correct awk script otherwise).
If left as is, the script might be called directly in the shell:
> ./adjust_gpx_to_apple_format.awk input.txt >output.txt
In the latter case, I would suggest two additions:
Insert a "hut" in the first line e.g. #!/bin/bash which makes it more obviously.
Rename the script to adjust_gpx_to_apple_format.sh.
Note:
Remember, that the file suffix does not have the strict meaning in Unix like shells as they have for example in MSDOS. Actually, the suffix could be anything (including nothing). It's more valuable for the user than the shell and should be chosen respectively.

grep warning: recursive directory loop

I'm searching recursively some location e.g. /cygdrive/c/dev/maindir/dir/
There's a loop inside that directory structure i.e. there's a link .../maindir/dir/loopedDir/loopedDir pointing to .../maindir/dir/loopedDir.
When I run:
grep --exclude="/cygdrive/c/dev/maindir/dir/loopedDir/loopedDir" 'myPattern' -R /cygdrive/c/dev/maindir/dir/
...it works fine, like expected and finds what I need.
However, I also get a warning:
grep: warning: /cygdrive/c/dev/maindir/dir/loopedDir/loopedDir: recursive directory loop
...and I'm wondering why is that. Shouldn't dir exclusion prevent this particular looping occurance? How should I modify my query in order not to get the warning?
Add grep's option -s to suppress this and other error messages.

How do I run a beam file compiled by Elixir or Erlang?

I have installed Erlang/OTP and Elixir, and compiled the HelloWorld program into a BEAM using the command:
elixirc test.ex
Which produced a file named Elixir.Hello.beam
How do I run this file?
Short answer: no way to know for sure without also knowing the contents of your source file :)
There are a few ways to run Elixir code. This answer will be an overview of various workflows that can be used with Elixir.
When you are just getting started and want to try things out, launching iex and evaluating expressions one at a time is the way to go.
iex(5)> Enum.reverse [1,2,3,4]
[4, 3, 2, 1]
You can also get help on Elixir modules and functions in iex. Most of the functions have examples in their docs.
iex(6)> h Enum.reverse
def reverse(collection)
Reverses the collection.
[...]
When you want to put some code into a file to reuse it later, the recommended (and de facto standard) way is to create a mix project and start adding modules to it. But perhaps, you would like to know what's going on under the covers before relying on mix to perform common tasks like compiling code, starting applications, and so on. Let me explain that.
The simplest way to put some expressions into a file and run it would be to use the elixir command.
x = :math.sqrt(1234)
IO.puts "Your square root is #{x}"
Put the above fragment of code into a file named simple.exs and run it with elixir simple.exs. The .exs extension is just a convention to indicate that the file is meant to be evaluated (and that is what we did).
This works up until the point you want to start building a project. Then you will need to organize your code into modules. Each module is a collection of functions. It is also the minimal compilation unit: each module is compiled into a .beam file. Usually people have one module per source file, but it is also fine to define more than one. Regardless of the number of modules in a single source file, each module will end up in its own .beam file when compiled.
defmodule M do
def hi(name) do
IO.puts "Hello, #{name}"
end
end
We have defined a module with a single function. Save it to a file named mymod.ex. We can use it in multiple ways:
launch iex and evaluate the code in the spawned shell session:
$ iex mymod.ex
iex> M.hi "Alex"
Hello, Alex
:ok
evaluate it before running some other code. For example, to evaluate a single expression on the command line, use elixir -e <expr>. You can "require" (basically, evaluate and load) one or more files before it:
$ elixir -r mymod.ex -e 'M.hi "Alex"'
Hello, Alex
compile it and let the code loading facility of the VM find it
$ elixirc mymod.ex
$ iex
iex> M.hi "Alex"
Hello, Alex
:ok
In that last example we compiled the module which produced a file named Elixir.M.beam in the current directory. When you then run iex in the same directory, the module will be loaded the first time a function from it is called. You could also use other ways to evaluate code, like elixir -e 'M.hi "..."'. As long as the .beam file can be found by the code loader, the module will be loaded and the appropriate function in it will be executed.
However, this was all about trying to play with some code examples. When you are ready to build a project in Elixir, you will need to use mix. The workflow with mix is more or less as follows:
$ mix new myproj
* creating README.md
* creating .gitignore
* creating mix.exs
[...]
$ cd myproj
# 'mix new' has generated a dummy test for you
# see test/myproj_test.exs
$ mix test
Add new modules in the lib/ directory. It is customary to prefix all module names with your project name. So if you take the M module we defined above and put it into the file lib/m.ex, it'll look like this:
defmodule Myproj.M do
def hi(name) do
IO.puts "Hello, #{name}"
end
end
Now you can start a shell with the Mix project loaded in it.
$ iex -S mix
Running the above will compile all your source file and will put them under the _build directory. Mix will also set up the code path for you so that the code loader can locate .beam files in that directory.
Evaluating expressions in the context of a mix project looks like this:
$ mix run -e 'Myproj.M.hi "..."'
Again, no need to compile anything. Most mix tasks will recompile any changed files, so you can safely assume that any modules you have defined are available when you call functions from them.
Run mix help to see all available tasks and mix help <task> to get a detailed description of a particular task.
To specifically address the question:
$ elixirc test.ex
will produce a file named Elixir.Hello.beam, if the file defines a Hello module.
If you run elixir or iex from the directory containing this file, the module will be available. So:
$ elixir -e Hello.some_function
or
$ iex
iex(1)> Hello.some_function
Assume that I write an Elixir program like this:
defmodule PascalTriangle do
defp next_row(m), do: for(x <- (-1..Map.size(m)-1), do: { (x+1), Map.get(m, x, 0) + Map.get(m, x+1, 0) } ) |> Map.new
def draw(1), do: (IO.puts(1); %{ 0 => 1})
def draw(n) do
(new_map = draw(n - 1) |> next_row ) |> Map.values |> Enum.join(" ") |> IO.puts
new_map
end
end
The module PascalTriangle can be used like this: PascalTriangle.draw(8)
When you use elixirc to compile the ex file, it will create a file called Elixir.PascalTriangle.beam.
From command line, you can execute the beam file like this:
elixir -e "PascalTriangle.draw(8)"
You can see the output similar to the photo:

Erlang escript: exception error: no match of right hand side value {error,enoent}‏

I encountered the above error while trying to build an Erlang RabbitMQ plugin using MinGW/MSYS on Windows 7 (64 bit). I'm using Erlang v5.10.3 (32 bit). I'm able to run RabbitMQ on my system.
Fujitsu#Notebook /d/RabbitMQ/build-source/rabbitmq-public-umbrella/presence-exchange-master
$ make
[elided] generate deps
escript: exception error: no match of right hand side value {error,enoent}
in function generate_deps__escript__1389__793192__493000:detect_deps/5 (d:/RabbitMQ/build-source/rabbitmq-public-umbrella/generate_deps, line 40)
in call from generate_deps__escript__1389__793192__493000:'-main/1-fun-0-'/6 (d:/RabbitMQ/build-source/rabbitmq-public-umbrella/generate_deps, line 19)
in call from lists:foldl/3 (lists.erl, line 1248)
in call from generate_deps__escript__1389__793192__493000:main/1 (d:/RabbitMQ/build-source/rabbitmq-public-umbrella/generate_deps, line 17)
in call from escript:run/2 (escript.erl, line 747)
in call from escript:start/1 (escript.erl, line 277)
in call from init:start_it/1 (init.erl, line 1054)
in call from init:start_em/1 (init.erl, line 1034)
I've posted the full error on pastebin - http://pastebin.com/S739wfhB
The complete code for generate_deps can be found here - http://pastebin.com/N4HVz8z1
Ps. I've also tried using CYGWIN but it returns another error - escript: Failed to open file: /home/Fujitsu/rabbitmq/build-source/rabbitmq-public-umbrella/generate_deps
EDIT 1
CYGWIN returns:
$ make
[elided] generate deps
escript: Failed to open file: /cygdrive/d/RabbitMQ/build-source/rabbitmq-public-umbrella/generate_deps
[elided] generate deps
escript: Failed to open file: /cygdrive/d/RabbitMQ/build-source/rabbitmq-public-umbrella/generate_deps
make: *** No rule to make target 'build/deps.mk', needed by 'ebin/presence_exchange.beam'. Stop.
However, I'm able to open the file using the head command.
Fujitsu#Notebook /cygdrive/d/RabbitMQ/build-source/rabbitmq-public-umbrella/presence-exchange-master
$ head /cygdrive/d/RabbitMQ/build-source/rabbitmq-public-umbrella/generate_deps
#!/usr/bin/env escript
%% -*- erlang -*-
-mode(compile).
%% We expect the list of Erlang source and header files to arrive on
%% stdin, with the entries colon-separated.
main([TargetFile, EbinDir]) ->
ErlsAndHrls = [ string:strip(S,left) ||
S <- string:tokens(io:get_line(""), ":\n")],
ErlFiles = [F || F <- ErlsAndHrls, lists:suffix(".erl", F)],
Most likely this is because it cant find the file you are trying to open, this is what the POSIX enoent error means. It is even more explicit when you used cygwin. The erlang badmatch error comes from line 23:
{ok, Hdl} = file:open(TargetFile, [write, delayed_write]),
where you try to open the file and match on {ok, Hld}. However file:open returns {error,enoent} when can't find the file, which causes the match to fail and generate the erlang error.
EDIT:
As I see it the problem is the file it is trying to write. Are you allowed to write in that directory? If the file already exists are you allowed to open it for writing?

Resources