# How can I run hooks before and after the execution of a command in the REPL?

**URL:** https://discourse.julialang.org/t/how-can-i-run-hooks-before-and-after-the-execution-of-a-command-in-the-repl/44815
**Category:** Internals & Design
**Tags:** repl, hook
**Created:** [August 12, 2020, 3:54pm UTC](https://discourse.julialang.org/t/how-can-i-run-hooks-before-and-after-the-execution-of-a-command-in-the-repl/44815 "2020-08-12T15:54:16Z")
**Posts on this page:** 12
**Page:** 1

<div class="post-metadata">

### Author: ![NightMachinary](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nightmachinary/32/14196_2.png) [@NightMachinary](https://discourse.julialang.org/u/NightMachinary)
#### Post date: [August 12, 2020, 3:54pm UTC](https://discourse.julialang.org/t/how-can-i-run-hooks-before-and-after-the-execution-of-a-command-in-the-repl/44815/1 "2020-08-12T15:54:16Z")

</div>

I first opened an [issue](https://github.com/julia-vscode/julia-vscode/issues/1510) on VSCode’s Julia extension to make a bell sound after a long-running command. After more thought, I reached the conclusion that having hooks that run arbitrary Julia code before and after command execution is the correct approach (zsh and emacs use similar solutions). But the REPL hooks are not related to the VSCode extension, and so this should be a Julia feature, not an editor feature. Is there a way to do this now? If not, can the necessary hooks be added?

PS: If it isn’t clear, here’s what I want to do with hooks to solve the original problem of sounding a bell for longrunning commands:

> I want to record the time before any command is executed in the REPL, and after the execution finished, see the duration the command took. If this duration is larger than a threshold, I’ll then start a bell sound.

PPS: Since the VSCode extension does some weird background stuff with the REPL, it still probably needs to do some work to support these hooks properly for its background code execution features. But foreground execution should work without any change on their part.

---

<div class="post-metadata">

### Author: ![tbeason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tbeason/32/15898_2.png) [@tbeason](https://discourse.julialang.org/u/tbeason)
#### Post date: [August 12, 2020, 4:19pm UTC](https://discourse.julialang.org/t/how-can-i-run-hooks-before-and-after-the-execution-of-a-command-in-the-repl/44815/2 "2020-08-12T16:19:09Z")

</div>

I have not used it but there is

[https://github.com/goropikari/Notifier.jl](https://github.com/goropikari/Notifier.jl)

---

<div class="post-metadata">

### Author: ![NightMachinary](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nightmachinary/32/14196_2.png) [@NightMachinary](https://discourse.julialang.org/u/NightMachinary)
#### Post date: [August 12, 2020, 4:36pm UTC](https://discourse.julialang.org/t/how-can-i-run-hooks-before-and-after-the-execution-of-a-command-in-the-repl/44815/3 "2020-08-12T16:36:17Z")

</div>

This is a cool package, but it’s for sending a notification. I need a hook in the REPL machinary itself to actually use this package _automatically_. I want to record the time before any command is executed in the REPL, and after the execution finished, see the duration the command took. If this duration is larger than a threshold, I’ll then use a notification command (here is where Notifier.jl can be useful.).

---

<div class="post-metadata">

### Author: ![ffevotte](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ffevotte/32/6587_2.png) [@ffevotte](https://discourse.julialang.org/u/ffevotte)
#### Post date: [August 13, 2020, 7:20pm UTC](https://discourse.julialang.org/t/how-can-i-run-hooks-before-and-after-the-execution-of-a-command-in-the-repl/44815/4 "2020-08-13T19:20:20Z")

</div>

AFAIU `Revise` is hooking into the REPL in order to automatically run  
`Revise.revise()` before each command. You might want to look at how it’s done there.

PS: sorry for the short & incomplete answer; I’m not at my computer right now…

---

<div class="post-metadata">

### Author: ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)
#### Post date: [August 14, 2020, 5:25am UTC](https://discourse.julialang.org/t/how-can-i-run-hooks-before-and-after-the-execution-of-a-command-in-the-repl/44815/5 "2020-08-14T05:25:50Z")

</div>

I think it is this part:

[https://github.com/timholy/Revise.jl/blob/8336b10a5e7d0e4b1bb0726cf426469c8f866d2e/src/Revise.jl#L1280-L1284](https://github.com/timholy/Revise.jl/blob/8336b10a5e7d0e4b1bb0726cf426469c8f866d2e/src/Revise.jl#L1280-L1284)

I don’t know if this is documented API though. Looks like it changed for 1.5 to make this easier.

---

<div class="post-metadata">

### Author: ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)
#### Post date: [August 14, 2020, 1:54pm UTC](https://discourse.julialang.org/t/how-can-i-run-hooks-before-and-after-the-execution-of-a-command-in-the-repl/44815/6 "2020-08-14T13:54:30Z")

</div>

There’s two kinds of hooks I can imagine people wanting:

1. Run some function before/after each REPL input/output.
2. Transform each REPL AST input before evaluating it.

Of course, the latter is strictly more general since you can insert calls before and after the actual input expression to call hooks, but the former API is much simpler, so it may make some sense to have both? Would be worth filing an issue to discuss making this simpler and/or more official.

---

<div class="post-metadata">

### Author: ![NightMachinary](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nightmachinary/32/14196_2.png) [@NightMachinary](https://discourse.julialang.org/u/NightMachinary)
#### Post date: [August 14, 2020, 2:12pm UTC](https://discourse.julialang.org/t/how-can-i-run-hooks-before-and-after-the-execution-of-a-command-in-the-repl/44815/7 "2020-08-14T14:12:44Z")

</div>

Yes, this would be great. I accomplished my goals using @Tamas_Papp’s help, but making the API official would be good:

```julia
using REPL
function repl_pre()

end
function repl_post()

end
function repl_transform_prepost(ex)
    res_sym = gensym()
    Expr(:toplevel, :($repl_pre()), :($res_sym = $ex),:($repl_post()),:($res_sym))
end
if isdefined(Base, :active_repl_backend)
    if VERSION >= v"1.5.0-DEV.282"
        pushfirst!(Base.active_repl_backend.ast_transforms, repl_transform_prepost)
    else
        # Unsupported
    end
elseif isdefined(Main, :IJulia)
    # Unsupported
    Main.IJulia.push_preexecute_hook(repl_pre)
elseif VERSION >= v"1.5.0-DEV.282"
    pushfirst!(REPL.repl_ast_transforms, repl_transform_prepost)
end

```

---

<div class="post-metadata">

### Author: ![cstjean](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cstjean/32/1444_2.png) [@cstjean](https://discourse.julialang.org/u/cstjean)
#### Post date: [August 14, 2020, 2:21pm UTC](https://discourse.julialang.org/t/how-can-i-run-hooks-before-and-after-the-execution-of-a-command-in-the-repl/44815/8 "2020-08-14T14:21:16Z")

</div>

> [@StefanKarpinski](#):
>
> Transform each REPL AST input before evaluating it.

That sounds a lot like a REPL mode, [GitHub - MasonProtter/ReplMaker.jl: Simple API for building repl modes in Julia](https://github.com/MasonProtter/ReplMaker.jl)

---

<div class="post-metadata">

### Author: ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)
#### Post date: [August 14, 2020, 2:31pm UTC](https://discourse.julialang.org/t/how-can-i-run-hooks-before-and-after-the-execution-of-a-command-in-the-repl/44815/9 "2020-08-14T14:31:42Z")

</div>

Kind of, but you might want to modify and existing repl mode instead of adding a new one.

---

<div class="post-metadata">

### Author: ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)
#### Post date: [August 14, 2020, 2:54pm UTC](https://discourse.julialang.org/t/how-can-i-run-hooks-before-and-after-the-execution-of-a-command-in-the-repl/44815/10 "2020-08-14T14:54:27Z")

</div>

> [@Tamas\_Papp](#):
>
> I don’t know if this is documented API though. Looks like it changed for 1.5 to make this easier.

This isn’t currently documented, but `ast_transforms` is intended precisely to make it easier to hook into the REPL in a composable fashion. We should probably document it, but in the meantime I would still encourage you to use it for your REPL hooks with Julia ≥ 1.5.

I plan to support it in IJulia soon.

---

<div class="post-metadata">

### Author: ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)
#### Post date: [August 14, 2020, 3:19pm UTC](https://discourse.julialang.org/t/how-can-i-run-hooks-before-and-after-the-execution-of-a-command-in-the-repl/44815/11 "2020-08-14T15:19:12Z")

</div>

I don’t have a strong preference here, but since a chain of AST transformations is more general, I guess that would be enough, with the understanding that they will participate in a `foldl`-like reduction.

@stevengj: it would be great to have this documented. Can you please open an issue?

---

<div class="post-metadata">

### Author: ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)
#### Post date: [August 14, 2020, 3:54pm UTC](https://discourse.julialang.org/t/how-can-i-run-hooks-before-and-after-the-execution-of-a-command-in-the-repl/44815/12 "2020-08-14T15:54:13Z")

</div>

> [@Tamas\_Papp](#):
>
> Can you please open an issue?

Done: [document REPL `ast_transforms` · Issue #37047 · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/issues/37047)
