Is there an easy way to get at the history of REPL input?

I have also this:

less ~/.julia/logs/repl_history.jl

It is interesting julia_history’s last command is (edit:) one day one month older than repl_history’s…

So maybe it is actual one?

2 Likes

The location of the history file moved in 0.7, thus ~/.julia_history.jl is for versions 0.6 and prior, whereas ~/.julia/logs/repl_history.jl is for 0.7+. Apparently you last used version 0.6 a month ago.

2 Likes

I think this will serve nicely: REPL.find_hist_file(). Then all that is required is a little macro (or function) to spit out the contents of the history file… Perhaps like this, except a lot more succinct:

InteractiveUtils.less(REPL.find_hist_file())

Maybe this?

macro history() InteractiveUtils.less(REPL.find_hist_file()); end
2 Likes

I again tried to do something easy with Julia and it seems I am not very compatible with this language yet. :frowning:

This is just ugly (but it seems to work).

For examle I was impatient and used PyCall to implement findall function so you need to have PyCall installed.

I did not test it thoroughly so take it just as … (inspiration? I am not sure :stuck_out_tongue: ) !!

julia> macro history2(a)
       run(pipeline(```$(Sys.BINDIR)/julia -e """import PyCall
         re = PyCall.pyimport(\"re\")
         open(\"$(REPL.find_hist_file())\") do f
          data = read(f)
          aa = re[:findall]( \"(^\\\\# time.*?)(?=# time)\", String(data), re[:S] | re[:M])
          for i in aa 
            if match(Regex(\"$(a)\"), 
               i[findfirst(r\".*?\n.*?\n\", i).stop+1:end]  # ignore first two lines
               ) != nothing
               println(i)
            end
          end 
         end"""```, `less -`));
       end

You could try

julia> @history2 som.thing;  # this regex work

julia> @history2 som.*thing;  # this regex doesn't work! 

julia> @history2 "som.*thing";  # this regex work

julia> @history2 "(?i)pager";  # case insensitive example

Another warning: I used less - instead of something like InteractiveUtils.shell_split(get(ENV, "PAGER", "less")) because I am not sure if other pagers could work with output redirection and I don’t know how to nicely check this functionality…

It would be better to split it into two functionalities 1-searcher for “elements” 2-macro for pushing string (vector of strings) into “less”. But I spent too much time to this “self-homework”…

I tried a simpler way of searching the history file.

open(raw"C:\\Users\chatura\\.julia\\logs\\repl_history.jl") do file
    for ln in eachline(file)
#         if endswith(ln, "jl")==true
        if occursin(r"(CSV)", ln) ==true   
            println("$(length(ln)), $(ln)")
        end
    end
end

Wouldn’t opening in the editor, eg with

edit(REPL.find_hist_file())

be just as convenient?

1 Like

But the user needs to find the way to properly write all that sentence or remember it.

I have that set up as a key binding in Sublime Text (and a voice command). Similar device would work in VS Code and elsewhere.

@Liso, it is reassuring that all of the history is found under ~/.julia/logs/repl_history.jl

But having an easy command for getting the history in a current session would still be highly desirable (see the %history command in ipython for an example).

Note that there is IJulia.history as a replacement for python’s %history. (This was one of my very first Julia related PRs ! :smiley:)

Also you might want to take a look at https://github.com/crstnbr/SaveREPL.jl/blob/master/src/SaveREPL.jl which contains a bit of history access logic.

3 Likes

That is an awesome contribution!

Another way of looking at the history. I would like to be able to just grab the output and paste it into a script or into the command line.

An example is here:

julia> include(".\\REPLHistory.jl");                       
                                                            
julia> a = rand(3)                                          
                                                            
3-element Array{Float64,1}:                                 
 0.7650591549676755                                         
 0.37080326489156024                                        
 0.2852039006568494                                         
                                                            
shell> pwd                                                  
                                                            
/c/Users/PetrKrysl/Documents/Work-in-progress/Experiments   
                                                            
julia> b = deepcopy(a)                                      
                                                            
3-element Array{Float64,1}:                                 
 0.7650591549676755                                         
 0.37080326489156024                                        
 0.2852039006568494                                         
                                                            
julia> b[1] = 0                                             
                                                            
0                                                           
                                                            
julia> @show b                                              
b = [0.0, 0.37080326489156024, 0.2852039006568494]          
3-element Array{Float64,1}:                                 
 0.0                                                        
 0.37080326489156024                                        
 0.2852039006568494                                         
                                                            
julia> @history 7                                           
a = rand(3)                                                 
;pwd                                                        
b = deepcopy(a)                                             
b[1] = 0                                                    
@show b                                                     
                                                            
julia> 

This was produced with the following little module:

module REPLHistory

using InteractiveUtils
using REPL

export @history

macro history(n) 
	n = n - 1
	list = []; 
	for l in reverse(readlines(REPL.find_hist_file()))[2:end]
		l = strip(l)
		if n != 0
			(l[1] != '#') && (n = n - 1)
			push!(list, l); 
		else
			break
		end
	end
	next = ""
	for l in reverse(list)
		l = next * l
		if l == "# mode: shell"
			next = ";" 
		else
			printit = false
			if (l[1] != '#')
				if (length(l) >= 8) 
					if (l[1:8] != "@history")
						printit = true
					end
				else
					printit = true
				end
			end
			printit && println(l)
			next = "" 
		end
	end
end

end

using .REPLHistory

Is it ok to use

Base.active_repl.mistate.current_mode.hist.history

to get the history?

4 Likes

Well, that’s cool!

That’s awesome; I wonder if a couple more things are possible:

  • distinguishing commands in the different modes (normal, pkg, shell)
  • separating out commands from different REPL sessions (the command you provided interleaves them)

PetrKryslUCSD/REPLHistory.jl: Gain access to the Julia REPL history. (github.com)

$ ~/AppData/Local/Programs/Julia-1.5.3/bin/julia.exe
               _
   _       _ _(_)_     |  Documentation: https://docs.julialang.org
  (_)     | (_) (_)    |
   _ _   _| |_  __ _   |  Type "?" for help, "]?" for Pkg help.
  | | | | | | |/ _` |  |
  | | |_| | | | (_| |  |  Version 1.5.3 (2020-11-09)
 _/ |\__'_|_|_|\__'_|  |  Official https://julialang.org/ release
|__/                   |

julia> using REPLHistory

shell> ls
'3D Objects'
 AppData
'Application Data'
 Contacts
 Cookies
 Documents
 Downloads
 Favorites
...

(@v1.5) pkg> status
Status `C:\Users\pkonl\.julia\environments\v1.5\Project.toml`
  [a5566ce3] REPLHistory v0.1.0

julia> pwd()
"C:\\Users\\pkonl"

julia> print(history())
using REPLHistory
;ls
]status
pwd()

julia>

I wish I could have more confidence in Base.active_repl.mistate.current_mode.hist.history, but it looks alarmingly “internal”.

3 Likes

Man I love the Julia community. I feel like I have a magic lamp. And also the Genie has a time machine because what I wish for usually already has been made and is even in the registry!

I wonder though, might this belong in InteractiveUtils.jl? I can also think of a lot of enhancements that could really help with REPL productivity. Mostly some of the creature comforts I recall from IPython.

1 Like

Somewhat related: I just realized that OhMyREPL has enhanced history search which is pretty sweet, though it doesn’t AFAICT have a way to narrow to just the current session. I opened a feature request issue for that: FR: Limit history to current session · Issue #238 · KristofferC/OhMyREPL.jl · GitHub

1 Like

Not sure if this has been mentioned:

  • In Windows with the *.jl file extension registered for opening with VS Code, adding the following to startup.jl will open the REPL history in a VS Code tab, that updates automatically as more commands are typed:
path = raw"C:\Users\jrafa\.julia\logs\repl_history.jl"
run(`cmd /c code "" $path`)

or one may define a history() function instead:

history() = run(`cmd /c code "" "C:\Users\jrafa\.julia\logs\repl_history.jl"`)

NB: inspired by this @greg_plowman’s post

1 Like