February 2004 Archives
February 26, 2004

JavaScript introspection

JavaScript
Early morning in the Valley (Mt Hamilton, California)

JavaScript is a very loose language, but has some interesting properties. Some of them are not obvious or are quite weird.

The language uses prototype inheritance rather than the usual class inheritance from languages like Java, C++ or Python. To declare a class, you simply define a constructor function, which is really a normal function:

function MyClass() {}

The constructor defines a new property in the global space, named MyClass. The value associated with it is a function object that does nothing in our case.

To create an instance of MyClass you simply call the constructor:

var obj = new MyClass();

The new operator will create a new JavaScriptObject and invoke the function associated with the MyClass name, passing to it as invisible argument the newly created Object instance. Inside the "constructor" function, the code can use the special this property to refer to the instance.

The following code snippet:

function MyClass() {
this.ivar = 1;
}

creates a new property named ivar associated with the receiving Object instance.

In JavaScript all objects act as hash tables. The keys in the hash tables are the names of the "instance variables" or "properties". With the latter definition of MyClass() and the obj definition above, the following two expressions return the same object: obj.ivar and obj["ivar"].

If an instance variable is not declared and you refer to it using the this["name-of-variable"] you obtain the null value. This is nice since you can now verify if an instance variable is defined or not.

In JavaScript classes are just properties of the global scope object. The global scope is accessible through the this keyword. To obtain the MyClass object for example, you can do:

this["MyClass"]

You can also refer to the top-level obj variable with the expression:

this["obj"]

You can iterate over all the variables and classes defined in the global scope by doing:

for (i in this) print(i);

Quite nifty, huh? On the right is the JavaScript bible I use. The information above is not in it though...

Posted by ovidiu at 08:24 PM |
February 25, 2004

Tramp with XEmacs

Emacs
Clearing storm sunrise at Mt Hamilton, California

As I mentioned in a previous entry, Tramp is a really nice emacs package for editing remote files. On my PowerBook laptop it works out-of-the-box with the carbonized GNU Emacs on MacOS X Jaguar, there is no need to install anything.

One thing I discovered while trying to use tramp at work on XEmacs 21.4.12/Linux is that tramp version 2.0.22 shipped with XEmacs has compatibility issues with efs, another Emacs package. To fix the problem I had to grab the latest tramp package and install it in my local ~/emacs directory.

One confusing bit was how to access the CVS repository. Following the instructions from Tramp's manual does not work because Savannah's CVS repository is no longer accessible using anonymous CVS. To access the CVS, you have to follow the instructions on Tramp's Savannah CVS page instead.

With this new version, Tramp uses now a different syntax to access remote files:

  • /[machine].emacs or /[machine]~/.emacs - to open the ~/.emacs file on the remote machine.
  • /[machine]/full/path/name/to/file - to open a file using its full path name

Assuming you downloaded tramp in the ~/emacs/tramp directory, you need to configure and compile the tramp files:

$ autoconf
$ ./configure --with-xemacs
$ make
$ make info

After this add the following to your .emacs file:

(add-to-list 'load-path "~/emacs/tramp/list")
(add-to-list 'Info-directory-list "~/emacs/tramp/info")
(setq tramp-default-method "ssh")
(require 'tramp)
Posted by ovidiu at 10:32 AM |
February 17, 2004

Editing remote files in Emacs

Emacs
Wet rock? (Red Rock State Park, Nevada)

Today I was browsing some of the plugins for blosxom (an excellent blogging tool BTW), and I encountered some Emacs code for preserving the last time modified timestamp on a file. This is especially useful for blosxom which uses this timestamp as the date to show when the post was made. So having Emacs automatically do this work for you is really neat. Each time I find such a nice little tool, I love Emacs even more ;)

Trying to hook-up that code in my Emacs I discovered it was referring to functions from Tramp, a package I never heard of before. After doing a quick search on Google, I discovered it's a mode very similar to ange-ftp, which allows the editing of remote files. However it works completely transparent over ssh too, really nice!

As with ange-ftp, you specify a remote file as /machine:filename or /user@machine:filename, if you want to login as a different user on the remote machine. File name and directory completion on the remote system works as expected, really cool!

The way this mode works is by uploading some simple programs on the remote system to allow the sending and receiving of files over ssh. You can also use scp as an alternative method of uploading and downloading files, which may be faster for larger files (I still need to investigate this option).

I'm quite impressed the way tramp works, and is definitely a much better alternative to starting a remote Emacs instance, especially if you're running an X11 version.

To use tramp, add the following to your .emacs:

(require 'tramp)

If you're using XEmacs, you will need to modify the save-buffer-same-timestamp function from here to read like below instead. Upon successful completion, funcall returns t on XEmacs, and as a result (= 0 t) throws an exception. The change below simply removes this check, as well as the enclosing and and if expressions.

(defun save-buffer-same-timestamp (&optional args)
"Save the current buffer in visited file if modified. Versions are
controlled with ARGS as with `save-buffer'. The difference between
this command and save-timestamp is that this command saves the
modification time of the file from disk and resets it after the file
is saved."
(interactive)
(message "save-buffer-same-timestamp %s" (buffer-file-name))
(let* ((buffer (current-buffer))
(file-name (if (tramp-tramp-file-p (buffer-file-name))
(tramp-file-name-path
(tramp-dissect-file-name
(tramp-completion-handle-expand-file-name
(buffer-file-name))))
(expand-file-name (buffer-file-name))))
(file-attributes (file-attributes (buffer-file-name)))
(time-string (if file-attributes
(format-time-string "%Y%m%d%H%M.%S"
(nth 5 file-attributes))))
(shell-cmd (if (tramp-tramp-file-p (buffer-file-name))
'tramp-handle-shell-command
'shell-command)))
(save-buffer args)
(funcall shell-cmd
(format "touch -t %s %s" time-string file-name))
(set-buffer buffer)
(revert-buffer nil t)))
Posted by ovidiu at 09:48 PM |
February 10, 2004

Counting to 25

Random
Last run

Last evening my son - 4 1/2 years old - was determined to count the number of dominos he was playing with. The only problem was they were more than 10, up until he's able to routinely count. So he asked his mom to help him count, and she taught him to count to 25. She taught him the numbers in Romanian, which are easier than in English. The numbers between 11 and 19 are formed by juxtaposing the digit name, the word spre (to in English), and the word zece (ten in English). The names for the numbers over 20 are composed the same way as in English.

The rest of the evening he spent counting his dominos. Useless to say, they were never 25, but varying between 21 and 25, depending on how many numbers were skipped.

Posted by ovidiu at 11:43 AM |
 
Cool stuff
  Arduino TinyWebServer: part 3 and part 2
Search
More from me
Picture gallery
Admin
Copyright © 2002-2016 Ovidiu Predescu.