# Exclude pattern from the REPL history

**URL:** <https://discourse.julialang.org/t/exclude-pattern-from-the-repl-history/111999>\
**Category:** General Usage\
**Tags:** repl\
**Created:** [March 23, 2024, 1:57am UTC](https://discourse.julialang.org/t/exclude-pattern-from-the-repl-history/111999 "2024-03-23T01:57:59Z")\
**Posts on this page:** 18\
**Page:** 1

<div class="post-metadata">

**Author:** ![shg](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/shg/32/207943_2.png) [@shg](https://discourse.julialang.org/u/shg)\
**Post date:** [March 23, 2024, 1:57am UTC](https://discourse.julialang.org/t/exclude-pattern-from-the-repl-history/111999/1 "2024-03-23T01:57:59Z")

</div>

Is there any way to prevent some inputs that match a specific pattern from being stored in the REPL history?

---

<div class="post-metadata">

**Author:** ![GHTaarn](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ghtaarn/32/216007_2.png) [@GHTaarn](https://discourse.julialang.org/u/GHTaarn)\
**Post date:** [March 23, 2024, 4:13am UTC](https://discourse.julialang.org/t/exclude-pattern-from-the-repl-history/111999/2 "2024-03-23T04:13:53Z")

</div>

I don’t know of any easy way to do this, why do you want to do this? You can either switch off history entirely or increase the number of saved history items. I also made a package that will allow you to search for specific patterns in the history, but they still get saved, the link to it is [GitHub - GHTaarn/History.jl: History functionality in the Julia REPL similar to what bash provides](https://github.com/GHTaarn/History.jl)

---

<div class="post-metadata">

**Author:** ![screw\_dog](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/screw_dog/32/48119_2.png) [@screw\_dog](https://discourse.julialang.org/u/screw_dog)\
**Post date:** [March 23, 2024, 5:30am UTC](https://discourse.julialang.org/t/exclude-pattern-from-the-repl-history/111999/3 "2024-03-23T05:30:44Z")

</div>

Not sure how useful this is, but:

- there are a number of packages for working with the REPL history (though not exactly what you want), they might help or their code might be useful. See [REPLHistory](https://github.com/PetrKryslUCSD/REPLHistory.jl), [History](https://github.com/GHTaarn/History.jl) and even [OhMyREPL](https://juliapackages.com/p/ohmyrepl).

- Julia’s REPL history is just a text file which you can directly access. It’s usually at `~/.julia/logs/repl_history.jl` but can be found with `REPL.find_hist_file()`.

- the REPL’s least remembered modes are forward and reverse history search (`^S` and `^R` respectively).

Hope something there is useful.

---

<div class="post-metadata">

**Author:** ![shg](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/shg/32/207943_2.png) [@shg](https://discourse.julialang.org/u/shg)\
**Post date:** [March 23, 2024, 6:47am UTC](https://discourse.julialang.org/t/exclude-pattern-from-the-repl-history/111999/4 "2024-03-23T06:47:19Z")

</div>

Thank you @GHTaarn @screw_dog

An Emacs program I wrote sends a specific pattern of Julia code to the REPL. Because they are not reusable at all, I want to exclude them from the history to avoid clutter.

I think a functionality to exclude pattern from history may be useful in some cases in general. For example in bash, there’s HISTIGNORE environment variable for this purpose.

---

<div class="post-metadata">

**Author:** ![GHTaarn](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ghtaarn/32/216007_2.png) [@GHTaarn](https://discourse.julialang.org/u/GHTaarn)\
**Post date:** [March 23, 2024, 7:51am UTC](https://discourse.julialang.org/t/exclude-pattern-from-the-repl-history/111999/5 "2024-03-23T07:51:37Z")

</div>

> [@shg](#):
>
> An Emacs program I wrote sends a specific pattern of Julia code to the REPL. Because they are not reusable at all, I want to exclude them from the history to avoid clutter.

If you use history from past Julia sessions, then you could try to increase the number of history items that Julia saves and create a startup script that filters the history file through `grep -v` before Julia is started. I am not familiar enough with REPL internals to know how to do exactly what you are looking for.

---

<div class="post-metadata">

**Author:** ![kevbonham](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kevbonham/32/216165_2.png) [@kevbonham](https://discourse.julialang.org/u/kevbonham)\
**Post date:** [March 23, 2024, 2:29pm UTC](https://discourse.julialang.org/t/exclude-pattern-from-the-repl-history/111999/6 "2024-03-23T14:29:47Z")

</div>

> [@GHTaarn](#):
>
> why do you want to do this

Not op, but I frequently have situations where eg I’m adding an API key or something to the environment, and I’d rather it not be stored in plain text in my REPL history.

I usually try to remember to set the environment variable before starting the repl or delete manually with `sed`, but it would be nice to have a way to exclude it from the beginning

---

<div class="post-metadata">

**Author:** ![ericphanson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ericphanson/32/215186_2.png) [@ericphanson](https://discourse.julialang.org/u/ericphanson)\
**Post date:** [March 23, 2024, 3:41pm UTC](https://discourse.julialang.org/t/exclude-pattern-from-the-repl-history/111999/7 "2024-03-23T15:41:14Z")

</div>

one trick for that is to use e.g.

```julia
ENV["PASSWORD"] = Base.shred!(s -> read(s, String), Base.getpass("Password"))

```

Then you can paste the key into the prompt instead of the REPL. (Idk if there’s actually a security advantage of `Base.getpass` over `Base.prompt` in this case, since it’s going to an env variable anyway, but I guess it doesn’t hurt).

---

<div class="post-metadata">

**Author:** ![shg](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/shg/32/207943_2.png) [@shg](https://discourse.julialang.org/u/shg)\
**Post date:** [March 24, 2024, 9:34am UTC](https://discourse.julialang.org/t/exclude-pattern-from-the-repl-history/111999/8 "2024-03-24T09:34:19Z")

</div>

I found that I can exclude a specific pattern from history by adding the following to my startup.jl. This redefines REPL.add\_history. The most part is just a copy of original REPL.add\_history function definition from REPL.jl and I just added a line to check a pattern to skip. I know a monkey patching like this is something to be avoided in general. This works but I appreciate a better solution.

```julia
atreplinit() do repl
    @eval begin
        import REPL: add_history, REPLHistoryProvider, PromptState, LineEdit, mode_idx

        function add_history(hist::REPLHistoryProvider, s::PromptState)
            str = rstrip(String(take!(copy(s.input_buffer))))

            occursin(r"#PATTERN_TO_EXCLUDE", str) && return

            isempty(strip(str)) && return
            mode = mode_idx(hist, LineEdit.mode(s))
            !isempty(hist.history) &&
                isequal(mode, hist.modes[end]) && str == hist.history[end] && return
            push!(hist.modes, mode)
            push!(hist.history, str)
            hist.history_file === nothing && return
            entry = """
                # time: $(Libc.strftime("%Y-%m-%d %H:%M:%S %Z", time()))
                # mode: $mode
                $(replace(str, r"^"ms => "\t"))
                """
            try
                seekend(hist.history_file)
            catch err
                (err isa SystemError) || rethrow()
                hist_open_file(hist)
            end
            print(hist.history_file, entry)
            flush(hist.history_file)
            nothing
        end
    end
end

```

---

<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:** [March 24, 2024, 12:47pm UTC](https://discourse.julialang.org/t/exclude-pattern-from-the-repl-history/111999/9 "2024-03-24T12:47:03Z")

</div>

It would be a nice PR to add a hook to add\_history that lets people exclude patterns more easily.

---

<div class="post-metadata">

**Author:** ![shg](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/shg/32/207943_2.png) [@shg](https://discourse.julialang.org/u/shg)\
**Post date:** [March 24, 2024, 2:50pm UTC](https://discourse.julialang.org/t/exclude-pattern-from-the-repl-history/111999/10 "2024-03-24T14:50:13Z")

</div>

@StefanKarpinski What would be a good design of “hook” for this? I am thinking something like below.

```julia
atreplinit() do repl
    repl.options.hist_ignore_pattern = r"PATTERN"
end

```

---

<div class="post-metadata">

**Author:** ![kevbonham](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kevbonham/32/216165_2.png) [@kevbonham](https://discourse.julialang.org/u/kevbonham)\
**Post date:** [March 24, 2024, 5:57pm UTC](https://discourse.julialang.org/t/exclude-pattern-from-the-repl-history/111999/11 "2024-03-24T17:57:17Z")

</div>

Might be nice if it could also take a vector of patterns and then apply `any(pat-> contains(input, pat), patterns)`

Not sure what the performance implications would be…

---

<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:** [March 24, 2024, 7:20pm UTC](https://discourse.julialang.org/t/exclude-pattern-from-the-repl-history/111999/12 "2024-03-24T19:20:51Z")

</div>

It’s interactive, I’m pretty sure performance doesn’t matter at all.

---

<div class="post-metadata">

**Author:** ![mnemnion](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mnemnion/32/206596_2.png) [@mnemnion](https://discourse.julialang.org/u/mnemnion)\
**Post date:** [March 24, 2024, 7:26pm UTC](https://discourse.julialang.org/t/exclude-pattern-from-the-repl-history/111999/13 "2024-03-24T19:26:39Z")

</div>

> [@kevbonham](#):
>
> Not sure what the performance implications would be…

To anchor intuitions here, this is how long it takes PCRE, on an M2 Macbook, to find a line at the end of the Project Gutenberg edition of the King James Bible, which I happen to have around to do like-for-like benchmarks with a particular research paper.

```julia
julia> @time match(r"donations to the Project Gutenberg", kjv)
  0.000282 seconds (3 allocations: 176 bytes)
RegexMatch("donations to the Project Gutenberg")

```

You would need at minimum of three figures worth of regex to notice the time it would take to run them all on a line of REPl inpud.

---

<div class="post-metadata">

**Author:** ![Dan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dan/32/42581_2.png) [@Dan](https://discourse.julialang.org/u/Dan)\
**Post date:** [March 24, 2024, 8:21pm UTC](https://discourse.julialang.org/t/exclude-pattern-from-the-repl-history/111999/14 "2024-03-24T20:21:14Z")

</div>

> [@mnemnion](#):
>
> To anchor intuitions here, this is how long it takes PCRE, on an M2 Macbook, to find a line at the end

… Regex search has very instance-dependent performance. The intuition here is mostly relevant to this simple (and long) Regex.

Specifically, the search here could be sublinear (not even reading the entire Bible) - amen!

---

<div class="post-metadata">

**Author:** ![mnemnion](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mnemnion/32/206596_2.png) [@mnemnion](https://discourse.julialang.org/u/mnemnion)\
**Post date:** [March 24, 2024, 9:13pm UTC](https://discourse.julialang.org/t/exclude-pattern-from-the-repl-history/111999/15 "2024-03-24T21:13:36Z")

</div>

> [@Dan](#):
>
> … Regex search has very instance-dependent performance. The intuition here is mostly relevant to this simple (and long) Regex.

Okay… but like I said, I’m using KJV for some benchmarks and that isn’t the only one.

```julia
julia> @time collect(eachmatch(r"(Abraham|Sarah|Moses|Matthew|Tubalcain)", kjv));
  0.006095 seconds (4.63 k allocations: 404.047 KiB)

julia> length(collect(eachmatch(r"(Abraham|Sarah|Moses|Matthew|Tubalcain)", kjv)))
1157

```

It used to be pretty straightforward to force PCRE into catastrophic backtracking (not that this example would), but most of those cases have been eliminated, you really gotta work for it now.

I really don’t think there is a reasonable number of exclusion patterns which someone might apply to a REPL line which would cause them to notice the time it takes to do so.

---

<div class="post-metadata">

**Author:** ![shg](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/shg/32/207943_2.png) [@shg](https://discourse.julialang.org/u/shg)\
**Post date:** [March 25, 2024, 2:05am UTC](https://discourse.julialang.org/t/exclude-pattern-from-the-repl-history/111999/16 "2024-03-25T02:05:27Z")

</div>

OK. Thank you all. I will file a PR. The option would accept any of a string, a regexp, or a list of those.

---

<div class="post-metadata">

**Author:** ![shg](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/shg/32/207943_2.png) [@shg](https://discourse.julialang.org/u/shg)\
**Post date:** [March 27, 2024, 2:32am UTC](https://discourse.julialang.org/t/exclude-pattern-from-the-repl-history/111999/17 "2024-03-27T02:32:00Z")

</div>

Now I am about to start working on this. This is my first time to contribute to a stdlib and I’d like to know the right way for it.

I thought `]dev REPL` would work but it didn’t. I got an error like `The following package names could not be resolved: REPL`.

I also tried `Revise.track(REPL)` but an error again `invalid redefinition of constant REPL.Options`.

Are there a document for the steps of stdlib development?

---

<div class="post-metadata">

**Author:** ![GHTaarn](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ghtaarn/32/216007_2.png) [@GHTaarn](https://discourse.julialang.org/u/GHTaarn)\
**Post date:** [March 27, 2024, 7:55pm UTC](https://discourse.julialang.org/t/exclude-pattern-from-the-repl-history/111999/18 "2024-03-27T19:55:46Z")

</div>

I don’t have much experience with this, but I started by forking [GitHub - JuliaLang/julia: The Julia Programming Language](https://github.com/julialang/julia) and cloning my fork. I then created a new branch in that clone and edited the relevant `.jl` files. Ideally I guess that one should `make` the project, but I haven’t succeeded with that yet. Instead I downloaded the nightly build, replaced the relevant `.jl` files with my edited versions and started the nightly build to test them.

This is of course not very practical if you have big changes, but I have not had that yet.
