Browse Source

Rename the project to Indium

tags/0.4.0
Nicolas Petton 3 years ago
parent
commit
bda4c04ab5
Signed by: nico <nicolas@petton.fr> GPG Key ID: 233587A47C207910
43 changed files with 2434 additions and 2149 deletions
  1. +1
    -1
      Cask
  2. +588
    -0
      doc/Indium.texi
  3. +0
    -392
      doc/Jade.texi
  4. BIN
      doc/repl.png
  5. BIN
      doc/repl2.png
  6. BIN
      img/indium.png
  7. +89
    -0
      img/inlium.svg
  8. +51
    -51
      indium-backend.el
  9. +50
    -50
      indium-breakpoint.el
  10. +36
    -36
      indium-chrome.el
  11. +135
    -0
      indium-debugger-frames.el
  12. +37
    -37
      indium-debugger-litable.el
  13. +32
    -32
      indium-debugger-locals.el
  14. +144
    -144
      indium-debugger.el
  15. +30
    -30
      indium-faces.el
  16. +152
    -0
      indium-inspector.el
  17. +61
    -61
      indium-interaction.el
  18. +12
    -12
      indium-nodejs.el
  19. +57
    -57
      indium-render.el
  20. +399
    -0
      indium-repl.el
  21. +18
    -18
      indium-scratch.el
  22. +4
    -4
      indium-test-helpers.el
  23. +159
    -159
      indium-v8-inspector.el
  24. +178
    -178
      indium-webkit.el
  25. +33
    -33
      indium-workspace.el
  26. +10
    -10
      indium.el
  27. +0
    -135
      jade-debugger-frames.el
  28. +0
    -152
      jade-inspector.el
  29. +0
    -399
      jade-repl.el
  30. +12
    -12
      readme.md
  31. +4
    -4
      sphinx-doc/Makefile
  32. +11
    -11
      sphinx-doc/code-evaluation.rst
  33. +9
    -9
      sphinx-doc/conf.py
  34. BIN
      sphinx-doc/img/indium.png
  35. +3
    -3
      sphinx-doc/index.rst
  36. +12
    -12
      sphinx-doc/installation.rst
  37. +6
    -6
      sphinx-doc/intro.rst
  38. +2
    -2
      sphinx-doc/repl.rst
  39. +13
    -13
      sphinx-doc/setup.rst
  40. +12
    -12
      test/jade-backend-test.el
  41. +7
    -7
      test/jade-debugger-litable-test.el
  42. +20
    -20
      test/jade-interaction-test.el
  43. +47
    -47
      test/jade-workspace-test.el

+ 1
- 1
Cask View File

@@ -1,7 +1,7 @@
(source gnu)
(source melpa)

(package-file "jade.el")
(package-file "indium.el")

(depends-on "websocket")



+ 588
- 0
doc/Indium.texi View File

@@ -0,0 +1,588 @@
\input texinfo @c -*-texinfo-*-
@c %**start of header
@setfilename Indium.info
@documentencoding UTF-8
@ifinfo
@*Generated by Sphinx 1.5.5.@*
@end ifinfo
@settitle Indium Documentation
@defindex ge
@paragraphindent 0
@exampleindent 4
@finalout
@dircategory Emacs
@direntry
* Indium: (Indium.info). JavaScript development environment for Emacs.
@end direntry

@definfoenclose strong,`,'
@definfoenclose emph,`,'
@c %**end of header

@copying
@quotation
Indium 0.3.3, Apr 12, 2017

Nicolas Petton

Copyright @copyright{} 2017, Nicolas Petton
@end quotation

@end copying

@titlepage
@title Indium Documentation
@insertcopying
@end titlepage
@contents

@c %** start of user preamble

@c %** end of user preamble

@ifnottex
@node Top
@top Indium Documentation
@insertcopying
@end ifnottex

@c %**start of body
@anchor{index doc}@anchor{0}
@c Indium documentation master file, created by
@c sphinx-quickstart on Tue Apr 4 11:48:03 2017.
@c You can adapt this file completely to your liking, but it should at least
@c contain the root `toctree` directive.

Indium is a JavaScript development environment for Emacs@footnote{http://gnu.org/software/emacs}.

Indium connects to a browser tab or nodejs process and provides several features
for JavaScript development, including:


@itemize *

@item
a REPL (with auto completion) & object inspection;

@item
an inspector, with history and navigation;

@item
a scratch buffer (@code{M-x indium-scratch});

@item
JavaScript evaluation in JS buffers with @code{indium-interaction-mode};

@item
a stepping Debugger, similar to @code{edebug}, or @code{cider}.
@end itemize

This documentation can be read online at @indicateurl{https://indium.readthedocs.io}.

It is also available in Info format and be consulted from within Emacs with
@code{C-h i m indium RET}.

@menu
* Table of contents::
* Indices and tables::

@detailmenu
--- The Detailed Node Listing ---

Table of contents

* Installation::
* Getting up and running::
* The REPL::
* Interaction in JS buffers::
* The stepping debugger::
* The inspector::

Installation

* Using MELPA::
* Manual installation::

Getting up and running

* NodeJS::
* Chrome/Chromium::
* Using local files when debugging::

The REPL

* Starting a REPL::
* Using the REPL::
* Code evaluation & context::

Using the REPL

* Keybindings::
* Reconnecting from the REPL buffer::

Interaction in JS buffers

* Evaluating and inspecting::
* Switching to the REPL buffer::
* Adding and removing breakpoints::

@end detailmenu
@end menu

@node Table of contents,Indices and tables,Top,Top
@anchor{index table-of-contents}@anchor{1}@anchor{index indium}@anchor{2}
@chapter Table of contents


@menu
* Installation::
* Getting up and running::
* The REPL::
* Interaction in JS buffers::
* The stepping debugger::
* The inspector::

@end menu

@node Installation,Getting up and running,,Table of contents
@anchor{installation doc}@anchor{3}@anchor{installation installation}@anchor{4}
@section Installation


Indium supports @code{Emacs 25.1+}, @code{Chrome 54.0+} (debugging protocol @code{v1.2})
and @code{NodeJS 7+}.

Indium is availabe on MELPA@footnote{https://melpa.org}, MELPA Stable@footnote{https://stable.melpa/org}.

@menu
* Using MELPA::
* Manual installation::

@end menu

@node Using MELPA,Manual installation,,Installation
@anchor{installation using-melpa}@anchor{5}
@subsection Using MELPA


Unless you are already using MELPA, you will have to setup @code{package.el} to use
MELPA or MELPA Stable repositories. You can follow this documentation@footnote{https://melpa.org/#/getting-started}.

You can install Indium with the following command:

@example
M-x package-install [RET] indium [RET]
@end example

or by adding this bit of Emacs Lisp code to your Emacs initialization file
(@code{.emacs} or @code{init.el}):

@example
(unless (package-installed-p 'indium)
(package-install 'indium))
@end example

If the installation doesn't work try refreshing the package list:

@example
M-x package-refresh-contents [RET]
@end example

@node Manual installation,,Using MELPA,Installation
@anchor{installation manual-installation}@anchor{6}
@subsection Manual installation


If you want to install Indium manually, make sure to install @code{websocket.el}.
Obtain the code of Indium from the repository@footnote{https://github.com/NicolasPetton/indium}.

Add the following to your Emacs configuration:

@example
;; load Indium from its source code
(add-to-list 'load-path "~/projects/indium")
(require 'indium)
@end example

@node Getting up and running,The REPL,Installation,Table of contents
@anchor{setup doc}@anchor{7}@anchor{setup up-and-running}@anchor{8}@anchor{setup getting-up-and-running}@anchor{9}
@section Getting up and running


@menu
* NodeJS::
* Chrome/Chromium::
* Using local files when debugging::

@end menu

@node NodeJS,Chrome/Chromium,,Getting up and running
@anchor{setup id1}@anchor{a}@anchor{setup nodejs}@anchor{b}
@subsection NodeJS


Nodejs >= @code{7.0} is required for Indium to work.

Start a node process with the @code{--inspect} flag:

@example
node --inspect myfile.js
@end example

If you wish to break on the first line of the application code, start node using:

@example
node --inspect --debug-brk myfile.js
@end example

Node will tell you to open an URL in Chrome:

@example
chrome-devtools://inspector.html?...&ws=127.0.0.1:PORT/PATH
@end example

Evaluate @code{M-x indium-connect-to-nodejs RET 127.0.0.1 RET PORT RET PATH},
@code{PORT} and @code{PATH} are the ones from the @cite{ws} parameter of the above URL.

Connecting Indium to the node process will open a debugger on the first line of
the application code if you passed the CLI argument @code{--debug-brk}.

@node Chrome/Chromium,Using local files when debugging,NodeJS,Getting up and running
@anchor{setup chrome-chromium}@anchor{c}@anchor{setup chrome}@anchor{d}
@subsection Chrome/Chromium


Chrome/Chromium >= @code{54.0} is required for Indium to properly work (debugging
protocol @code{v1.2}).

Start Chrome/Chromium with the @code{--remote-debugging-port} flag like the following:

@example
chromium --remote-debugging-port=9222 https://localhost:3000
@end example

Make sure that no instance of Chrome is already running, otherwise Chrome will
simply open a new tab on the existing Chrome instance, and the
@code{remote-debugging-port} will not be set.

To connect to a tab, run from Emacs:

@example
M-x indium-connect-to-chrome
@end example

@node Using local files when debugging,,Chrome/Chromium,Getting up and running
@anchor{setup local-files}@anchor{e}@anchor{setup using-local-files-when-debugging}@anchor{f}
@subsection Using local files when debugging


Indium can use local files when debugging, or to set breakpoints.

@cartouche
@quotation Hint
When using @code{NodeJS}, or when the connected tab uses the @code{file://}
URL, Indium will by itself use local files from disk. In this case
there is nothing to setup.
@end quotation
@end cartouche

If the Chrome connection uses the @code{http://} or @code{https://} protocol, you will
have to tell Indium where to find the corresponding JavaScript files on disk by
setting up a workspace.

To do that, place an empty @code{.indium} marker file in the root folder where your
@strong{web server serves static files}.

The @code{.indium} file should not always be placed in the directory that contains
your JavaScript files. It has to be in the root folder containing static
files. Most of the time, it is at least one level above.

Given the following project structure:

@example
project/ (current directory)
www/
index.html
css/
style.css
js/
app.js
.indium
@end example

Indium will lookup the file @code{www/js/app.js} for the URL
"@indicateurl{http://localhost:3000/js/app.js}".

@cartouche
@quotation Warning
In order for this setup to work, make sure to call
@code{indium-connect-to-chrome} from somewhere within the workspace
directory!
@end quotation
@end cartouche

@node The REPL,Interaction in JS buffers,Getting up and running,Table of contents
@anchor{repl doc}@anchor{10}@anchor{repl the-repl}@anchor{11}@anchor{repl repl}@anchor{12}
@section The REPL


@menu
* Starting a REPL::
* Using the REPL::
* Code evaluation & context::

@end menu

@node Starting a REPL,Using the REPL,,The REPL
@anchor{repl starting-a-repl}@anchor{13}
@subsection Starting a REPL


A REPL (Read Eval Print Loop) buffer is automatically open when a new Indium
connection is made (see @ref{8,,Getting up and running}).

@image{repl,,,,png}

The REPL offers the following features:


@itemize *

@item
Auto completion with @code{company-mode}

@item
JS syntax highlighting

@item
Pretty printing and preview of printed values

@item
Access to the object inspector
@end itemize

@image{repl2,,,,png}

@node Using the REPL,Code evaluation & context,Starting a REPL,The REPL
@anchor{repl using-the-repl}@anchor{14}
@subsection Using the REPL


@menu
* Keybindings::
* Reconnecting from the REPL buffer::

@end menu

@node Keybindings,Reconnecting from the REPL buffer,,Using the REPL
@anchor{repl keybindings}@anchor{15}
@subsubsection Keybindings


Here is the list of available keybindings in a REPL buffer:


@multitable {xxxxxxxxxxxxxxx} {xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}
@headitem

Keybinding

@tab

Description

@item

@code{RET}

@tab

Evalute the current input. When the point is on a printed object, inspect the object.

@item

@code{C-RET}

@tab

Insert a newline.

@item

@code{C-c M-i}

@tab

Evalute the current input and open an inspector on the result.

@item

@code{C-c C-o}

@tab

Clear the output.

@item

@code{C-c C-q}

@tab

Kill the REPL buffer and close the current connection.

@item

@code{M-n}

@tab

Insert the previous input in the history.

@item

@code{M-p}

@tab

Instert the next input in the history.

@end multitable


@node Reconnecting from the REPL buffer,,Keybindings,Using the REPL
@anchor{repl reconnecting-from-the-repl-buffer}@anchor{16}
@subsubsection Reconnecting from the REPL buffer


When a connection is closed (most probably because other devtools were open on
the same runtime), the REPL will display two buttons, one to try to reopen the
connection, and another one to kill Emacs buffers using this connection (the
REPL buffer, inspectors & debuggers).

@node Code evaluation & context,,Using the REPL,The REPL
@anchor{repl code-evaluation-context}@anchor{17}
@subsection Code evaluation & context


When evaluating code in the REPL, Indium will always run the code on the current
execution context.

This means that while debugging, code execution will happen in the context of
the current stack frame, and will be able to access local variables from the
stack, etc.

@node Interaction in JS buffers,The stepping debugger,The REPL,Table of contents
@anchor{code-evaluation doc}@anchor{18}@anchor{code-evaluation interaction-in-js-buffers}@anchor{19}
@section Interaction in JS buffers


Indium comes with a minor mode called @code{indium-interaction-mode} for interactive
programming. To enable it in all JavaScript buffers, add something
like the following to your Emacs configuration:

@example
(require 'indium)
(add-hook 'js-mode-hook #'indium-interaction-mode)
@end example

When @code{indium-interaction-mode} is on, you can evaluate code, inspect objects and
add or remove breakpoints from your buffers.

@menu
* Evaluating and inspecting::
* Switching to the REPL buffer::
* Adding and removing breakpoints::

@end menu

@node Evaluating and inspecting,Switching to the REPL buffer,,Interaction in JS buffers
@anchor{code-evaluation evaluating-and-inspecting}@anchor{1a}
@subsection Evaluating and inspecting


To evaluate the JavaScript expression preceding the point, press @code{C-x C-e}.

To inspect the result of an expression, press @code{C-c M-i} (see @ref{1b,,The inspector}).

The entire buffer can be evaluating with @code{M-x indium-eval-buffer}.

@node Switching to the REPL buffer,Adding and removing breakpoints,Evaluating and inspecting,Interaction in JS buffers
@anchor{code-evaluation switching-to-the-repl-buffer}@anchor{1c}
@subsection Switching to the REPL buffer


Press @code{C-c C-z} from any buffer with @code{indium-interaction-mode} turned on to
switch back to the REPL buffer (see @ref{12,,The REPL}).

@node Adding and removing breakpoints,,Switching to the REPL buffer,Interaction in JS buffers
@anchor{code-evaluation adding-and-removing-breakpoints}@anchor{1d}
@subsection Adding and removing breakpoints


You need to first make sure that Indium is set up correctly to use local files
(see @ref{e,,Using local files when debugging}).


@itemize -

@item
@code{C-c b b}: Toggle a breakpoint

@item
@code{C-u C-c b b}: Toggle a breakpoint with condition

@item
@code{C-c b K}: Remove all breakpoints from the current buffer
@end itemize

Once a breakpoint is set, execution will stop when a breakpoint is hit, and the
Indium debugger pop up (see @ref{1e,,The stepping debugger}).

@cartouche
@quotation Note
Breakpoints are persistent: if the connection is closed, when a new
connection is made Indium will attempt to add back all breakpoints.
@end quotation
@end cartouche

@cartouche
@quotation Warning
When modifying JavaScript buffers, it is up to the user to update
the browser tab. Indium will attempt to update breakpoint locations
when saving a buffer, but the runtime script contents won't be
updated automatically. You can either refresh the page or evaluate
@code{indium-reload}.
@end quotation
@end cartouche

@node The stepping debugger,The inspector,Interaction in JS buffers,Table of contents
@anchor{debugger doc}@anchor{1f}@anchor{debugger the-stepping-debugger}@anchor{20}@anchor{debugger debugger}@anchor{1e}
@section The stepping debugger


@node The inspector,,The stepping debugger,Table of contents
@anchor{inspector doc}@anchor{21}@anchor{inspector the-inspector}@anchor{22}@anchor{inspector inspector}@anchor{1b}
@section The inspector


@node Indices and tables,,Table of contents,Top
@anchor{index indices-and-tables}@anchor{23}
@chapter Indices and tables



@itemize *

@item
genindex

@item
modindex

@item
search
@end itemize

@c %**end of body
@bye

+ 0
- 392
doc/Jade.texi View File

@@ -1,392 +0,0 @@
\input texinfo @c -*-texinfo-*-
@c %**start of header
@setfilename Jade.info
@documentencoding UTF-8
@ifinfo
@*Generated by Sphinx 1.5.5.@*
@end ifinfo
@settitle Jade Documentation
@defindex ge
@paragraphindent 0
@exampleindent 4
@finalout
@dircategory Emacs
@direntry
* Jade: (Jade.info). JavaScript development environment for Emacs.
@end direntry

@definfoenclose strong,`,'
@definfoenclose emph,`,'
@c %**end of header

@copying
@quotation
Jade 0.3.3, Apr 06, 2017

Nicolas Petton

Copyright @copyright{} 2017, Nicolas Petton
@end quotation

@end copying

@titlepage
@title Jade Documentation
@insertcopying
@end titlepage
@contents

@c %** start of user preamble

@c %** end of user preamble

@ifnottex
@node Top
@top Jade Documentation
@insertcopying
@end ifnottex

@c %**start of body
@anchor{index doc}@anchor{0}
@c Jade documentation master file, created by
@c sphinx-quickstart on Tue Apr 4 11:48:03 2017.
@c You can adapt this file completely to your liking, but it should at least
@c contain the root `toctree` directive.

Jade is a JavaScript development environment for Emacs@footnote{http://gnu.org/software/emacs}.

Jade connects to a browser tab or nodejs process and provides several features
for JavaScript development, including:


@itemize *

@item
a REPL (with auto completion) & object inspection;

@item
an inspector, with history and navigation;

@item
a scratch buffer (@code{M-x jade-scratch});

@item
JavaScript evaluation in JS buffers with @code{jade-interaction-mode};

@item
a stepping Debugger, similar to @code{edebug}, or @code{cider}.
@end itemize

@menu
* Table of contents::
* Indices and tables::

@detailmenu
--- The Detailed Node Listing ---

Table of contents

* Installation::
* Getting up and running::
* Interaction in JS buffers::

Installation

* Using MELPA::
* Manual installation::

Getting up and running

* NodeJS::
* Chrome/Chromium::
* Using local files when debugging::

Interaction in JS buffers

* Evaluating and inspecting::
* Switching to the REPL buffer::
* Adding and removing breakpoints::

@end detailmenu
@end menu

@node Table of contents,Indices and tables,Top,Top
@anchor{index welcome-to-jade-s-documentation}@anchor{1}@anchor{index table-of-contents}@anchor{2}
@chapter Table of contents


@menu
* Installation::
* Getting up and running::
* Interaction in JS buffers::

@end menu

@node Installation,Getting up and running,,Table of contents
@anchor{installation installation}@anchor{3}@anchor{installation doc}@anchor{4}
@section Installation


Jade supports @code{Emacs 25.1+}, @code{Chrome 54.0+} (debugging protocol @code{v1.2})
and @code{NodeJS 7+}.

Jade is availabe on MELPA@footnote{https://melpa.org}, MELPA Stable@footnote{https://stable.melpa/org}.

@menu
* Using MELPA::
* Manual installation::

@end menu

@node Using MELPA,Manual installation,,Installation
@anchor{installation using-melpa}@anchor{5}
@subsection Using MELPA


Unless you are already using MELPA, you will have to setup @code{package.el} to use
MELPA or MELPA Stable repositories. You can follow this documentation@footnote{https://melpa.org/#/getting-started}.

You can install Jade with the following command:

@example
M-x package-install [RET] jade [RET]
@end example

or by adding this bit of Emacs Lisp code to your Emacs initialization file
(@code{.emacs} or @code{init.el}):

@example
(unless (package-installed-p 'jade)
(package-install 'jade))
@end example

If the installation doesn't work try refreshing the package list:

@example
M-x package-refresh-contents [RET]
@end example

@node Manual installation,,Using MELPA,Installation
@anchor{installation manual-installation}@anchor{6}
@subsection Manual installation


If you want to install Jade manually, make sure to install @code{websocket.el}.
Obtain the code of Jade from the repository@footnote{https://github.com/NicolasPetton/jade}.

Add the following to your Emacs configuration:

@example
;; load Jade from its source code
(add-to-list 'load-path "~/projects/jade")
(require 'jade)
@end example

@node Getting up and running,Interaction in JS buffers,Installation,Table of contents
@anchor{setup doc}@anchor{7}@anchor{setup getting-up-and-running}@anchor{8}@anchor{setup up-and-running}@anchor{9}
@section Getting up and running


@menu
* NodeJS::
* Chrome/Chromium::
* Using local files when debugging::

@end menu

@node NodeJS,Chrome/Chromium,,Getting up and running
@anchor{setup id1}@anchor{a}@anchor{setup nodejs}@anchor{b}
@subsection NodeJS


Nodejs >= @code{7.0} is required for Jade to work.

Start a node process with the @code{--inspect} flag:

@example
node --inspect myfile.js
@end example

If you wish to break on the first line of the application code, start node using:

@example
node --inspect --debug-brk myfile.js
@end example

Node will tell you to open an URL in Chrome:

@example
chrome-devtools://inspector.html?...&ws=127.0.0.1:PORT/PATH
@end example

Evaluate @code{M-x jade-connect-to-nodejs RET 127.0.0.1 RET PORT RET PATH},
@code{PORT} and @code{PATH} are the ones from the @cite{ws} parameter of the above URL.

Connecting Jade to the node process will open a debugger on the first line of
the application code if you passed the CLI argument @code{--debug-brk}.

@node Chrome/Chromium,Using local files when debugging,NodeJS,Getting up and running
@anchor{setup chrome}@anchor{c}@anchor{setup chrome-chromium}@anchor{d}
@subsection Chrome/Chromium


Chrome/Chromium >= @code{54.0} is required for Jade to properly work (debugging
protocol @code{v1.2}).

Start Chrome/Chromium with the @code{--remote-debugging-port} flag like the following:

@example
chromium --remote-debugging-port=9222 https://localhost:3000
@end example

Make sure that no instance of Chrome is already running, otherwise Chrome will
simply open a new tab on the existing Chrome instance, and the
@code{remote-debugging-port} will not be set.

To connect to a tab, run from Emacs:

@example
M-x jade-connect-to-chrome
@end example

@node Using local files when debugging,,Chrome/Chromium,Getting up and running
@anchor{setup local-files}@anchor{e}@anchor{setup using-local-files-when-debugging}@anchor{f}
@subsection Using local files when debugging


Jade can use local files when debugging, or to set breakpoints.

@cartouche
@quotation Hint
When using @code{NodeJS}, or when the connected tab uses the @code{file://}
URL, Jade will by itself use local files from disk. In this case
there is nothing to setup.
@end quotation
@end cartouche

If the Chrome connection uses the @code{http://} or @code{https://} protocol, you will
have to tell Jade where to find the corresponding JavaScript files on disk by
setting up a workspace.

To do that, place an empty @code{.jade} marker file in the root folder where your
@strong{web server serves static files}.

The @code{.jade} file should not always be placed in the directory that contains
your JavaScript files. It has to be in the root folder containing static
files. Most of the time, it is at least one level above.

Given the following project structure:

@example
project/ (current directory)
www/
index.html
css/
style.css
js/
app.js
.jade
@end example

Jade will lookup the file @code{www/js/app.js} for the URL
"@indicateurl{http://localhost:3000/js/app.js}".

@cartouche
@quotation Danger
In order for this setup to work, make sure to call
@code{jade-connect-to-chrome} from somewhere within the workspace
directory!
@end quotation
@end cartouche

@node Interaction in JS buffers,,Getting up and running,Table of contents
@anchor{code-evaluation doc}@anchor{10}@anchor{code-evaluation interaction-in-js-buffers}@anchor{11}
@section Interaction in JS buffers


Jade comes with a minor mode called @code{jade-interaction-mode} for interactive
programming. To enable it in all JavaScript buffers, add something
like the following to your Emacs configuration:

@example
(require 'jade)
(add-hook 'js-mode-hook #'jade-interaction-mode)
@end example

When @code{jade-interaction-mode} is on, you can evaluate code, inspect objects and
add or remove breakpoints from your buffers.

@menu
* Evaluating and inspecting::
* Switching to the REPL buffer::
* Adding and removing breakpoints::

@end menu

@node Evaluating and inspecting,Switching to the REPL buffer,,Interaction in JS buffers
@anchor{code-evaluation evaluating-and-inspecting}@anchor{12}
@subsection Evaluating and inspecting


To evaluate the JavaScript expression preceding the point, press @code{C-x C-e}.

To inspect the result of an expression, press @code{C-x M-i}.

The entire buffer can be evaluating with @code{M-x jade-eval-buffer}.

@node Switching to the REPL buffer,Adding and removing breakpoints,Evaluating and inspecting,Interaction in JS buffers
@anchor{code-evaluation switching-to-the-repl-buffer}@anchor{13}
@subsection Switching to the REPL buffer


Press @code{C-c C-z} from any buffer with @code{jade-interaction-mode} turned on to
switch back to the REPL buffer.

@node Adding and removing breakpoints,,Switching to the REPL buffer,Interaction in JS buffers
@anchor{code-evaluation adding-and-removing-breakpoints}@anchor{14}
@subsection Adding and removing breakpoints


You need to first make sure that Jade is set up correctly to use local files
(see @ref{e,,Using local files when debugging}).


@itemize -

@item
@code{C-c b b}: Toggle a breakpoint

@item
@code{C-u C-c b b}: Toggle a breakpoint with condition

@item
@code{C-c b K}: Remove all breakpoints from the current buffer
@end itemize

@cartouche
@quotation Note
Breakpoints are persistent: if the connection is closed, when a new
connection is made Jade will attempt to add back all breakpoints.
@end quotation
@end cartouche

@node Indices and tables,,Table of contents,Top
@anchor{index indices-and-tables}@anchor{15}
@chapter Indices and tables



@itemize *

@item
genindex

@item
modindex

@item
search
@end itemize

@c %**end of body
@bye

BIN
doc/repl.png View File

Before After
Width: 739  |  Height: 336  |  Size: 24KB

BIN
doc/repl2.png View File

Before After
Width: 736  |  Height: 215  |  Size: 19KB

BIN
img/indium.png View File

Before After
Width: 128  |  Height: 128  |  Size: 1.1KB

+ 89
- 0
img/inlium.svg View File

@@ -0,0 +1,89 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->

<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="256px"
height="256px"
viewBox="0 0 256 256"
version="1.1"
id="SVGRoot"
inkscape:version="0.92.1 r"
sodipodi:docname="inlium.svg"
inkscape:export-filename="/home/nico/indium.png"
inkscape:export-xdpi="245.07495"
inkscape:export-ydpi="245.07495">
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1.63"
inkscape:cx="235.15359"
inkscape:cy="98.37298"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1315"
inkscape:window-height="713"
inkscape:window-x="51"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:grid-bbox="true" />
<defs
id="defs4485" />
<metadata
id="metadata4488">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:groupmode="layer"
inkscape:label="Layer 1">
<rect
style="fill:#ff6a5e;fill-opacity:1;stroke:#cb595f;stroke-width:7.55905533;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect5044"
width="193"
height="193"
x="31.5"
y="31.5"
ry="0" />
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="69.46875"
y="191.884"
id="text5048"><tspan
sodipodi:role="line"
id="tspan5046"
x="69.46875"
y="191.884"
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:133.33332825px;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans Bold';fill:#ffffff;fill-opacity:1">In</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="113.49693"
y="62.134968"
id="text5071"><tspan
sodipodi:role="line"
id="tspan5069"
x="113.49693"
y="97.525589" /></text>
</g>
</svg>

jade-backend.el → indium-backend.el View File

@@ -1,4 +1,4 @@
;;; jade-backend.el --- Backend for jade.el -*- lexical-binding: t; -*-
;;; indium-backend.el --- Backend for indium.el -*- lexical-binding: t; -*-

;; Copyright (C) 2016-2017 Nicolas Petton

@@ -22,81 +22,81 @@

;; Generic backend implementation.

;; Backends should define a new backend symbol using `jade-register-backend',
;; Backends should define a new backend symbol using `indium-register-backend',

;;; Code:

(require 'map)
(require 'seq)
(require 'jade-repl)
(require 'jade-debugger-litable)
(require 'indium-repl)
(require 'indium-debugger-litable)

(declare 'jade-debugger-unset-current-buffer)
(declare 'indium-debugger-unset-current-buffer)

(defvar jade-connection nil
(defvar indium-connection nil
"Current connection to the browser tab.

A connection should be an alist with the following required keys:
`backend' and `url'. Other backend-specific keys might be used
by backends.")

(defvar jade-backends nil "List of registered backends.")
(defvar indium-backends nil "List of registered backends.")

(defun jade-backend ()
(defun indium-backend ()
"Return the backend for the current connection."
(map-elt jade-connection 'backend))
(map-elt indium-connection 'backend))

(defun jade-register-backend (backend)
(defun indium-register-backend (backend)
"Register a new BACKEND.
BACKEND should be a symbol."
(add-to-list 'jade-backends backend))
(add-to-list 'indium-backends backend))

(defun jade-quit ()
(defun indium-quit ()
"Close the current connection and kill its REPL buffer if any.
When called interactively, prompt for a confirmation first."
(interactive)
(unless jade-connection
(unless indium-connection
(user-error "No active connection to close"))
(when (or (not (called-interactively-p 'interactive))
(y-or-n-p (format "Do you really want to close the connection to %s ? "
(map-elt jade-connection 'url))))
(jade-backend-close-connection (jade-backend))
(jade-backend-cleanup-buffers)
(setq jade-connection nil)))
(map-elt indium-connection 'url))))
(indium-backend-close-connection (indium-backend))
(indium-backend-cleanup-buffers)
(setq indium-connection nil)))

(defun jade-reconnect ()
(defun indium-reconnect ()
"Try to re-establish a connection.
The new connection is based on the current (usually closed) one."
(interactive)
(unless jade-connection
(user-error "No Jade connection to reconnect to"))
(jade-backend-reconnect (jade-backend)))
(unless indium-connection
(user-error "No Indium connection to reconnect to"))
(indium-backend-reconnect (indium-backend)))

(defun jade-backend-cleanup-buffers ()
"Cleanup all Jade buffers."
(defun indium-backend-cleanup-buffers ()
"Cleanup all Indium buffers."
(seq-map (lambda (buf)
(with-current-buffer buf
(when buffer-file-name
(jade-debugger-unset-current-buffer))))
(indium-debugger-unset-current-buffer))))
(buffer-list))
(when-let ((buf (jade-repl-get-buffer)))
(when-let ((buf (indium-repl-get-buffer)))
(kill-buffer buf)))

;;; jade-connection methods
;;; indium-connection methods

(cl-defgeneric jade-backend-active-connection-p (backend)
(cl-defgeneric indium-backend-active-connection-p (backend)
"Return non-nil if the current connection is active."
t)

(cl-defgeneric jade-backend-close-connection (backend)
(cl-defgeneric indium-backend-close-connection (backend)
"Close the current connection.")

(cl-defgeneric jade-backend-reconnect (backend)
(cl-defgeneric indium-backend-reconnect (backend)
"Try to re-establish a connection.
The new connection is created based on the current
`jade-connection'.")
`indium-connection'.")

(cl-defgeneric jade-backend-evaluate (backend string &optional callback)
(cl-defgeneric indium-backend-evaluate (backend string &optional callback)
"Evaluate STRING then call CALLBACK.
CALLBACK is called with two arguments, the value returned by the
evaluation and non-nil if the evaluation threw an error.
@@ -106,41 +106,41 @@ The value should be an alist with a the following required keys:
remote object that can be inspected, it should also have an
`objectid' key.")

(cl-defgeneric jade-backend-get-completions (backend expression prefix callback)
(cl-defgeneric indium-backend-get-completions (backend expression prefix callback)
"Get the completion for EXPRESSION that match PREFIX.
Evaluate CALLBACK on the filtered candidates.

EXPRESSION should be a valid JavaScript expression string.")

(cl-defgeneric jade-backend-add-breakpoint (backend file line &optional callback condition)
(cl-defgeneric indium-backend-add-breakpoint (backend file line &optional callback condition)
"Request the addition of a breakpoint.

The breakpoint is addet to FILE on line LINE. When CALLBACK is
non-nil, evaluate it with the breakpoint's location and id.")

(cl-defgeneric jade-backend-remove-breakpoint (backend id)
(cl-defgeneric indium-backend-remove-breakpoint (backend id)
"Request the removal of the breakpoint with id ID.")

(cl-defgeneric jade-backend-get-breakpoints (backend)
(cl-defgeneric indium-backend-get-breakpoints (backend)
"Return all breakpoints.
A breakpoint is a map with the keys `id', `file', and `line'.")

(defun jade-backend-remove-all-breakpoints-from-buffer (buffer)
(defun indium-backend-remove-all-breakpoints-from-buffer (buffer)
"Remove all breakpoints from BUFFER."
(with-current-buffer buffer
(seq-do (lambda (brk)
(jade-backend-remove-breakpoint (jade-backend)
(indium-backend-remove-breakpoint (indium-backend)
(map-elt brk 'id)))
(jade-backend-get-breakpoints-in-file buffer-file-name))))
(indium-backend-get-breakpoints-in-file buffer-file-name))))

(defun jade-backend-get-breakpoints-in-file (file)
(defun indium-backend-get-breakpoints-in-file (file)
"Return all breakpoints in FILE."
(let ((breakpoints (jade-backend-get-breakpoints (jade-backend))))
(let ((breakpoints (indium-backend-get-breakpoints (indium-backend))))
(seq-filter (lambda (brk)
(string= (map-elt brk 'file) file))
breakpoints)))

(cl-defgeneric jade-backend-get-properties (backend reference &optional callback all-properties)
(cl-defgeneric indium-backend-get-properties (backend reference &optional callback all-properties)
"Request the properties of the remote object represented by REFERENCE.
REFERENCE must be the id of a remote object.
CALLBACK is called with the fetched list of properties.
@@ -148,32 +148,32 @@ CALLBACK is called with the fetched list of properties.
If ALL-PROPERTIES is non-nil, get all the properties from the
prototype chain of the remote object.")

(cl-defgeneric jade-backend-get-script-source (backend frame callback)
(cl-defgeneric indium-backend-get-script-source (backend frame callback)
"Get the source of the script for FRAME.
Evaluate CALLBACK with the result.")

(cl-defgeneric jade-backend-get-script-url (backend frame)
(cl-defgeneric indium-backend-get-script-url (backend frame)
"Return the url of the script for FRAME, or nil.")

(cl-defgeneric jade-backend-resume (backend &optional callback)
(cl-defgeneric indium-backend-resume (backend &optional callback)
"Resume the debugger and evaluate CALLBACK if non-nil.")

(cl-defgeneric jade-backend-step-into (backend &optional callback)
(cl-defgeneric indium-backend-step-into (backend &optional callback)
"Step into the current stack frame and evaluate CALLBACK if non-nil.")

(cl-defgeneric jade-backend-step-out (backend &optional callback)
(cl-defgeneric indium-backend-step-out (backend &optional callback)
"Step out the current stack frame and evaluate CALLBACK if non-nil.")

(cl-defgeneric jade-backend-step-over (backend &optional callback)
(cl-defgeneric indium-backend-step-over (backend &optional callback)
"Step over the current stack frame and evaluate CALLBACK if non-nil.")

(cl-defgeneric jade-backend-continue-to-location (backend location &optional callback)
(cl-defgeneric indium-backend-continue-to-location (backend location &optional callback)
"Continue to LOCATION and evaluate CALLBACK if non-nil.
Location should be an alist with a `column' and `row' key.")

(defun jade-backend-object-reference-p (value)
(defun indium-backend-object-reference-p (value)
"Return non-nil if VALUE is a reference to a remote object."
(map-elt value 'objectid))

(provide 'jade-backend)
;;; jade-backend.el ends here
(provide 'indium-backend)
;;; indium-backend.el ends here

jade-breakpoint.el → indium-breakpoint.el View File

@@ -1,4 +1,4 @@
;;; jade-breakpoint.el --- Add/remove breakpoints -*- lexical-binding: t; -*-
;;; indium-breakpoint.el --- Add/remove breakpoints -*- lexical-binding: t; -*-

;; Copyright (C) 2017 Nicolas Petton

@@ -21,71 +21,71 @@

;; Add and remove breakpoints to a buffer.
;;
;; Breakpoints are added even if Jade is not connected. In such case, Jade will
;; Breakpoints are added even if Indium is not connected. In such case, Indium will
;; attempt to put all breakpoints when a connection is made.

;; Add or remove breakpoints from buffers.

;;; Code:

(require 'jade-backend)
(require 'jade-faces)
(require 'indium-backend)
(require 'indium-faces)

(defun jade-breakpoint-add (&optional condition)
(defun indium-breakpoint-add (&optional condition)
"Add a breakpoint at point.

When CONDITION is non-nil, the breakpoint will be hit when
CONDITION is true."
(let ((ov (jade-breakpoint--put-icon condition)))
(when jade-connection
(jade-backend-add-breakpoint (jade-backend)
(let ((ov (indium-breakpoint--put-icon condition)))
(when indium-connection
(indium-backend-add-breakpoint (indium-backend)
buffer-file-name
(1- (line-number-at-pos))
(lambda (line id condition)
(jade-breakpoint-added id ov))
(indium-breakpoint-added id ov))
condition))))

(defun jade-breakpoint-remove ()
(defun indium-breakpoint-remove ()
"Remove the breakpoint from the current line."
(if-let ((id (jade-breakpoint-id-at-point)))
(when jade-connection
(jade-backend-remove-breakpoint (jade-backend) id)))
(jade-breakpoint--remove-icon))
(if-let ((id (indium-breakpoint-id-at-point)))
(when indium-connection
(indium-backend-remove-breakpoint (indium-backend) id)))
(indium-breakpoint--remove-icon))

(defun jade-breakpoint-remove-all ()
(defun indium-breakpoint-remove-all ()
"Remove all breakpoints from the current buffer's file."
(jade-breakpoint-remove-breakpoints-from-buffer)
(jade-backend-remove-all-breakpoints-from-buffer (current-buffer)))
(indium-breakpoint-remove-breakpoints-from-buffer)
(indium-backend-remove-all-breakpoints-from-buffer (current-buffer)))

(defun jade-breakpoint-add-breakpoints-to-buffer ()
(defun indium-breakpoint-add-breakpoints-to-buffer ()
"Add all breakpoints markers to the current buffer.
This function does not add breakpoints."
(seq-do (lambda (brk)
(save-excursion
(goto-line (1+ (map-elt brk 'line)))
(let ((ov (jade-breakpoint--put-icon)))
(jade-breakpoint-added (map-elt brk 'id) ov))))
(jade-backend-get-breakpoints-in-file buffer-file-name)))
(let ((ov (indium-breakpoint--put-icon)))
(indium-breakpoint-added (map-elt brk 'id) ov))))
(indium-backend-get-breakpoints-in-file buffer-file-name)))

(defun jade-breakpoint-remove-breakpoints-from-buffer ()
(defun indium-breakpoint-remove-breakpoints-from-buffer ()
"Remove all breakpoint markers from the current buffer.
This function does no unset breakpoints,"
(remove-overlays (point-min)
(point-max)
'jade-breakpoint
'indium-breakpoint
t))

(defun jade-breakpoint-added (id overlay)
(defun indium-breakpoint-added (id overlay)
"Add the breakpoint ID to OVERLAY."
(jade-breakpoint--put-id id overlay))
(indium-breakpoint--put-id id overlay))

(defun jade-breakpoint-update-breakpoints ()
(defun indium-breakpoint-update-breakpoints ()
"Update all breakpoints for the current buffer in the backend."
(when jade-connection
(jade-backend-remove-all-breakpoints-from-buffer (current-buffer))
(jade-breakpoint-restore-breakpoints)))
(when indium-connection
(indium-backend-remove-all-breakpoints-from-buffer (current-buffer))
(indium-breakpoint-restore-breakpoints)))

(defun jade-breakpoint-restore-breakpoints ()
(defun indium-breakpoint-restore-breakpoints ()
"Restore all breakpoints set to all buffers.
This function is used when reconnecting to a new connection."
(seq-doseq (buf (buffer-list))
@@ -93,13 +93,13 @@ This function is used when reconnecting to a new connection."
(save-excursion
(let ((overlays (overlays-in (point-min) (point-max))))
(seq-doseq (ov overlays)
(when (overlay-get ov 'jade-breakpoint)
(let ((condition (overlay-get ov 'jade-breakpoint-condition))
(when (overlay-get ov 'indium-breakpoint)
(let ((condition (overlay-get ov 'indium-breakpoint-condition))
(start (overlay-start ov)))
(goto-char start)
(jade-breakpoint-add condition)))))))))
(indium-breakpoint-add condition)))))))))

(defun jade-breakpoint--put-icon (&optional condition)
(defun indium-breakpoint--put-icon (&optional condition)
"Add a breakpoint icon on the current line.
The icon is added to the left fringe.

@@ -108,50 +108,50 @@ Return the overlay."
(let ((ov (make-overlay (point-at-bol) (point-at-eol))))
(overlay-put ov
'before-string
(jade-breakpoint--fringe-icon))
(indium-breakpoint--fringe-icon))
(overlay-put ov
'jade-breakpoint
'indium-breakpoint
t)
(when condition
(overlay-put ov
'jade-breakpoint-condition
'indium-breakpoint-condition
condition))
ov))

(defun jade-breakpoint--put-id (id overlay)
(defun indium-breakpoint--put-id (id overlay)
"Put the ID of the breakpoint to OVERLAY."
(overlay-put overlay
'jade-breakpoint-id
'indium-breakpoint-id
id))

(defun jade-breakpoint--remove-icon ()
(defun indium-breakpoint--remove-icon ()
"Remove the breakpoint icon from the current line."
(remove-overlays (point-at-bol)
(point-at-eol)
'jade-breakpoint
'indium-breakpoint
t))

(defun jade-breakpoint--fringe-icon ()
(defun indium-breakpoint--fringe-icon ()
"Return the fringe icon used for breakpoints."
(propertize "b" 'display
(list 'left-fringe 'jade-breakpoint 'jade-breakpoint-face)))
(list 'left-fringe 'indium-breakpoint 'indium-breakpoint-face)))

(defun jade-breakpoint-id-at-point ()
(defun indium-breakpoint-id-at-point ()
"Return the id of the breakpoint on the current line.
If there is no breakpoint set on the line, return nil."
(seq-some (lambda (ov)
(overlay-get ov 'jade-breakpoint-id))
(overlay-get ov 'indium-breakpoint-id))
(overlays-at (point))))

(defun jade-breakpoint-on-current-line-p ()
(defun indium-breakpoint-on-current-line-p ()
"Return non-nil if there is a breakpoint on the current line."
(seq-some (lambda (ov)
(overlay-get ov 'jade-breakpoint))
(overlay-get ov 'indium-breakpoint))
(overlays-at (point))))

(and (display-images-p)
(define-fringe-bitmap 'jade-breakpoint
(define-fringe-bitmap 'indium-breakpoint
"\x3c\x7e\xff\xff\xff\xff\x7e\x3c"))

(provide 'jade-breakpoint)
;;; jade-breakpoint.el ends here
(provide 'indium-breakpoint)
;;; indium-breakpoint.el ends here

jade-chrome.el → indium-chrome.el View File

@@ -1,4 +1,4 @@
;;; jade-chrome.el --- Chrom{e|ium} support for jade -*- lexical-binding: t; -*-
;;; indium-chrome.el --- Chrom{e|ium} support for indium -*- lexical-binding: t; -*-

;; Copyright (C) 2016-2017 Nicolas Petton

@@ -20,9 +20,9 @@

;;; Commentary:

;; Handle jade connections to Chrom{e|ium} using the webkit backend.
;; Handle indium connections to Chrom{e|ium} using the webkit backend.
;;
;; To open a Jade connection, enable chromium/chrome remote debugging:
;; To open a Indium connection, enable chromium/chrome remote debugging:
;;
;; chromium --remote-debugging-port=9222 https://gnu.org

@@ -33,73 +33,73 @@
(require 'map)
(require 'seq)

(require 'jade-webkit)
(require 'indium-webkit)

(defgroup jade-chrome nil
(defgroup indium-chrome nil
"Chrome interaction."
:prefix "jade-chrome-"
:group 'jade)
:prefix "indium-chrome-"
:group 'indium)

(defcustom jade-chrome-executable
(defcustom indium-chrome-executable
"chromium"
"Chrome executable."
:type '(file))

(defcustom jade-chrome-port
(defcustom indium-chrome-port
9222
"Chrome remote debugger port."
:type '(integer))

(defun jade-run-chrome (url)
(defun indium-run-chrome (url)
"Start chrome/chromium with remote debugging enabled.
Open URL if provided."
(interactive "sUrl: ")
(make-process :name "*jade-chromium*"
:command (list (jade-chrome--find-executable)
(format "--remote-debugging-port=%s" jade-chrome-port)
(make-process :name "*indium-chromium*"
:command (list (indium-chrome--find-executable)
(format "--remote-debugging-port=%s" indium-chrome-port)
(or url "")))
(message "Connecting to Chrome instance...")
(jade-chrome--try-connect "127.0.0.1" 10))
(indium-chrome--try-connect "127.0.0.1" 10))

(defun jade-chrome--find-executable ()
"Find chrome executable using `jade-chrome-executable'."
(let ((executable (executable-find jade-chrome-executable)))
(defun indium-chrome--find-executable ()
"Find chrome executable using `indium-chrome-executable'."
(let ((executable (executable-find indium-chrome-executable)))
(unless executable
(user-error "Cannot find chrome/chromium binary (%s) in PATH" jade-chrome-executable))
(user-error "Cannot find chrome/chromium binary (%s) in PATH" indium-chrome-executable))
executable))


(defun jade-chrome--try-connect (host num-tries)
(defun indium-chrome--try-connect (host num-tries)
"Try to connect to chrome on HOST.
Try a maximum of NUM-TRIES."
(message "Trying to connect to the Chrome instance...")
(sleep-for 1)
(jade-chrome--get-tabs-data host
jade-chrome-port
(indium-chrome--get-tabs-data host
indium-chrome-port
(lambda (tabs)
(if tabs
(jade-chrome--connect-to-tab tabs)
(jade-chrome--try-connect host (1- num-tries))))))
(indium-chrome--connect-to-tab tabs)
(indium-chrome--try-connect host (1- num-tries))))))

(defun jade-connect-to-chrome ()
(defun indium-connect-to-chrome ()
"Open a connection to a webkit tab."
(interactive)
(when (or (null jade-connection) (yes-or-no-p "Close the current Jade connection? "))
(when jade-connection
(jade-quit))
(when (or (null indium-connection) (yes-or-no-p "Close the current Indium connection? "))
(when indium-connection
(indium-quit))
(let ((host (read-from-minibuffer "Host: " "127.0.0.1"))
(port (read-from-minibuffer "Port: " (number-to-string jade-chrome-port))))
(jade-chrome--get-tabs-data host port #'jade-chrome--connect-to-tab))))
(port (read-from-minibuffer "Port: " (number-to-string indium-chrome-port))))
(indium-chrome--get-tabs-data host port #'indium-chrome--connect-to-tab))))

(defun jade-chrome--get-tabs-data (host port callback)
(defun indium-chrome--get-tabs-data (host port callback)
"Get the list of open tabs on HOST:PORT and evaluate CALLBACK with it."
(url-retrieve (format "http://%s:%s/json" host port)
(lambda (status)
(funcall callback (if (eq :error (car status))
nil
(jade-chrome--read-tab-data))))))
(indium-chrome--read-tab-data))))))

(defun jade-chrome--connect-to-tab (tabs)
(defun indium-chrome--connect-to-tab (tabs)
"Ask the user for a tab in the list TABS and connects to it."
(unless tabs
(error "No Chrome tab found. Is Chrome running with the `--remote-debugging-port' flag set?"))
@@ -111,9 +111,9 @@ Try a maximum of NUM-TRIES."
(string= (map-elt tab 'url) url))
tabs))
(websocket-url (map-elt tab 'webSocketDebuggerUrl)))
(jade-webkit--open-ws-connection url websocket-url)))
(indium-webkit--open-ws-connection url websocket-url)))

(defun jade-chrome--read-tab-data ()
(defun indium-chrome--read-tab-data ()
"Return the JSON tabs data in the current buffer."
(when (save-match-data
(looking-at "^HTTP/1\\.1 200 OK$"))
@@ -122,5 +122,5 @@ Try a maximum of NUM-TRIES."
(delete-region (point-min) (point))
(json-read)))

(provide 'jade-chrome)
;;; jade-chrome.el ends here
(provide 'indium-chrome)
;;; indium-chrome.el ends here

+ 135
- 0
indium-debugger-frames.el View File

@@ -0,0 +1,135 @@
;;; indium-debugger-frames.el --- List the stack frame -*- lexical-binding: t; -*-

;; Copyright (C) 2017 Nicolas Petton

;; Author: Nicolas Petton <nicolas@petton.fr>

;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.

;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.

;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.

;;; Commentary:

;;

;;; Code:

(require 'indium-render)

(declare 'indium-debugger-frames)
(declare 'indium-debugger-current-frame)
(declare 'indium-debugger-select-frame)

(defun indium-debugger-stack-frames ()
"List the stack frames in a separate buffer and switch to it."
(interactive)
(let ((buf (indium-debugger-frames-get-buffer-create))
(frames (indium-debugger-frames))
(current-frame (indium-debugger-current-frame))
(inhibit-read-only t))
(with-current-buffer buf
(indium-debugger-frames-list frames current-frame))
(switch-to-buffer buf)))

(defun indium-debugger-frames-maybe-refresh ()
"When a buffer listing the stack frames is open, refresh it."
(interactive)
(let ((buf (indium-debugger-frames-get-buffer))
(frames (indium-debugger-frames))
(current-frame (indium-debugger-current-frame))
(inhibit-read-only t))
(when buf
(with-current-buffer buf
(indium-debugger-frames-list frames current-frame)))))

(defun indium-debugger-frames-list (frames &optional current-frame)
"Render the list of stack frames FRAMES.
CURRENT-FRAME is the current stack frame in the debugger."
(save-excursion
(erase-buffer)
(indium-render-header "Debugger stack")
(newline 2)
(seq-doseq (frame frames)
(indium-render-frame frame
(indium-backend-get-script-url (indium-backend) frame)
(eq current-frame frame))
(newline))))

(defun indium-debugger-frames-select-frame (frame)
"Select FRAME and switch to the corresponding debugger buffer."
(interactive)
(indium-debugger-select-frame frame))

(defun indium-debugger-frames-next-frame ()
"Go to the next frame in the stack."
(interactive)
(indium-debugger-frames-goto-next 'next))

(defun indium-debugger-frames-previous-frame ()
"Go to the previos frame in the stack."
(interactive)
(indium-debugger-frames-goto-next 'previous))

(defun indium-debugger-frames-goto-next (direction)
"Go to the next frame in DIRECTION."
(let ((next (eq direction 'next)))
(forward-line (if next 1 -1))
(back-to-indentation)
(while (and (not (if next
(eobp)
(bobp)))
(not (get-text-property (point) 'indium-action)))
(forward-char (if next 1 -1)))))

(defun indium-debugger-frames-get-buffer ()
"Return the buffer listing frames for the current connection.
If no buffer is found, return nil."
(get-buffer (indium-debugger-frames-buffer-name)))

(defun indium-debugger-frames-buffer-name ()
"Return the name of the frames buffer for the current connection."
"*JS Frames*")

(defun indium-debugger-frames-get-buffer-create ()
"Create a buffer for listing frames unless one exists, and return it."
(let ((buf (indium-debugger-frames-get-buffer)))
(unless buf
(setq buf (generate-new-buffer (indium-debugger-frames-buffer-name)))
(indium-debugger-frames-setup-buffer buf))
buf))

(defun indium-debugger-frames-setup-buffer (buffer)
"Setup the frames BUFFER."
(with-current-buffer buffer
(indium-debugger-frames-mode)
(setq-local truncate-lines nil)))

(defvar indium-debugger-frames-mode-map
(let ((map (make-sparse-keymap)))
(define-key map [return] #'indium-follow-link)
(define-key map (kbd "C-m") #'indium-follow-link)
(define-key map (kbd "n") #'indium-debugger-frames-next-frame)
(define-key map (kbd "p") #'indium-debugger-frames-previous-frame)
(define-key map [tab] #'indium-debugger-frames-next-frame)
(define-key map [backtab] #'indium-debugger-frames-previous-frame)
map))

(define-derived-mode indium-debugger-frames-mode special-mode "Frames"
"Major mode visualizind and navigating the JS stack.

\\{indium-debugger-frames--mode-map}"
(setq buffer-read-only t)
(font-lock-ensure)
(read-only-mode))

(provide 'indium-debugger-frames)
;;; indium-debugger-frames.el ends here

jade-debugger-litable.el → indium-debugger-litable.el View File

@@ -1,4 +1,4 @@
;;; jade-debugger-litable.el --- Display local values in debugger buffers -*- lexical-binding: t; -*-
;;; indium-debugger-litable.el --- Display local values in debugger buffers -*- lexical-binding: t; -*-

;; Copyright (C) 2017 Nicolas Petton

@@ -26,15 +26,15 @@
(require 'js2-mode)
(require 'subr-x)
(require 'seq)
(require 'jade-render)
(require 'indium-render)

(declare-function jade-debugger-get-current-scopes "jade-debugger" ())
(declare-function jade-debugger-get-scope-properties "jade-debugger" (scope callback))
(declare-function indium-debugger-get-current-scopes "indium-debugger" ())
(declare-function indium-debugger-get-scope-properties "indium-debugger" (scope callback))

(defun jade-debugger-litable-setup-buffer ()
(defun indium-debugger-litable-setup-buffer ()
"Render locals in the current buffer."
(let ((scope (car (jade-debugger-get-current-scopes))))
(jade-debugger-get-scope-properties
(let ((scope (car (indium-debugger-get-current-scopes))))
(indium-debugger-get-scope-properties
scope
(lambda (properties _)
;; This is just cosmetic, don't break the session
@@ -42,48 +42,48 @@
(js2-mode-wait-for-parse
(lambda ()
(js2-visit-ast js2-mode-ast
(jade-debugger-litable-make-visitor properties)))))))))
(indium-debugger-litable-make-visitor properties)))))))))

(defun jade-debugger-litable-unset-buffer ()
(defun indium-debugger-litable-unset-buffer ()
"Remove locals from the current buffer."
(remove-overlays (point-min)
(point-max)
'jade-litable t))
'indium-litable t))

(defun jade-debugger-litable-make-visitor (properties)
(defun indium-debugger-litable-make-visitor (properties)
"Return an AST visitor to add overlays for values in PROPERTIES."
(lambda (node end-p)
(unless end-p
(cond ((js2-function-node-p node)
(jade-debugger-litable-visit-function-node node properties)))
(cond ((jade-debugger-litable-local-name-node-p node)
(jade-debugger-litable-visit-name-node node properties))))
(indium-debugger-litable-visit-function-node node properties)))
(cond ((indium-debugger-litable-local-name-node-p node)
(indium-debugger-litable-visit-name-node node properties))))
t))

(defun jade-debugger-litable-visit-function-node (node properties)
(defun indium-debugger-litable-visit-function-node (node properties)
"Visit the function NODE with PROPERTIES."
(seq-do (lambda (param)
(jade-debugger-litable-maybe-add-value-overlay param properties))
(indium-debugger-litable-maybe-add-value-overlay param properties))
(js2-function-node-params node)))

(defun jade-debugger-litable-visit-name-node (node properties)
(defun indium-debugger-litable-visit-name-node (node properties)
"Visit a JS2 name NODE to add an overlay displaying PROPERTIES."
(jade-debugger-litable-maybe-add-value-overlay node properties))
(indium-debugger-litable-maybe-add-value-overlay node properties))

(defun jade-debugger-litable-local-name-node-p (node)
(defun indium-debugger-litable-local-name-node-p (node)
"Return non-nil if NODE represents a local variable."
(let ((parent (js2-node-parent node)))
(and parent (js2-name-node-p node)
(or (js2-var-init-node-p parent)
(js2-assign-node-p parent)))))

(defun jade-debugger-litable-visit-var-init-node (node properties)
(defun indium-debugger-litable-visit-var-init-node (node properties)
"Visit variable initialization NODE with PROPERTIES."
(seq-do (lambda (param)
(jade-debugger-litable-maybe-add-value-overlay param properties))
(indium-debugger-litable-maybe-add-value-overlay param properties))
(js2-function-node-params node)))

(defun jade-debugger-litable-maybe-add-value-overlay (node properties)
(defun indium-debugger-litable-maybe-add-value-overlay (node properties)
"If NODE match PROPERTIES, add a value overlay."
(if-let ((name (buffer-substring-no-properties (js2-node-abs-pos node)
(js2-node-abs-end node)))
@@ -91,35 +91,35 @@
(string= name
(map-elt property 'name)))
properties)))
(jade-debugger-litable-add-value-overlay node property)))
(indium-debugger-litable-add-value-overlay node property)))

(defun jade-debugger-litable-add-value-overlay (node property)
(defun indium-debugger-litable-add-value-overlay (node property)
"Add an overlay displaying the value of NODE for PROPERTY.
Ignore if the object name of NODE is not in the current scope."
(save-excursion
(goto-char (js2-node-abs-pos node))
(let ((inhibit-read-only t)
(ov (jade-debugger-litable--get-overlay-at-pos))
(contents (string-trim (jade-render-property-to-string property)))
(ov (indium-debugger-litable--get-overlay-at-pos))
(contents (string-trim (indium-render-property-to-string property)))
(name (map-elt property 'name)))
(unless (seq-contains (overlay-get ov 'jade-properties) name)
(unless (seq-contains (overlay-get ov 'indium-properties) name)
(if-let ((existing-contents (overlay-get ov 'after-string)))
(setq contents (concat existing-contents ", " contents))
(setq contents (concat " " contents)))
(setq contents (jade-debugger-litable--overlay-string contents))
(setq contents (indium-debugger-litable--overlay-string contents))
(font-lock-prepend-text-property 0
(seq-length contents)
'face
'jade-litable-face
'indium-litable-face
contents)
(overlay-put ov
'jade-properties
(cons name (overlay-get ov 'jade-properties)))
'indium-properties
(cons name (overlay-get ov 'indium-properties)))
(overlay-put ov
'after-string
contents)))))

(defun jade-debugger-litable--overlay-string (string)
(defun indium-debugger-litable--overlay-string (string)
"Return the STRING to be added to an overlay at the end of the line.
If the display string overflows, trim it to avoid truncating the line."
(save-excursion
@@ -129,15 +129,15 @@ If the display string overflows, trim it to avoid truncating the line."
(truncate-string-to-width string width 0 nil "..."))
string)))

(defun jade-debugger-litable--get-overlay-at-pos ()
(defun indium-debugger-litable--get-overlay-at-pos ()
"Return the overlay for litable at point.
If no overlay exist, create one."
(or (seq-find (lambda (ov)
(overlay-get ov 'jade-litable))
(overlay-get ov 'indium-litable))
(overlays-in (point-at-bol) (point-at-eol)))
(let ((ov (make-overlay (point-at-bol) (point-at-eol))))
(overlay-put ov 'jade-litable t)
(overlay-put ov 'indium-litable t)
ov)))

(provide 'jade-debugger-litable)
;;; jade-debugger-litable.el ends here
(provide 'indium-debugger-litable)
;;; indium-debugger-litable.el ends here

jade-debugger-locals.el → indium-debugger-locals.el View File

@@ -1,4 +1,4 @@
;;; jade-debugger-locals.el --- Inspect locals -*- lexical-binding: t; -*-
;;; indium-debugger-locals.el --- Inspect locals -*- lexical-binding: t; -*-

;; Copyright (C) 2017 Nicolas Petton

@@ -23,37 +23,37 @@

;;; Code:

(require 'jade-render)
(require 'indium-render)

(declare 'jade-backend-get-properties)
(declare 'jade-debugger-get-scopes-properties)
(declare 'jade-debugger-get-current-scopes)
(declare 'indium-backend-get-properties)
(declare 'indium-debugger-get-scopes-properties)
(declare 'indium-debugger-get-current-scopes)

(defun jade-debugger-locals (&optional no-pop)
(defun indium-debugger-locals (&optional no-pop)
"Inspect the local variables in the current stack frame's scope.
Unless NO-POP is non-nil, pop the locals buffer."
(interactive)
(let* ((buf (jade-debugger-locals-get-buffer-create))
(let* ((buf (indium-debugger-locals-get-buffer-create))
(inhibit-read-only t)
(scopes (jade-debugger-get-current-scopes)))
(scopes (indium-debugger-get-current-scopes)))
(with-current-buffer buf
(erase-buffer))
(jade-debugger-get-scopes-properties
(indium-debugger-get-scopes-properties
scopes
(lambda (properties scope)
(jade-debugger-locals-render-properties properties scope no-pop)))))
(indium-debugger-locals-render-properties properties scope no-pop)))))

(defun jade-debugger-locals-maybe-refresh ()
(defun indium-debugger-locals-maybe-refresh ()
"When a local inspector is open, refresh it."
(interactive)
(let ((buf (jade-debugger-locals-get-buffer)))
(let ((buf (indium-debugger-locals-get-buffer)))
(when buf
(jade-debugger-locals t))))
(indium-debugger-locals t))))

(defun jade-debugger-locals-render-properties (properties scope &optional no-pop)
(defun indium-debugger-locals-render-properties (properties scope &optional no-pop)
"Render PROPERTIES in SCOPE.
Unless NO-POP in non-nil, pop the locals buffer."
(let* ((buf (jade-debugger-locals-get-buffer-create))
(let* ((buf (indium-debugger-locals-get-buffer-create))
(inhibit-read-only t)
(name (map-elt scope 'name))
(type (map-elt scope 'type))
@@ -64,45 +64,45 @@ Unless NO-POP in non-nil, pop the locals buffer."
(with-current-buffer buf
(save-excursion
(goto-char (point-max))
(jade-render-keyword description)
(indium-render-keyword description)
(insert "\n\n")
(jade-render-properties properties)
(indium-render-properties properties)
(insert "\n")))
(unless no-pop
(pop-to-buffer buf))))

(defun jade-debugger-locals-get-buffer ()
(defun indium-debugger-locals-get-buffer ()
"Return the buffer to use to inspect locals."
(get-buffer (jade-debugger-locals-buffer-name)))
(get-buffer (indium-debugger-locals-buffer-name)))

(defun jade-debugger-locals-buffer-name ()
(defun indium-debugger-locals-buffer-name ()
"Return the name of the buffer to use to inspect locals."
"*JS Debugger Locals*")

(defun jade-debugger-locals-get-buffer-create ()
(defun indium-debugger-locals-get-buffer-create ()
"Create a locals buffer unless one exists, and return it."
(let ((buf (jade-debugger-locals-get-buffer)))
(let ((buf (indium-debugger-locals-get-buffer)))
(unless buf
(setq buf (generate-new-buffer (jade-debugger-locals-buffer-name)))
(jade-debugger-locals-setup-buffer buf))
(setq buf (generate-new-buffer (indium-debugger-locals-buffer-name)))
(indium-debugger-locals-setup-buffer buf))
buf))

(defun jade-debugger-locals-setup-buffer (buffer)
(defun indium-debugger-locals-setup-buffer (buffer)
"Setup BUFFER."
(with-current-buffer buffer
(jade-debugger-locals-mode)
(indium-debugger-locals-mode)
(read-only-mode)))

(defvar jade-debugger-locals-mode-map
(let ((map (copy-keymap jade-inspector-mode-map)))
(defvar indium-debugger-locals-mode-map
(let ((map (copy-keymap indium-inspector-mode-map)))
(define-key map "g" nil)
(define-key map "l" nil)
map))

(define-derived-mode jade-debugger-locals-mode jade-inspector-mode "Locals"
(define-derived-mode indium-debugger-locals-mode indium-inspector-mode "Locals"