134 lines
5.1 KiB
Markdown
134 lines
5.1 KiB
Markdown
# Task 11: Fix Exception Display in Org Buffer
|
|
|
|
## Problem
|
|
|
|
When an Elixir code block throws an exception, the error is not displayed in the org buffer. The error is only shown in the minibuffer/messages, leaving the user without visible feedback in their document.
|
|
|
|
### Root Cause
|
|
|
|
1. The variable `ob-elixir-signal-errors` defaults to `t` (line 57-63 in `ob-elixir.el`)
|
|
2. When an error is detected, `ob-elixir--process-result` (line 206-222) calls `signal`, which throws an Emacs error
|
|
3. The signaled error propagates up and prevents `org-babel-execute:elixir` from returning a result
|
|
4. Since no result is returned, org-babel has nothing to insert into the buffer
|
|
|
|
### Current Behavior
|
|
|
|
| `ob-elixir-signal-errors` | What happens |
|
|
|--------------------------|--------------|
|
|
| `t` (default) | Error is signaled, shown in minibuffer, **NOT inserted in buffer** |
|
|
| `nil` | Error is returned as the result string, **inserted in buffer** |
|
|
|
|
### Desired Behavior
|
|
|
|
Errors should always be displayed in the org buffer as the result, regardless of the `ob-elixir-signal-errors` setting.
|
|
|
|
## Scope
|
|
|
|
- Non-session execution mode only
|
|
- Session mode is out of scope for this fix
|
|
|
|
## Implementation Plan
|
|
|
|
### Step 1: Modify `ob-elixir--process-result` to pass full error output
|
|
|
|
**File:** `ob-elixir.el` (line 218)
|
|
|
|
**Change:** When signaling an error, pass the full error output instead of the formatted short message.
|
|
|
|
**Current code (line 218):**
|
|
```elisp
|
|
(list (ob-elixir--format-error error-info)))
|
|
```
|
|
|
|
**Proposed change:**
|
|
```elisp
|
|
(list (plist-get error-info :full-output)))
|
|
```
|
|
|
|
**Rationale:**
|
|
- The `:full-output` field contains the complete multi-line error output including stack traces
|
|
- This ensures the `condition-case` in `org-babel-execute:elixir` returns the same full output that would be returned when `ob-elixir-signal-errors` is `nil`
|
|
- The formatted short message from `ob-elixir--format-error` only includes the exception name and first-line message, which is insufficient for debugging
|
|
|
|
### Step 2: Wrap result computation in `org-babel-execute:elixir` (ALREADY DONE)
|
|
|
|
**File:** `ob-elixir.el` (lines 928-945)
|
|
|
|
**Status:** This step was already implemented. The `condition-case` wraps the result computation and catches `ob-elixir-error`, returning `(cadr err)` which will now contain the full error output after Step 1 is applied.
|
|
|
|
```elisp
|
|
(result (condition-case err
|
|
(cond
|
|
;; Session mode with deps
|
|
((and session (not (string= session "none")) deps-string)
|
|
(ob-elixir--evaluate-in-session-with-deps
|
|
session full-body result-type deps-string))
|
|
;; Session mode without deps
|
|
((and session (not (string= session "none")))
|
|
(ob-elixir--evaluate-in-session session full-body result-type))
|
|
;; Non-session with deps
|
|
(deps-string
|
|
(ob-elixir--execute-with-deps full-body result-type deps-string))
|
|
;; Plain execution
|
|
(t
|
|
(ob-elixir--execute full-body result-type)))
|
|
(ob-elixir-error
|
|
;; Return error message so it appears in buffer
|
|
(cadr err))))
|
|
```
|
|
|
|
### Step 3: Add tests for the new behavior
|
|
|
|
**File:** `test/test-ob-elixir-errors.el`
|
|
|
|
**Add new test:** Verify that errors appear in org buffer output when `ob-elixir-signal-errors` is `t`.
|
|
|
|
```elisp
|
|
(ert-deftest ob-elixir-test-error-appears-in-result ()
|
|
"Test that errors appear in result even when signaling is enabled."
|
|
(skip-unless (executable-find ob-elixir-command))
|
|
(let ((ob-elixir-signal-errors t))
|
|
;; Execute via the main entry point (not ob-elixir--execute directly)
|
|
(let ((result (org-babel-execute:elixir "raise \"test error\""
|
|
'((:result-type . value)
|
|
(:result-params . ("replace"))))))
|
|
;; Result should contain the error, not be nil/empty
|
|
(should result)
|
|
(should (string-match-p "RuntimeError" result)))))
|
|
```
|
|
|
|
**Rationale:** The existing test `ob-elixir-test-error-signaling` tests that `ob-elixir--execute` signals an error, but doesn't test the full flow through `org-babel-execute:elixir`. The new test verifies the end-to-end behavior.
|
|
|
|
### Step 4: Update TODO.org
|
|
|
|
**File:** `TODO.org`
|
|
|
|
**Change:** Mark the first item ("errors should be printed in the org buffer") as DONE.
|
|
|
|
## Summary of Changes
|
|
|
|
| File | Change |
|
|
|------|--------|
|
|
| `ob-elixir.el` | Change signal data to pass `:full-output` instead of formatted message |
|
|
| `ob-elixir.el` | Wrap result computation in `condition-case` to catch `ob-elixir-error` (already done) |
|
|
| `test/test-ob-elixir-errors.el` | Add test for error display in org buffer |
|
|
| `TODO.org` | Mark issue as resolved |
|
|
|
|
## Files NOT Modified
|
|
|
|
- Session-related code
|
|
- `ob-elixir--process-result` (keeps existing signaling behavior)
|
|
- `ob-elixir-signal-errors` default value (stays `t`)
|
|
|
|
## Verification
|
|
|
|
After implementation, test with:
|
|
|
|
```org
|
|
#+begin_src elixir
|
|
raise "This error should appear in the buffer"
|
|
#+end_src
|
|
```
|
|
|
|
Expected: The RuntimeError message should appear as the result block below the code block.
|