I should add: jcalc and jconsole (or ijcalc and jconsole (or whatever
you want to name them)) need to be executable and need to be in your
$PATH.

If they aren't executable, you'll get a permission denied error when
you try to use them.

If they aren't in your path, you'll get a not found error when you try
to use them.

To make executable, use chmod a+x filename (sudo if you have installed
in a privileged location), where filename is jcalc or ijconsole or
whatever it is that you want to be a program instead of just a file.

To understand your PATH you can use something like this from the unix
command prompt:

(IFS=:; for d in $PATH; do echo $d; done)

(Note that if you leave off the parenthesis, you'll have altered the
interfield separator for your command shell and you might have to shut
it down and get a fresh one if you want things to work normally
afterwards.)

There's other issues here also, but if you are just getting started
with the command shell, you should seriously consider playing around
with it for a short bit of time every day for a month or two, just to
get comfortable with it.

It can also help to read some of the earlier writeups on the design of
unix (files, processes, devices, paging) so you'll have a bit of
intuition about how things work. Or, if you can't find anything fun to
do with it, maybe something like
https://books.google.com/books?id=ijAEAAAAMBAJ&pg=PT79

Thanks,

-- 
Raul

On Fri, Apr 10, 2015 at 12:58 PM, Raul Miller <rauldmil...@gmail.com> wrote:
> I often itch to use J from the command line.
>
> Here's my current best implementation for jcalc.
>
> jcalc is an analog to jconsole. But instead of providing a console
> environment, it provides the ability to execute a j sentence from the
> host operating system command line.
>
> Since it must exist in the operating system environment, this means
> you have to do a little operating system specific work setting it up.
>
> One thing it needs is jconsole to be available in your operating
> system's PATH. On a mac, this means that I have a jconsole in my
> personal bin directory which looks something like this:
>
> #!/bin/sh
> exec /Applications/j64-803/bin/jconsole "$@"
>
> The same basic approach works for arbitrary unix machines, including
> cygwin except the specific directory which holds jconsole varies (or
> you could use a symbolic link instead). If you really like java, or
> you are building systems for other people, you should use ijconsole
> instead (and, by analogy, call this ijcalc).
>
> With that out of the way, here's the implementation of ijcalc:
>
> #!/bin/sh
> #0 :0
> exec ijconsole "$0" "$@"
> )
> onfail=:3 :0
>   1!:2&2 ARGV
>   1!:2&2]13!:12''
>   2!:55>:13!:11''
> )
> 9!:27 'onfail 1'
> 9!:29]1
> echo".;:inv 2}.ARGV
> exit 0
>
> This is based on http://rosettacode.org/wiki/Multiline_shebang#J
>
> What's happening here is that this is both a valid unix shell script
> and a valid j "ijs" style script with a relative minimum of external
> assumptions. (Though in a hasty and minimal "j hosted on a foreign
> system" context you might want to use the -js option to jconsole,
> because you didn't install a standard profile in the proper place).
>
> If you are running on windows, you can ignore the shell script part
> (because this is also valid J), but you might want to save this as
> jcalc.ijs in a directory which is a part of your path, and you might
> want to make *.ijs scripts handled by your jconsole (wherever you have
> installed it).
>
> Meanwhile, here's a walkthrough first from a shell script perspective:
>
> Unix inspects the first few bytes of a file for hints about how it
> should be executed. If the first two bytes are ascii 35 followed by
> ascii 33 (that can be 0x23, 0x21 or \043, \041 or "#!" in a C
> program), then it's expected that the following characters specify the
> exact name of a program to be executed, with this file as an argument,
> to handle this command line. There are some constraints here (such as
> how long the line can be, or how spaces get treated) but those vary
> depending on which unix implementation you are working with.
>
> Nowadays most uses of Unix are either Linux (which is not unix) or
> BSD. Android is linux. iOS is BSD.
>
> Once /bin/sh gets control of the execution, # marks comments (much
> like NB. in J - including the need for a proceeding space if it is
> meant to be recognized after a word).
>
> So the first line executed by /bin/sh is this:
>
> exec ijconsole "$0" "$@"
>
> The exec keyword says "replace the currently running program with the
> specified program" which is ijconsole. This prevents creation of a
> fresh context (a minor efficiency gain) and also prevents execution of
> further lines (which is important here because /bin/sh has no idea
> what to do with them).
>
> The "$@" thing says pass on the command line arguments as distinct
> arguments. I could have had them merged into a single argument by
> using "$*" instead but usually that's the wrong thing to do, so I am
> avoiding it here out of habit. You'll see that this costs me a couple
> of characters later on. But since this approach also gives better
> insight into the command line environment, I am sticking with it.
>
> The "$0" thing is the name of this file. It's not part of "$@" since
> "$@" is meant to represent arguments. But obviously J needs to know
> about this file so it can use it to control what happens next.
>
> ----
>
> So now we have done everything we need at the OS level, and it's time
> for J to do its thing, so let's walk through how that works:
>
> #!/bin/sh
>
> Here, bin and sh are names without definitions. J treats them as
> verbs, and the result of executing this line is the same as:
>
>    # (!/ bin/ sh)
>
> So that's a verb definition which gets ignored.
>
> #0 :0
> exec ijconsole "$0" "$@"
> )
>
> This is going to count how many characters are in the following script
> block (up through the bare closing parenthesis). So that's going to
> give us a result much like would be produced by this expression:
>
>    24
>
> We needed that stuff to bootstrap ourselves into the J environment,
> but now that we are here we need to think about what's next.
> Ultimately, we are going to be executing a line of code from somebody
> and that code might result in an error. But we do not want jconsole's
> "stay in the command line environment" behavior. If we wanted that, we
> would be using jconsole instead of jcalc. (Er... we would have been
> using ijconsole instead of ijcalc... anyways...)
>
> So, if there's an error, we need to let the user know some details
> about what went wrong. So that is what this is about:
>
> onfail=:3 :0
>   1!:2&2 ARGV
>   1!:2&2]13!:12''
>   2!:55>:13!:11''
> )
> 9!:27 'onfail 1'
> 9!:29]1
>
> First we define our 'onfail' handler. Then we queue it up to be
> executed before any command line execution using 9!:27. And, finally,
> we enable its use with 9!:29.
>
> So if an error happens, the first thing we do is display ARGV, the
> second thing we do is display an error diagnostic. And the final thing
> we do is exit with a non-zero exit code (adding 1 to J's error message
> index, because 0 is a valid index).
>
> In shell contexts, a non-zero exit code means something went wrong,
> and a zero exit code means things worked. No news is good news (though
> it's true that plenty of people like some bad news, let's save that
> for the error cases).
>
> Finally, we get to the main event, which is basically about telling J
> to execute the sentence we are giving it on the command line:
>
> echo".;:inv 2}.ARGV
>
> Note that while I was paranoid about how I dealt with the error cases,
> I'm assuming everything is working normally now that I've gotten my
> error case handling defined. At this point, I *want* things to break
> if something is wrong. If that happens, I should get a nice error
> message, and that will let me decide what to do next.
>
> That's what error messages are for, after all - to draw attention to
> something that needs attention.
>
> So what this does is drop the first two elements from ARGV (which is a
> boxed list of strings - basically the same thing that /bin/sh was
> working with, and the same thing the operating system was working
> with) and then we join them together in a single string, execute that,
> and display the result.
>
> Note that I'm using ;:inv here instead of ; and there's a reason for
> that. Do you see why?
>
> Finally, if all goes well, we exit with a zero exit code, indicating success.
>
> So...
>
> If you install this properly, you should be able to do something like this:
>
> ijcalc 1+1
>
> and get a result like this:
>
> 2
>
> I can tell you are impressed.
>
> But that's not all!
>
> Consider this, for example:
>
> jcalc 2 3 + 4 5 6
> ┌──────────────────────────────────┬────────────────────────────┬─┬─┬─┬─┬─┬─┐
> │/Applications/j64-803/bin/jconsole│/Users/rauldmiller/bin/jcalc│2│3│+│4│5│6│
> └──────────────────────────────────┴────────────────────────────┴─┴─┴─┴─┴─┴─┘
> |length error: script
> |   2 3    +4 5 6
>
> My, but that's an ugly error...
>
> No, I mean beautiful! Yes!
>
> My my, but that's a beautiful error...
>
> ...
>
> Some should tell whoever wrote this that he needs to be using names
> like ijcalc and ijconsole instead of jcalc and jconsole or the java
> guys are going to spring beans all over his desktop. And they will not
> be happy.
>
> One character makes all the difference. And i is a very strange character.
>
> Thanks,
>
> --
> Raul
----------------------------------------------------------------------
For information about J forums see http://www.jsoftware.com/forums.htm

Reply via email to