(archive 'newLISPer)

June 6, 2006

Is Your Text Currently Current? (Inside Joke)

Filed under: newLISP — newlisper @ 17:44
Tags:

Here is a handy gem of a function: current-text. This may be one of the first functions I wrote in newLISP. (Insert pause here while the author reflects nostalgically on the topic of that last sentence.) Oh yeah, the current-text function builds upon the current-line function (hence the name). It returns the text contained in the standard input pipe as one big, juicy string. The impetus for this was my desire to use newLISP from within TextMate. Everything in this editor is handled using standard input and output, and most of the time, I work with the text as a whole, rather than one line at a time. I needed a way of grabbing all of the text from standard input at once. So, without further ado, here is current-text:

(define (current-text)
    (set 's "")
    (while (read-line)
       (set 's (string s (current-line) "\n")))
    s)

(global 'current-text)

;; example:
;; > (exec {echo 'how do you do' | newlisp -e "(current-text)"})
;; ("\"how do you do\\n\"")

Instead of (string s (current-line) “\n”), we could have used (format “%s%s\n” “abc” “defg”); otherwise, this is a very basic function. There may already even be a way to do this in newLISP, but that didn’t matter to me then — then, the new experience of coding in newLISP carried me away into . . . into . . . (author once again trails off while fondly looking back). Where were we? Globals! Let’s talk about globals.

global makes the quoted symbols passed into it visible within all contexts. This allows you to treat one of your user-defined functions just like a bona fide built-in function. Without using global, the illusion would be shattered the first time you tried to call your user-defined–built-in (made-up name) function within a context other than the one in which it was defined.

> (define (like-built-in?) "No!")
(lambda () "No!")
> (like-built-in?)
"No!"
> ;; seems like a built-in here.
> (context 'c)
c
c> (like-built-in?)

invalid function : (like-built-in?)
> ;; do you know what is wrong? i do, but i won't tell.
> ;; wait, that's why i'm doing this! we forgot the context!
> (MAIN:like-built-in?)
"No!"
> ;; illusion shattered. but don't forget about globals!
> ;; note: stop and restart your newLISP shell to continue
> ;; (reason follows)
> ^D
bash> newlisp
newLISP v.8.8.9 on OSX UTF-8, execute 'newlisp -h' for more info.

> (define (like-built-in?) "Yes!")
(lambda () "Yes!")
> (global 'like-built-in?)
like-built-in?
> (context 'c)
c
c> (like-built-in?)
"Yes!"
c> (MAIN:like-built-in?)
"Yes!"
c> ;; we can still do it this way.
c> ;; helpful when context has symbol with same name as global
c> _

As promised, here is the reason we had to restart. A symbol with the same name as the function we defined within MAIN was created in the c context. This happened when we mistakenly tried to call our earlier function as though it were a global function. The same effect can be produced in the following way:

> (context 'c)
c
c> (symbols)
()
c> ;; no symbols in `c` yet
c> like-built-in?
nil
c> (symbols)
(like-built-in?)
c> ;; now `c` has this symbol, but it's nil
c> (context MAIN)
MAIN
> _

Once a symbol with the same name as a global is mentioned within a context, you must disambiguate which one you mean by prefixing it with the name of the current context or MAIN. This allows you to refer to either the local symbol (typically accessible without the context name) or the globally defined symbol using MAIN. All globals must be defined within the MAIN context. Don’t believe me? See for yourself:

> (context 'i-told-you)
i-told-you
i-told-you> (define (f a b) (+ a b b a))
(lambda (a b) (+ a b b a))
i-told-you> (context MAIN)
MAIN
> (global 'i-told-you:f)

symbol not in MAIN context in function global : i-told-you:f
> _

global is complaining that f isn’t defined within the MAIN context. global knows (he alllwaaays knows ;-) He also only wants to be used from within the MAIN context. My MAIN man seems kinda grumpy, but he has his reasons. Not the least of which is that everyone is always knocking globals all of the time ;-)

I vaguely recall this supposedly being about current-text, but it seems to have become a lesson on global! Maybe I should look in the manual at the entry for global to see if I’ve missed anything. Oh look, we can also combine constant with global to protect our user-defined–built-ins from mean code that just wants to change us. We user-defined–built-ins like ourselves just the way we are, thank you ;-)

Combining what we learned from the manual with our earlier code, we arrive at this definition:

(define (current-text)
    (set 's "")
    (while (read-line)
       (set 's (string s (current-line) "\n")))
    s)

(constant (global 'current-text))

I just realized we haven’t played with our function yet!

#!/newlisp
(print (chop (join (parse (current-text) { }) {-})))
(exit)

This piece of coding delight is tucked into a command, is summoned by keyboard shortcut, and takes the selected text within the editor (now on standard input). The command replaces the selected text with a hyphenated version of itself (by printing to standard output): “jack of all trades” becomes “jack-of-all-trades”, for example. I won’t explain this code, except to say that I have an alias defined from the root directory to the newlisp executable, so my shebang looks nice and clean (yeah man, I tricked out my shebang by chopping the dirs and lowering the entry, man ;-)

m i c h a e l

Advertisements

2 Comments »

  1. >here is a variation which could be faster on big strings:(define (current-text) (let (s “”) (while (read-line) (write-line (current-line) s)) s))when write-line gets a string instead of a file handle it will apppend to a string together with a line-feed. When strings are big doing this in place growing of a string is much faster. The let also makes you variable s local.And here is another trick: you can test these kind of functions interactively by pressing Ctrl-D as an end-of-file character. This will simulate the situation when your functions get input piped in from the editor and read-line returns nil at the end of the text. Ctrl-D will do the same thing.So you can start (current-text) in the console, enter a couple of lines and hit Ctrl-D to test your function.

    Comment by don Lucio — June 6, 2006 @ 20:10 | Reply

  2. >Thanks, Lutz, for this and the last function (uses). I had a feeling there was a better way of doing this, but just being able to knock that function out when I was so new to the language is a testament to how well thought out newLISP is. Just makes sense. Cheers!m i c h a e lP.S. Thanks also, for the great tricks to use with TextMate. It’s really helping with a huge editing project I’m working on at the moment ;-)

    Comment by m i c h a e l — June 7, 2006 @ 02:37 | Reply


RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Blog at WordPress.com.

%d bloggers like this: