Skip to content

Commit

Permalink
Debug extension
Browse files Browse the repository at this point in the history
Use DebugAdapter.jl + dape to provide debugging capabilities from repl.

Requires julia-vscode/DebugAdapter.jl#95 to
be merged first.
  • Loading branch information
iNecas committed Nov 8, 2024
1 parent dff92c4 commit c54dda1
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 1 deletion.
14 changes: 13 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -463,11 +463,23 @@ Customization variables:
- `julia-snail/ob-julia-capture-io t` : If true, all intermediate printing during evaluation will be captured by ob-julia and printed into your org notebook
- `julia-snail/ob-julia-resource-directory "./.ob-julia-snail/"`: Directory used to store automatically generated image files for display in org buffers. By default this is a local hidden directory, but it can be changed to e.g. `/tmp/` if you don't want to keep the image files around.

### Debug

This extension uses [DebugAdapter.jl](https://github.com/julia-vscode/DebugAdapter.jl) and [dape](https://github.com/svaante/dape) to allow debugging inside the REPL.

Use one of the following macros to initiate the debug session from the REPL:
- `@run` pause on first breakpoint.
- `@enter` pause on entry.

```julia
using .JuliaSnail.Extensions.Debug

@enter(println("hello world"))
```

## Future improvements

- The `libvterm` dependency forces the use of recent Emacs releases, forces Emacs to be build with module support, complicates support for Windows, and is generally quite gnarly. The Eat alternative requires Emacs 28. It would be much better to re-implement the REPL in Elisp and make sure it works on older Emacs versions.
- Completion does not pick up local variables.
- A real eldoc implementation would be great, but difficult to do with Julia’s generic functions.
- A debugger would be great.
- A real test suite which fully drives both Julia and Emacs and runs in a CI environment (like GitHub Actions) wouldn’t hurt, either.
80 changes: 80 additions & 0 deletions extensions/debug/Debug.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
## 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/>.

module Debug

export @enter, @run

Main.JuliaSnail.@with_pkg_env (@__DIR__) begin
import DebugAdapter
import Sockets
import Logging
end

port = 12124
conn = missing
session = missing
server = missing
ready = Channel{Bool}(1)

function init()
# Logging.global_logger(Logging.SimpleLogger(Logging.Debug))
end

function start()
global server = Sockets.listen(port)
Threads.@spawn begin
while true
@debug "Listening on port $port"
global conn = Sockets.accept(server)
@debug "Accepted connection"
global session = DebugAdapter.DebugSession(conn)
# When using the attach request, the terminate request does not work.
session.capabilities.supportsTerminateRequest = false
@debug "Starting debug session"
put!(ready, true)
DebugAdapter.run(session)
end
end
end

function run(mod, code, filepath; stop_on_entry=false)
if ismissing(server)
start()
end
soe = ":json-false"
if stop_on_entry
soe = "t"
end
Main.JuliaSnail.send_to_client("""
(dape `(:request "attach"
host "localhost"
port $port
:type "julia"
:stopOnEntry $soe))
""")
# Wait for the session to be ready.
take!(ready)
DebugAdapter.debug_code(session, mod, code, filepath)
end

macro enter(command)
Base.remove_linenums!(command)
:(run(Main, $(string(command)), $(string(__source__.file)), stop_on_entry=true))
end

macro run(command)
Base.remove_linenums!(command)
:(run(Main, $(string(command)), $(string(__source__.file)), stop_on_entry=false))
end
end
2 changes: 2 additions & 0 deletions extensions/debug/Project.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[deps]
DebugAdapter = "17994d07-08fe-42cc-bc1b-7af499b1ea47"
11 changes: 11 additions & 0 deletions extensions/debug/debug.el
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
;;; debug.el --- Julia Snail -*- lexical-binding: t -*-

(defun julia-snail/debug-init (repl-buf)
(julia-snail--send-to-server
'("JuliaSnail" "Extensions")
"load([\"debug\" \"Debug.jl\"]); Debug.init()"
:repl-buf repl-buf
:async nil
:async-poll-maximum 120000))

(provide 'julia-snail/debug)

0 comments on commit c54dda1

Please sign in to comment.