Code Monkey home page Code Monkey logo

swank-js's Introduction

swank-js

NOTE: the official repo is at https://github.com/swank-js/swank-js.

swank-js provides SLIME REPL and other development tools for in-browser JavaScript and Node.JS. It consists of SWANK backend and accompanying SLIME contrib. Socket.IO is used to communicate with wide range of web browsers.

Request for Contributors

A lot of the contributors of this project are strapped for time, and we could use some more.

Please see: #52

Motivation

From my experience an ability to use REPL for JavaScript debugging and interactive development is very helpful when developing Web applications. Previously I was using a heavily patched MozRepl version that was adapted for in-browser JavaScript. Primary downsides of that approach were extreme instability of communication between Emacs and the browser, the lack of cross-browser support and the lack of good RPC between Emacs and JS that can be used to develop some handy extensions.

I knew there exists slime-proxy project that provides such functionality for Parenscript. The problem is that most of us including myself can't use Lisp all the time and a lot of code needs to be developed using languages like plain JavaScript (as opposed to Parenscript), Python and so on. My first thought was to adapt slime-proxy for use with plain JS, but then I decided to roll my own SWANK backend using Node.JS. I wanted to find out what this buzz around Node.JS is about and perhaps steal an idea or two from there for use in my Lisp projects. Another reason was availability of Socket.IO and an example of tiny http server proxy.

Some people may prefer Firebug or built-in browser development tools to Emacs-based development, but for example in case of mobile browsers you don't have much choice. At some point I did try swank-js with an colleague's iPhone and it worked, which is not too unexpected given that Socket.IO has good cross-browser support.

Status

As of now swank-js provides REPL with an ability to work with multiple browser connections, supports dynamic updates of JavaScript code using C-c C-c / C-M-x, provides debug output function and an ability to reload web pages in the browser or refresh their CSS using Emacs commands.

Many aspects of full-fledged SWANK backends aren't implemented yet, there's no debugger/completion/autodoc and so on, but as I plan to use swank-js a lot in future there's a good chance many of these features will be eventually added.

Installation

  1. Install Node.JS and npm

  2. Install swank-js from npm:

     npm install -g swank-js
    
  3. Get recent SLIME from its CVS or the git mirror. The backend was verified to work with SLIME 2012-02-12, it may or may not work with other versions, but note that breaking change in the protocol was introduced in SLIME 2011-11-27.

  4. Make sure you have latest js2-mode. Add it to your .emacs:

     (add-to-list 'load-path "/path/to/js2-mode/directory")
     (autoload 'js2-mode "js2-mode" nil t)
     (add-to-list 'auto-mode-alist '("\\.js$" . js2-mode))
    
  5. Create symbolic link to slime-js.el in the contrib subdirectory of SLIME project.

  6. Install js2-mode into emacs from http://tromey.com/elpa/

  7. In your .emacs, add the following lines (you may use other key for slime-js-reload; also, if you're already using SLIME, just add slime-js to the list of contribs, otherwise adjust the load-path item):

     (global-set-key [f5] 'slime-js-reload)
     (add-hook 'js2-mode-hook
               (lambda ()
                 (slime-js-minor-mode 1)))
    
  8. If you're using CSS mode, you may want to add the following lines too:

     (add-hook 'css-mode-hook
               (lambda ()
                 (define-key css-mode-map "\M-\C-x" 'slime-js-refresh-css)
                 (define-key css-mode-map "\C-c\C-r" 'slime-js-embed-css)))
    

Usage

If you want to use swank from the node project just add following to your package.json file:

  { 
   	 "devDependencies": {
     "swank-js": ">=0.0.1"
    },
      "scripts": {
      "swank": "node node_modules/swank-js"
    }
  }

Once this is done you should be able to run up a swank for this project by running:

    npm run swank

Alternatively you can install swank-js globally by running:

    npm install -g swank-js

Once installed you could run it from you project directory:

    swank-js

Make SLIME connect to the backend using M-x slime-connect and specifying localhost and port 4005. You will see REPL buffer with the following prompt:

NODE>

This means that you're currently talking to Node.JS. You may play around with it by running some JavaScript expressions.

If you get warning about SLIME version mismatch, you may make it disappear until the next SLIME upgrade by typing ,js-slime-version at the REPL and entering your SLIME version (e.g. 2010-11-13).

Connecting to a web browser

Point your web browser to

http://localhost:8009/swank-js/test.html

You will see the following message appear in the REPL (browser name and version may differ):

Remote attached: (browser) Firefox3.6:127.0.0.1

This means that the browser is now connected. Several browsers can connect simultaneously and you can switch between them and Node.JS REPL using ,select-remote REPL shortcut. To use it, press ',' (comma) and type select-remote (completion is supported). You will see "Remote:" prompt. Press TAB to see completions. Select your browser in the list by typing its name or clicking on the completion. The following message will appear:

NODE>
Remote selected: (browser) Firefox3.6:127.0.0.1
FIREFOX-3.6>

After that, you can interactively evaluate expressions in your browser. To go back to Node.JS repl, switch back to node.js/direct remote.

FIREFOX-3.6> document.body.nodeName
BODY
FIREFOX-3.6> alert("test!")
FIREFOX-3.6>

When working with browser, you may use F5 to reload the page. swank-js connection with browser is lost in this case, but to solve this problem you may use ,sticky-select-remote instead of ,select-remote. This way swank-js will remember your selection and automagically attach to the browser whenever it connects. If you press F5 after using ,sticky-select-remote, you will see that browser briefly disconnects but then connects again:

Remote detached: (browser) Firefox3.6:127.0.0.1
FIREFOX-3.6>
Remote selected (auto): (direct) node.js
Remote attached: (browser) Firefox3.6:127.0.0.1
NODE>
Remote selected (auto): (browser) Firefox3.6:127.0.0.1
FIREFOX-3.6>

The sticky remote selection is saved in the config file, ~/.swankjsrc, so you don't need to do ,sticky-select-remote after restarting the browser.

Connecting to a remote page

Now, let's try to make it work with an actual site. swank-js acts as a proxy between your browser and the site so it can inject necessary script tags into HTML pages and avoid cross-domain HTTP request problems. Let's point it to reddit. Type ,target-url and then http://www.reddit.com (www. part is important, otherwise it will redirect to www.reddit.com skipping the proxy). Point your browser to http://localhost:8009, you'll see reddit frontpage load. If you didn't do ,select-remote or ,sticky-select-remote yet do it now and select your browser from the list of remotes. Now you can execute JavaScript in the context of reddit:

FIREFOX-3.6> $(".sitetable a.title").map(function(n) { return (n + 1) + ". " + $(this).text(); }).get().join("\n")
1. Wikileaks currently under a mass DDOS attack
2. Munich University - Jealous
...

Let's make a function from it. Create a file test.js somewhere and make sure it uses js2-mode (if it doesn't, switch it to js2-mode using M-x js2-mode). Type the following there:

function listRedditTitles () {
  $(".sitetable a.title").map(
    function (n) {
      SwankJS.output((n + 1) + ". " + $(this).text() + "\n");
    }).get().join("\n");
}

Note SwankJS.output() function being used there. It allows you to send debug print to SLIME REPL.

Move the point somewhere into the middle of the listRedditTitles() function and press C-M-x. Now you may try it out in the REPL:

FIREFOX-3.6> listRedditTitles()
1. Wikileaks currently under a mass DDOS attack
2. Munich University - Jealous
...

You may edit the function definition and update it using C-M-x any number of times.

Hacking CSS

By updating a file

Now let's try some CSS hacking. Create a directory named zzz and start a Web server in it from your command prompt:

$ mkdir zzz && cd zzz && python -mSimpleHTTPServer

Create a file named a.css there and make sure it uses css-mode (like with js2-mode, you can force it with M-x css-mode). Add some CSS rules to this file:

body {
    background: green;
}

Now let's add the stylesheet to the reddit page:

FIREFOX-3.6> $('head').append('<link rel="stylesheet" href="http://localhost:8000/a.css" type="text/css" />');
[object Object]

You will see some parts of the page become green. Now, change green to blue in the CSS file and press C-M-x (it will save the file automatically):

body {
    background: blue;
}

You will see the page become blue, maybe after some flickering as all CSS used on the page is reloaded. This way you may update CSS in an AJAX application without reloading the page, which is often rather handy. Unlike editing CSS in Firebug in case when you're editing CSS of your own application changes will not disappear upon page reload (with reddit page you'll have to readd the stylesheet).

By embedding CSS

Alternatively to just try out a snippet of CSS you can select some CSS code and hit C-c C-r. This will send the code snippet (or the content of the whole buffer) to the browser and embed it inside a style element.

To remove the embedded CSS run the command with a prefix C-u C-c C-r.

Embedding swank-js in a page

This is useful for automatically connecting to a web page you develop locally without using the ,target-url command and without changing the document URL for that page. When node swank.js is running embed

<script type="text/javascript" src="http://localhost:8009/swank-js/swank-js-inject.js"></script>

and you are ready to go!

swank-js as a bookmarklet

You can bookmark swank connect / swank disconnect links and use them on any page you'd like to play with.

swank-js from another node.js process

When installed globally (npm install -g swank-js) you can connect another node.js process to the swank-js node process via

require("swank-js/client/node").setupNodeJSClient();

Optionally you can pass in swank_server_host and swank_server_port as arguments to the setupNodeJSClient call.

Troubleshooting

I've noticed that flashsocket Socket.IO transport does exhibit some instability. You may want to try other transports by changing the socketio cookie, e.g.:

document.cookie = "socketio=xhr-polling"

Be careful not to lose connection to the browser though especially in case of REPL-less browser like IE6/7 or you'll have to type something like

javascript:void(document.cookie = "socketio=flashsocket")

in the address bar.

In case of IE, increasing the maximum number of HTTP connections may help with non-Flash transports, although I didn't try it yet. To do it add DWORD value MaxConnectionsPer1_0Server to the following registry key:

HKEY\_CURRENT\_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings

License

swank-js is distributed under X11-style license. See LICENSE file.

swank-js's People

Contributors

archimag avatar arianitu avatar davelambert avatar diunko avatar erjoalgo avatar fukamachi avatar gozala avatar hanshuebner avatar hugoduncan avatar ivan4th avatar jaeschliman avatar joddie avatar jonnay avatar magnars avatar newsomc avatar rksm avatar rohitarondekar avatar xiaohanyu avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

swank-js's Issues

More contributors

I'm busy these days, and don't have much time and we need some more contributors. Apply within!

Run slime-js on a different port

Hello again :)

I have a clojure project also running on my server that serves another potion of my web project, which also runs slime/swank on the same port that slime-js defaults to. I am wondering if there is any way to specify another port for which slime-js will run on.

`:coding-system` / `:coding-systems` discrepancy

Looks like there has been some change in the past year or so that changed a keyword at least. Here is what got written to my *Messages* buffer:

Versions differ: 2012-02-07 (slime) vs. 2010-11-13 (swank). Continue? (y or n) y
error in process filter: cond: Keyword argument :coding-system not one of (:coding-systems)
error in process filter: Keyword argument :coding-system not one of (:coding-systems)

and here's the node side:

$ node swank.js
   info  - socket.io started
Handler.prototype.receive(): (:emacs-rex (swank:connection-info) "COMMON-LISP-USER" t 1)
info = {"pid":53425,"encoding":{"codingSystem":"utf-8","externalFormat":"UTF-8"},"packageSpec":{"name":"NODE","prompt":"NODE"},"implementation":{"type":"JS","name":"JS","version":"1.5"},"version":"2010-11-13"}
response: 0000d3(:return (:ok (:encoding (:coding-system "utf-8" :external-format "UTF-8") :lisp-implementation (:name "JS" :type "JS" :version "1.5") :package (:name "NODE" :prompt "NODE") :pid 53425 :version "2010-11-13")) 1)

error on connect: "symbol's value as variable is void: package-updating"

I get this error when trying to run slime-connect after having started swank-js.

Seems to be related to slime-js.el somehow: When I don't simlink this and don't have slime-js installed, I get at least asked for IP and port when running slime-connect.
With slime-js present, I just get the error message from above.

Any ideas what is going wrong?

Fix Sticky Remotes

On the one hand Sticky Remotes seem to cause a lot of confusion, but on the other, they are really useful.

There needs to be a much better way to persist sticky remotes, list them, and show the user we are trying to connect to one.

Persistence: A customizable var, instead of yet another dotfile.
Listing and status: Maybe when slime is connected, we could show all sticky remotes, and whether or not they are connected and available?

#21

Can't call slime-js-send-defun

C-M-x and C-c\C-c give the following error in emacs:
Wrong type argument: stringp, nil

I tried the key chords inside the js code, before and after the js code for the demo function listRedditTitles() with the same error. The function wasn't define on my slime-repl JS* prompt.

My emacs fu is not strong with this problem. Can you point me in the right direction?
Thanks.

slime-js--echo-result does not properly escape '%' character

slime-js--echo-result does not properly escape '%' character. When creating an object that returns a blob url schme expected no error and result to be printed to the repl. Actually got:

(error "Not enough arguments for format string")
message("blob:http%3A//localhost%3A8009/8")
slime-js--echo-result("blob:http%3A//localhost%3A8009/8" 271 84)

[PATCH] use the generated doc string for slime-js-minor-mode which is better

(http://bpaste.net/raw/44357)

diff --git a/slime-js.el b/slime-js.el
index d5df22dd..de7c9b86 100644
--- a/slime-js.el
+++ b/slime-js.el
@@ -251,12 +251,7 @@ (defun slime-js-send-defun ()
                  (setf sent-func (match-string 1)))
                (message "Sent: %s" sent-func))))))))

-(define-minor-mode slime-js-minor-mode
-  "Toggle slime-js minor mode
-With no argument, this command toggles the mode.
-Non-null prefix argument turns on the mode.
-Null prefix argument turns off the mode."
-  nil
+(define-minor-mode slime-js-minor-mode nil nil
   " slime-js"
   '(("\C-\M-x"  . slime-js-send-defun)
     ("\C-c\C-c" . slime-js-send-defun)

this.context = Script.createContext(); ^ TypeError: undefined is not a function

myuser-netbook$npm run swank

> [email protected] swank /home/myuser/programs/swank-js-master
> node ./swank.js

/home/myuser/programs/swank-js-master/swank-handler.js:303
  this.context = Script.createContext();
                        ^
TypeError: undefined is not a function
    at new DefaultRemote (/home/myuser/programs/swank-js-master/swank-handler.js:303:25)
    at new Executive (/home/myuser/programs/swank-js-master/swank-handler.js:370:21)
    at Object.<anonymous> (/home/myuser/programs/swank-js-master/swank.js:43:17)
    at Module._compile (module.js:460:26)
    at Object.Module._extensions..js (module.js:478:10)
    at Module.load (module.js:355:32)
    at Function.Module._load (module.js:310:12)
    at Function.Module.runMain (module.js:501:10)
    at startup (node.js:129:16)
    at node.js:814:3

npm ERR! Linux 3.2.0-4-686-pae
npm ERR! argv "/usr/local/bin/node" "/usr/local/bin/npm" "run" "swank"
npm ERR! node v0.12.4
npm ERR! npm  v2.10.1
npm ERR! code ELIFECYCLE
npm ERR! [email protected] swank: `node ./swank.js`
npm ERR! Exit status 1
npm ERR! 
npm ERR! Failed at the [email protected] swank script 'node ./swank.js'.
npm ERR! This is most likely a problem with the swank-js package,
npm ERR! not with npm itself.
npm ERR! Tell the author that this fails on your system:
npm ERR!     node ./swank.js
npm ERR! You can get their info via:
npm ERR!     npm owner ls swank-js
npm ERR! There is likely additional logging output above.

npm ERR! Please include the following file with any support request:
npm ERR!     /home/myuser/programs/swank-js-master/npm-debug.log

target-url only goes to the target domain

Hey, I am probably missing something blindingly obvious here but it would be great if you could help.

Using swank-js and slime-js I can connect my browser to the REPL in Emacs, and perform some basic JS (alert(), etc). I can also go to the slime-js REPL and type ",target-url" and successfully see a site appear in the browser. However, I will only go to the domain of the URL that I type.

For example, if I type "http://conornash.com/?p=22" the page shown in the browser will be "http://conornash.com/". How do I prevent this happening?

don't create the "exports" variable

The client-side js creates a global "exports" variable. This is a bad name to use because a lot of code checks for that to see if they are in a node environment. I'd recommend not using it.

Failing swank-handler-tests

I made some minor changes to help with testing, namely I made this little file that I call tests.js

#!/usr/bin/env node
require("./completion-tests");
require("./swank-handler-tests");
require("./swank-protocol-tests");
require("./user-agent-tests");

and added "test": "./tests.js" to package.json. So I get this error.

$ npm test

> [email protected] test /tmp/swank-js
> ./tests.js

'completion eval error: TypeError' is expected: completion eval error: TypeError: Cannot read property 'bar' of undefined

assert.js:92
  throw new assert.AssertionError({
        ^
AssertionError: got response (:return (:ok (:not-available t)) 6) instead of (:return (:ok :not-available) 6)
    at Handler.i (/tmp/swank-js/swank-handler-tests.js:50:14)
    at Handler.emit (events.js:95:17)
    at Handler.sendResponse (/tmp/swank-js/swank-handler.js:240:8)
    at cont (/tmp/swank-js/swank-handler.js:99:10)
    at Handler.receive (/tmp/swank-js/swank-handler.js:227:3)
    at request (/tmp/swank-js/swank-handler-tests.js:67:11)
    at Object.<anonymous> (/tmp/swank-js/swank-handler-tests.js:91:1)
    at Module._compile (module.js:456:26)
    at Object.Module._extensions..js (module.js:474:10)
    at Module.load (module.js:356:32)
npm ERR! Test failed.  See above for more details.

You can reproduce this easily by cloning my fork, ie

cd /tmp
git clone http://github.com/fakedrake/swank-js
cd swank-js
npm test

Swank-js-inject.js assumes js files available on same port

Hi,

Within client/swank-js-inject.js, the line:

if (!window.swank_server)
   window.swank_server = document.location.protocol + "//" + document.location.host + "/";

... assumes that the swank server and swank js files are on the same port as the application that the swank-js-inject.js file has been referenced from. This is ok if the local server is happy to serve up swank's js files, however with a node app a la:

var http = require('http');
var fs = require('fs'); 
var index = fs.readFileSync('index.html');

var server = http.createServer( function(req,res){
    res.writeHead(200, {"Content-Type":"text/html"});
    res.end(index);
}).listen(8000);

...and index.html includes <script type="text/javascript" src="http://localhost:8009/swank-js/swank-js-inject.js"></script>, the swank-js files will fail to get loaded as the node app (on that port) will only serve up index.html and not the swank js files.

I hope that I'm not misinterpreting something here, I've locally fixed the issue by altering the line to include a + ':8009/', but I'm not sure what a permanent fix should look like.

ReferenceError: SwankJS is not defined

First of all I want to say THANKS for this! Ive been searching for something like this for a long time, and finally u made it work...

Altho i have one problem. I get a stack trace including this msg: ReferenceError: SwankJS is not defined when i try running slime-js-reload. Any way to fix this on my end?

Better Display of objects

Right now all objects are going through toString (I think?) which is good in most cases, until we get to objects. Objects should be JSON pretty printed (at least). I dont' know enough about slime/swank, but perhaps there is a better way to browse objects, which would be even more slick.

Of course, we'd have to be careful about circular structures. We'll probably need to write our own version of stringify, so that we can handle them, otherwise (for instance) printing out any result from jQuery will give us problems.

repo doesn't work with slime/slime head....(and melpa/elpa versions)

I've just had some fun trying to get up and running - I've figured that the last release of slime/slime that is compatible with the head of this repo was version 2.9. Here are the notes I made during a manual bisect through the tags in the slime repo....

   - [ ] 2015-06-01 22:11:38 +0100  (tag: v2.14)
   - [ ] 2015-03-04 19:45:01 +0000  (tag: v2.13)
   - [ ] 2015-01-02 20:06:48 +0000  (tag: v2.12)
   - [ ] 2014-12-01 10:05:54 +0000  (tag: v2.11)  -- BAD destructure case
   - [ ] 2014-10-10 21:57:04 +0100  (tag: v2.10.1)
   - [ ] 2014-10-06 23:00:37 +0100  (tag: v2.10) -- BAD destructure case + invalid args.
   - [X] 2014-08-04 21:49:54 +0000  (tag: v2.9)
   - [X] 2014-07-05 18:48:21 +0400  (tag: v2.8)
   - [X] 2014-06-01 22:32:31 +0100  (tag: v2.7)
   - [X] 2014-05-04 23:53:29 +0100  (tag: v2.6)
   - [X] 2014-03-31 22:54:49 +0100  (tag: v2.5)
   - [X] 2014-03-02 13:39:46 +0000  (HEAD, tag: v2.4)

I'm not sure if my elisp is up to fixing but I think it'd be good if at least (in lieu of a fix) the README could be updated to reflect something like this. If I get the thumbs up I can maybe submit a PR to summarise the steps I took today to get it up and running maybe?

At very least there should be some sort of recipe for getting someone up and running. Current status is that it just doesn't work with melpa etc. ( correct me if I'm wrong). Which is a shame coz it's very cool stuff :-)

Bust to double check am I being stupid - Is there another fork/patch of slime that currently does work with this repo?

Cheers,

A.

Start swank-js failed

[email protected]
[email protected]
[email protected]
[email protected]

~/src/js/swank-js $ node swank.js

node.js:63
throw e;
^
TypeError: Object function serveClient(req, res) {
var self = this;
var path = url.parse(req.url).pathname, parts, cn;
// console.log("%s %s", req.method, req.url);
if (path && path.indexOf("/swank-js/") != 0) {
// console.log("--> proxy");
this.proxyRequest(req, res);
return;
}
var file = path.substr(1).split('/').slice(1);

var localPath = this.clientFiles[file];
if (req.method == 'GET' && localPath !== undefined){
// TBD: reenable caching, check datetime of the file
// if (path in this.cachedFiles){
// this.sendCachedFile(req, res, path);
// return;
// }

fs.readFile(
  __dirname + '/client/' + localPath, function(err, data) {
    if (err) {
      console.log("error: %s", err);
      self.notFound(res);
    } else {
      var ext = localPath.split('.').pop();
      self.cachedFiles[localPath] = {
        headers: {
          'Content-Length': data.length,
          'Content-Type': self.types[ext],
          'ETag': self.clientVersion
        },
        content: data,
        encoding: ext == 'swf' ? 'binary' : 'utf8'
      };
      self.sendCachedFile(req, res, localPath);
    }
  });

} else {
console.log("bad request for /swank-js/ path");
this.notFound(res);
}
} has no method 'bind'
at Object. (/home/darren/src/js/swank-js/swank.js:374:61)
at Module._compile (node.js:462:23)
at Module._loadScriptSync (node.js:469:10)
at Module.loadSync (node.js:338:12)
at Object.runMain (node.js:522:24)
at Array. (node.js:756:12)
at EventEmitter._tickCallback (node.js:55:22)
at node.js:773:9

interact with a local file

I may be asking a stupid question, but I didn't manage to interact with a local file as done with the example in the tutorial test.html (accessed via the url "localhost:8009/swank-js/test.html"). Assuming I have an html file located at /path/to/local/file.html, what should I write in the url bar? If I use the target-url command specifying file:///path/to/local/file.html it doesn't seem to work, as I receive the message "WARNING: the URL must contain host and port" and pointing the browser to "localhost:8009" produces the message: "swank-js: unable to forward the request". Am I missing something? Btw, many thanks for the great tool!

Better Documentation

I want to write some better documentation for this project. Not that it isn't good, but I think some clearer organization, and a how-to guide to make it work with your own node.js project.

Also, instead of living in the readme, the primary documentation should be in the wiki. I'll be using org-mode format for that.

Fix a typo

diff --git a/slime-js.el b/slime-js.el
index a0891459..68594ed5 100644
--- a/slime-js.el
+++ b/slime-js.el
@@ -79,7 +79,7 @@ (defun slime-js-read-remote-index (&optional prompt)
(p (or (position
(completing-read prompt (slime-bogus-completion-alist remote-names)
nil nil nil

  •                              'slime-remote-history nil)
    
  •                              'slime-js-remote-history nil)
              remote-names :test #'equal)
             (error "bad remote name"))))
    
    (first (elt remotes p))))

Please delete

Please delete. I had reported an issue that mysteriously resolved itself.

Basic page information

It would be cool if swank.js had some tools for basic page information and debugging. Something like:

  • A shortcut to getElementByID, (or perhaps even the ender.js selector library)
  • A way to list available stylesheets
  • A way to list currently loaded scripts

js-mode?

installation notes suggest js2-mode is a dependency, i'm quite attached to js-mode.. are there known issues in mixing js-mode and swank, or is it just untested?

"slime-dcase failed" error

Hi all!

I get this strange error whenever I try to connect to my browser. As
soon as I load http://localhost:8009/swank-js/test.html I get.

Debugger entered--Lisp error: (error "slime-dcase failed: (:write-string \"Remote detached: (browser) Firefox32.0
\")")
  signal(error ("slime-dcase failed: (:write-string \"Remote detached: (browser) Firefox32.0\n\")"))
  error("slime-dcase failed: %S" (:write-string "Remote detached: (browser) Firefox32.0\n"))
  slime-dispatch-event((:write-string "Remote detached: (browser) Firefox32.0\n") #<process SLIME Lisp>)
  slime-process-available-input(#<process SLIME Lisp>)
  slime-net-filter(#<process SLIME Lisp> "000039(:write-string \"Remote detached: (browser) Firefox32.0\n\")")

I installed slime-js using el-get with the following recipe:

(:name swank-js
   :description "SLIME REPL and other development tools for in-browser JavaScript and Node.JS"
   :type github
   :pkgname "swank-js/swank-js"
   :depends (js2-mode slime)
   :after (let* ((slime-dir (el-get-package swank-js))
         (swank-js-dir (el-get-package swank-js))
         (slime-link (concat slime-dir "/contrib/slime-js.el"))
         (swank-el (concat swank-js-dir "/slime-js.el")))
        ;; Make sur the file is there.
        (unless (file-exists-p slime-link)
          (make-symbolic-link swank-el slime-link)))
   :features nil))

Also *slime-events* is:

(:emacs-rex
 (swank:connection-info)
 nil t 1)
(:return
 (:ok
  (:encoding
   (:coding-systems
    ("utf-8-unix"))
   :lisp-implementation
   (:name "JS" :type "JS" :version "1.5")
   :package
   (:name "NODE" :prompt "NODE")
   :pid 6257 :version "2012-02-12"))
 1)
(:emacs-rex
 (swank:simple-completions "ale" '"COMMON-LISP-USER")
 "COMMON-LISP-USER" t 2)
(:return
 (:ok
  (nil "ale"))
 2)
(:emacs-rex
 (swank:simple-completions "ale" '"COMMON-LISP-USER")
 "COMMON-LISP-USER" t 3)
(:return
 (:ok
  (nil "ale"))
 3)
(:emacs-rex
 (swank-repl:listener-eval "alert(\"hello\")\n")
 "COMMON-LISP-USER" :repl-thread 4)
(:return
 (:ok nil)
 4)
(:write-string "Remote detached: (browser) Firefox32.0\n")
(:write-string "Remote attached: (browser) Firefox32.0\n")
(:write-string "Remote detached: (browser) Firefox32.0\n")
(:write-string "Remote attached: (browser) Firefox32.0\n")
(:write-string "Remote detached: (browser) Firefox32.0\n")

and the output of swank-js (run in /tmp)

 $ swank-js
client connected
client connected
added remote: (browser) Firefox32.0
client connected
client connected
client connected
client connected
client connected
client connected
client connected
client connected
client connected
client connected
client connected
client connected
Handler.prototype.receive(): (:emacs-rex (swank:connection-info) nil t 1)
info = {"pid":6257,"encoding":{"codingSystems":["utf-8-unix"]},"packageSpec":{"name":"NODE","prompt":"NODE"},"implementation":{"type":"JS","name":"JS","version":"1.5"},"version":"2012-02-12"}
response: 0000c1(:return (:ok (:encoding (:coding-systems ("utf-8-unix")) :lisp-implementation (:name "JS" :type "JS" :version "1.5") :package (:name "NODE" :prompt "NODE") :pid 6257 :version "2012-02-12")) 1)
Handler.prototype.receive(): (:emacs-rex (swank:simple-completions "ale" '"COMMON-LISP-USER") "COMMON-LISP-USER" t 2)
Called swank:simple-completions: ale
complete: ale
response: 00001d(:return (:ok (nil "ale")) 2)
Handler.prototype.receive(): (:emacs-rex (swank:simple-completions "ale" '"COMMON-LISP-USER") "COMMON-LISP-USER" t 3)
Called swank:simple-completions: ale
complete: ale
response: 00001d(:return (:ok (nil "ale")) 3)
Handler.prototype.receive(): (:emacs-rex (swank-repl:listener-eval "alert(\"hello\")\n") "COMMON-LISP-USER" :repl-thread 4)
Unfound Command, Trying to run: listener_eval
response: 000015(:return (:ok nil) 4)
client disconnected: Firefox32.0
response: 000039(:write-string "Remote detached: (browser) Firefox32.0
")
found device
{ address: '127.0.0.1', family: 'IPv4', internal: true }
{ address: '::1', family: 'IPv6', internal: true }
found device wlp3s0
{ address: '192.168.1.4', family: 'IPv4', internal: false }
{ address: 'fe80::1af4:6aff:fe03:87c1',
  family: 'IPv6',
  internal: false }
client connected
response: 000039(:write-string "Remote attached: (browser) Firefox32.0
")
added remote: (browser) Firefox32.0
client disconnected: Firefox32.0
response: 000039(:write-string "Remote detached: (browser) Firefox32.0
")
found device lo
{ address: '127.0.0.1', family: 'IPv4', internal: true }
{ address: '::1', family: 'IPv6', internal: true }
found device wlp3s0
{ address: '192.168.1.4', family: 'IPv4', internal: false }
{ address: 'fe80::1af4:6aff:fe03:87c1',
  family: 'IPv6',
  internal: false }
client connected
response: 000039(:write-string "Remote attached: (browser) Firefox32.0
")
added remote: (browser) Firefox32.0
client disconnected: Firefox32.0
response: 000039(:write-string "Remote detached: (browser) Firefox32.0
")

Sorry about the flood of info, I am not sure what is relevant.

Wrong type argument: sequencep, :not-available

After connected to Chrome, I just typed

alert('hello');

minibuffer outputs:

error in process filter: =: Wrong type argument: sequencep, :not-available
error in process filter: Wrong type argument: sequencep, :not-available

After seconds the browser alerts. Can somebody tell be what is happening ? I'm using ubuntu 12.04, emacs 24.1.1, chrome 20.0.1132.47, and node v0.8.1. Thanks.

Query: can this be used to develop browser extensions?

Is it possible to use swank-js to develop browser extensions as well as js for web pages? E.g., could one use this to develop chrome for Firefox or the equivalent for Chrome, and if so, how?

Thanks, looks fabulous!

Abort when unicode is used

Try entering the following in slime-repl:

"你好".length

after that all communication between slime and swank is broken. The same thing happens when the return value from swank contains unicode. For example, I was trying the example:

$(".sitetable a.title").map(function(n) { return (n + 1) + ". " + $(this).text(); }).get().join("\n")

and reddit.com today contains this heading (note the two unicode chars at the end):

I just explained memes to my uncle. This was his first one ಠ_ಠ (qkme.me)

The error looks like this: http://paste.pocoo.org/show/529755

New Maintainers

I dunno about the other people, but I don't have time to maintain this project anymore.

Anyone interested in becoming the new maintainers?

Need some way to do an NPM publish

Right now My identity is not the correct identity to do an npm publish on the swank-js package.

Who has the rights to that?

How do we re-assign rights?

repl barfs on {a: 1}.a

{a: 1}.a should evaluate to 1, but the repl instead thrown an exception. Running node js from the command line, without swank-js as an intermediary, handles this case.

Here is the stack trace:
NODE> {a: 1}.a
SyntaxError: Unexpected token .
at DefaultRemote.evaluate (/home/brenmill/Dropbox/ext/swank-js/swank-handler.js:267:9)
at Executive.listenerEval (/home/brenmill/Dropbox/ext/swank-js/swank-handler.js:367:21)
at Handler.receive (/home/brenmill/Dropbox/ext/swank-js/swank-handler.js:161:20)
at SwankParser.onMessage (/home/brenmill/Dropbox/ext/swank-js/swank.js:49:17)
at SwankParser.handleMessage (/home/brenmill/Dropbox/ext/swank-js/swank-protocol.js:73:8)
at SwankParser.handleContent (/home/brenmill/Dropbox/ext/swank-js/swank-protocol.js:58:10)
at SwankParser.execute (/home/brenmill/Dropbox/ext/swank-js/swank-protocol.js:47:20)
at Socket. (/home/brenmill/Dropbox/ext/swank-js/swank.js:59:16)
at Socket.emit (events.js:64:17)
at Socket._onReadable (net.js:673:31)

no match for 'select-remote'

I've been following theought the instruction on the main page of the repo.

from a terminal I can run 'swank-js'. Then within emacs I can run 'slime-connect'. Then I get a buffer with the NODE prompt.

I then visit this url in my browser:
http://localhost:8009/swank-js/test.html

On that page I can see:

You have connected to swank.js! 
you can use ,select-remote to select this browser now!

...followed by information about bookmarklets.

However, back inside the buffer with NODE prompt, I don't have access to the command 'select-remote'. I hit comma, and get access to a bunch of command. 'select-remote' is not one of them. If I start to type it in the minibuffer and hit TAB for completion, I get 'no match'.

select-remote not appearing as available command.

I receive the error "document not defined" in the REPL (after starting everything up). I believe I have missed a step or a critical component - but I followed the documentation steps.

Here is the copy-paste from the question I asked StackOverflow (http://stackoverflow.com/questions/12066196/why-does-swank-js-give-me-document-is-not-defined-in-the-emacs-repl):

I follow these steps:

Run swank-js in the command line.
Run emacs.
M-x slime-connect.
Host: 127.0.0.1; Port: 4005
Open up the http://localhost:8009/swank-js/test.html in Firefox.
Receive: "Remote attached: (browser) Firefox14.0" in the emacs REPL.
Run the command "document" in the REPL.

At this point, I receive the error:

ReferenceError: document is not defined
at repl:1:1
at DefaultRemote.evaluate (/usr/lib/nodejs/swank-js/swank-handler.js:314:9)
at Executive.listenerEval (/usr/lib/nodejs/swank-js/swank-handler.js:414:21)
at Handler.receive (/usr/lib/nodejs/swank-js/swank-handler.js:169:20)
at SwankParser.onMessage (/usr/lib/nodejs/swank-js/swank.js:50:17)
at SwankParser.handleMessage (/usr/lib/nodejs/swank-js/swank-protocol.js:75:8)
at SwankParser.handleContent (/usr/lib/nodejs/swank-js/swank-protocol.js:62:10)
at SwankParser.execute (/usr/lib/nodejs/swank-js/swank-protocol.js:53:20)
at Socket. (/usr/lib/nodejs/swank-js/swank.js:60:16)
at Socket.emit (events.js:67:17)

Should I be using require() or something? I'm still a bit hazy how swank/slime/node are communicating so please forgive the black box nature of this question. :D

Uncaught ReferenceError: module is not defined

I'm trying to get swank-js+slime-js working and I keep running into this error. When I hook up to a browser, the test page loads fine, however I get the following error in my javascript console (which prevents remote execute from working):

Uncaught ReferenceError: module is not defined :8009/socket.io/socket.io.js:1

The relevant code is here:

!function(e){"object"==typeof exports?module.exports=e():"function"==typeof define&&define.amd?define(e):"undefined"!=typeof window?window.io=e():"undefined"!=typeof global?global.io=e():"undefined"!=typeof self&&(self.io=e())}(function(){var define,module,exports;

It looks like the "module" variable is not defined, but why I can't say. I'm using NodeJS version 0.10.30, and this exact problem happens on OSX and Windows.

Any ideas? I've tried it on the npm version of swank-js as well as downloading directly from github and installing.

Best,
JLS

M-x swank-js-run-swank not working

Hi all,

I am not sure if I am doing something wrong or if this is a legitimate bug, but when I run M-x swank-js-run-swank it does not start the swank server. I am running Emacs 24.1.1 on Win7 64 bit. I added the following line to my init.el:
(makunbound 'slime-js-swank-buffer)
and it started working though. Basically it seemed like even though slime-js-swank-buffer was not being set anywhere (that I could find) it was also not being evaluated as void so the following snippet of code from setup-slime-js.el:
(defun slime-js-run-swank ()
"Runs the swank side of the equation."
(interactive)
(unless (boundp 'slime-js-swank-buffer)
(setq slime-js-swank-buffer
(apply #'make-comint "swank-js" slime-js-swank-command nil slime-js-swank-args))))
would always not load swank-js because boundp would always return true. Anyway, my work around above got it working for me and I thought it might help you to let you know. Thanks for swank-js!

Doesn't work with Firefox 4

  1. console.log.apply is undefined
    When I changed the last line in SwankJS.debug to
    Function.prototype.apply.call(debug, console, args);
    it worked.
  2. Evaluating a reference to native code (like console.log) is broken
    On the client side, it throws
    TypeError: can't convert r to string
    most likely from swank-js.js:129 (String(r)).
  3. Evaluating an object literal throws a scary stack trace:
    FIREFOX-4.0> {a:1, b:2}
    SyntaxError: invalid label
    swankjs_evaluate([object Object])@http://127.0.0.1:8009/swank-js/swank-js.js:112
    {anonymous}("message",[object Array])@http://127.0.0.1:8009/socket.io/socket.io.js:881
    {anonymous}([object Object])@http://127.0.0.1:8009/socket.io/socket.io.js:920
    {anonymous}("j{"id":41,"code":"{a:1, b:2}\n"}")@http://127.0.0.1:8009/socket.io/socket.io.js:196
    {anonymous}("m34m~~j{"id":41,"code":"{a:1, b:2}\n"}")@http://127.0.0.1:8009/socket.io/socket.io.js:172
    {anonymous}([object MessageEvent])@http://127.0.0.1:8009/socket.io/socket.io.js:387
    {anonymous}()@http://127.0.0.1:8009/socket.io/socket.io.js:1736
    {anonymous}(0)@http://127.0.0.1:8009/socket.io/socket.io.js:1591
    It doesn't seem to work with Chrome either, but the stack trace from it looks nicer.

Fix or document the following potential issue when running slime-js-run-swank

Can't exec program: /Users/jonathana/.emacs.d/npm


Process swank-js exited abnormally with code 127
env: node: No such file or directory

The fix is to make sure your path is set up properly so both node and npm can be found by emacs.

The first error is if npm isn't on the path. The second is if node is not of the path.

no SwankJS.setup is called when interacting with real sites

this causes confusion to new beginners.

updated a block of code in swank.js to be :

HttpListener.prototype.scriptBlock =
new Buffer(
'<script type="text/javascript" src="/swank-js/json2.js"></script>' +
'<script type="text/javascript" src="/socket.io/socket.io.js"></script>' +
'<script type="text/javascript" src="/swank-js/stacktrace.js"></script>' +
'<script type="text/javascript" src="/swank-js/swank-js.js"></script>' +
'<script type="text/javascript">SwankJS.setup("http://127.0.0.1:8009/")</script>');

seems to fix this problem.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.