Showing posts with label Applescript. Show all posts
Showing posts with label Applescript. Show all posts

Sunday, June 13, 2010

Prolog Homoiconicity

Although when talking about homoiconicity the first language that springs into mind is Lisp (or a Lisp dialect), Prolog is a completely homoiconic language. In Prolog everything is a term. Variables, atoms, numbers are terms. And everything else is a compound term: e.g., foo(a, b) is a term. Lists are the main data structure of Prolog, and a list is a term as well. In fact a Prolog list is i) the empty list []; ii) a term '.'(a, b), where a is a term and b is a list or a variable. We say that a compound term foo(x, y) has functor foo and arity 2. Clauses (the prolog equivalent of "functions") are represented as terms whose main functor is :-, their head is a prolog term and their body is a prolog term as well. Moreover, the read predicate reads from file (or standard input) some prolog predicates. E.g., this simple Prolog program reads a Prolog program into memory (and the program is represented as a list of prolog terms):
read_all([Predicate|T]) :-
	read(Predicate),
	Predicate \== end_of_file, !,
	read_all(T).
read_all([]).

read_file(File, L) :-
	see(File), read_all(L), seen.
If we call read_file to read "read_file.pl" (spaces added by me):
?- read_file('read_all.pl', L).
L = [(read_all([_A|_B]):-read(_A),_A\==end_of_file,!,read_all(_B)),
     read_all([]),
     (read_file(_C,_D):-see(_C),read_all(_D),seen)] ? y
The display predicate some prolog interpreters provide gives us more insight on internal representation of terms. We call it on just one rule in order not to clutter the output with list representations:
?- read_file('read_all.pl', [H|_]), display(H).
:-(read_all(.(_932,_952)),,(read(_932),,(\==(_932,end_of_file),,(!,read_all(_952)))))
And here on the full program (notice... lists are "consed" with the '.' functor):
?- read_file('read_all.pl', L), display(L).
.(:-(read_all(.(_900,_920)),,(read(_900),,(\==(_900,end_of_file),,(!,read_all(_920))))),.(read_all([]),.(:-(read_file(_1410,_1430),,(see(_1410),,(read_all(_1430),seen))),[])))
Indeed, infix operators have been placed in prefix form like every other predicate (indeed, they are not special, just a parsing trick). Another "useful" predicate (not standard) is portray_clause/1, in order to do some "pretty-printing":
?- read_file('read_all.pl', [H|_]), portray_clause(H).
read_all([A|B]) :-
        read(A),
        A\==end_of_file, !,
        read_all(B).

The assert family of predicates can “store” into the Prolog database facts (this is very common, in fact, memoization is often implemented this way) and rules (this is done less frequently – and there may be a slight efficiency penality [CHECK]). Thus we can manipulate terms (indeed that is what Prolog is about) and load them as programs. Notice that I showed the read predicate only to show that “standard” Prolog programs are represented that way, but it is not necessary at all to use programs saved in files.

4 ?- assert((foo(X) :- bar(X), \+ baz(X))).
true.

5 ?- assert(bar(1)), assert(bar(2)), assert(baz(2)).
true.

6 ?- foo(X).
X = 1 .

Wednesday, May 17, 2006

Open in iTerm from Finder

Since I've been asked to do it, I wrote the "Open in iTerm" app, that does the very same thing than "Open in Terminal" (except that it uses iTerm instead of Terminal.app)

Actually there could be bugs, but at least on my system I suppose it's not my fault, but rather it is iTerm that crashes a lot (maybe the AppleScript part has not been tested extensively on intel macs).

If you experience problems, let me know.

The script part that accesses iTerm is

tell application "iTerm"

        activate

        set myTerm to (make new terminal)

        tell myTerm

                set mySession to (make new session at the end of sessions)

                tell mySession

                        exec command "/bin/bash"

                        write text "cd \""& myPath &"\""

                end tell

        end tell

end tell

I bundled both apps in the very same package, and you can download it here.

I upgraded this script too with Marco's help.

on run

        tell application "Finder" to try

                set myPath to quoted form of ¬

                        POSIX path of ((target of window 1) as string)

        on error

                set myPath to "~"

        end try

        

        tell application "iTerm"

                activate

                set myTerm to (make new terminal)

                tell myTerm

                        set mySession to (make new session at the end of sessions)

                        tell mySession

                                exec command "/bin/bash"

                                write text "cd "& myPath

                        end tell

                end tell

        end tell

end run

Definitive?

After some discussion on icm and the help of tv and Marco (thank you guys) we came to this

on run

tell app "Finder"

try

set myPath to quoted form of ¬

POSIX path of ((target of window 1) as string)

on error

set myPath to "~"

end

set esiste to ((count (get ¬

name of every application process ¬

whose creator type is "ITRM")) is not 0)

end

tell app "iTerm"

activate

if esiste then

set myTerm to (make new terminal)

else

set myTerm to the first terminal

end if

tell myTerm

make new session at the end of sessions

tell the last session

exec command "/bin/bash"

write text "cd "& myPath

end

end

end

end

Open in Terminal from Finder

This is a trivial AppleScript
tell application "Finder"
        set targ to target of Finder window 1
        set myPath to POSIX path of (targ as string)
end tell
tell application "Terminal" to do script "cd \""& myPath &"\""
Here you can see a couple of screenshots.
If you want to download the application (with pretty icon) that uses it, you can download it from here.
Edit: Thanks to Marco Balestra for showing me his own script (that does the same thing, but is much cleaner). Now I included his script instead of mine.
on run
        tell application "Finder" to try
                set myPath to quoted form of ¬
                        POSIX path of ((target of window 1) as string)
        on error
                set myPath to "~"
        end try
       
        tell application "Terminal"
                do script "cd "& myPath
                activate
        end tell
end run

Monday, May 1, 2006

Open with BBEdit

This is a tiny Automator Workflow that opens the current Safari document with BBEdit.
Previously I wrote an AppleScript that did the very same job, however the new document was marked as "new", thus when one tried to close it, BBEdit would complain and ask if we wanted to save
tell application "Safari"
        set cur to document 1
        set mySource to source of cur
        set myName to name of cur
end tell
tell application "BBEdit"
        set x to make new text document with properties ¬
                {contents:mySource, name:myName}
        activate
end tell
However if we use the automator action "New BBEdit Document", it offers the possibility to "Set unmodified" (that is to say the new document won't ask if it has to be saved before closing).
I created a two step Automator workflow. The first step is a slightly modified version of the first part of the script. It is a "Run AppleScript action" containing
on run {input, parameters}
        tell application "Safari"
                set cur to document 1
                set mySource to source of cur
                set myName to name of cur
        end tell
        return mySource
end run
The second step is the "New BBEdit Document" action.
You can download the workflow here. I sugest to put it in the script menu.