Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ version = "0.3.3-DEV"
InteractiveUtils = "b77e0a4c-d291-57a0-90e8-8db25a27a240"
Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"
REPL = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb"
peco_jll = "b89f85f3-45f8-5ea8-8223-9dfa39faf294"

[compat]
julia = "= 0.7, 1.0"
Expand Down
100 changes: 51 additions & 49 deletions src/InteractiveCodeSearch.jl
Original file line number Diff line number Diff line change
Expand Up @@ -47,23 +47,34 @@
using Base: IOError
using InteractiveUtils: edit, gen_call_with_extracted_types, methodswith

function _readandwrite(cmds)
processes = open(cmds, "r+")
return (processes.out, processes.in, processes)
end


abstract type SearchPolicy end
struct Shallow <: SearchPolicy end
struct Recursive <: SearchPolicy end


mutable struct SearchConfig # CONFIG
open
interactive_matcher::Cmd
interactive_matcher::Function
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This breaks backward-compatibility. Let's still support

CONFIG.interactive_matcher = 

and just remove ::Cmd. The idea is to use run-time dispatch: #6 (comment)

auto_open::Bool
end

function setmatcher!(cmd::Function, obj::SearchConfig)
obj.interactive_matcher = cmd
return
end

function setmatcher!(cmd::Cmd, obj::SearchConfig)
setmatcher!(convertCmd(cmd), obj)
end

function convertCmd(cmd)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use snake_case.

maybe_warn_matcher(cmd)
return function (f)
maybe_warn_matcher(cmd)
f(cmd)
end
end

maybe_identifier(s) = !startswith(string(s), "#")

is_locatable(::Any) = false
Expand Down Expand Up @@ -147,6 +158,12 @@
return path
end

function _readandwrite(matcher)
proc = matcher() do cmd
open(`$cmd`, "r+")
end
return (proc.out, proc.in, proc)
end

"""
read_stdout(input::AbstractString, cmd)
Expand Down Expand Up @@ -182,7 +199,6 @@
end

function run_matcher(input)
maybe_warn_matcher()
return String(read_stdout(input, CONFIG.interactive_matcher))
end

Expand Down Expand Up @@ -265,8 +281,7 @@

## Using InteractiveCodeSearch.jl by default

Put the following code in your `~/.julia/config/startup.jl` (≥ Julia 0.7)
or `~/.juliarc.jl` (Julia 0.6):
Put the following code in your `~/.julia/config/startup.jl`:

```julia
using InteractiveCodeSearch
Expand All @@ -275,7 +290,7 @@
"""
const CONFIG = SearchConfig(
edit, # open
`peco`, # interactive_matcher
x->error("uninitialized"), # interactive_matcher

Check warning on line 293 in src/InteractiveCodeSearch.jl

View check run for this annotation

Codecov / codecov/patch

src/InteractiveCodeSearch.jl#L293

Added line #L293 was not covered by tests
true, # auto_open
)

Expand Down Expand Up @@ -437,10 +452,23 @@
end
end

const preferred_terminal = Cmd[
`peco`,
`percol`,
]
################################################################################
# matcher binaries #
################################################################################

@static if VERSION<v"1.3-"
const preferred_terminal = Cmd[
`peco`,
`percol`,
]
else
using peco_jll
const preferred_terminal = Union{Function,Cmd}[
`peco`,
peco,
`percol`,
]
end

const preferred_gui = Cmd[
`rofi -dmenu -i -p "🔎"`,
Expand All @@ -451,43 +479,18 @@
return !all(isa.(stdstreams, Ref(Base.TTY)))
end

function choose_preferred_command(commands::Vector{Cmd})
function choose_preferred_command(commands::Vector{<:Union{Function,Cmd}}, default=nothing)
for cmd in commands
if Sys.which(cmd.exec[1]) !== nothing
if !(cmd isa Cmd) || Sys.which(cmd.exec[1]) !== nothing
return cmd
end
end
return nothing
end

function choose_preferred_command(f, commands::Vector{Cmd})
cmd = choose_preferred_command(commands)
if cmd !== nothing
return cmd
else
return f()
end
return default
end

# Julia 0.6
const _preferred_terminal = preferred_terminal
const _preferred_gui = preferred_gui

function choose_interactive_matcher(;
preferred_terminal = _preferred_terminal,
preferred_gui = _preferred_gui,
gui = need_gui())
if gui
return choose_preferred_command(preferred_gui) do
return preferred_gui[1]
end
else
return choose_preferred_command(preferred_terminal) do
return choose_preferred_command(preferred_gui) do
return preferred_terminal[1]
end
end
end
function choose_interactive_matcher()
need_gui() && return choose_preferred_command(preferred_gui, preferred_gui[1])
return choose_preferred_command(vcat(preferred_terminal, preferred_gui), preferred_terminal[1])
end

function matcher_installation_tips(program::AbstractString)
Expand All @@ -509,7 +512,7 @@
"""
end

function maybe_warn_matcher(cmd = CONFIG.interactive_matcher)
function maybe_warn_matcher(cmd::Cmd)
if Sys.which(cmd.exec[1]) === nothing
@warn """
Matcher $(cmd.exec[1]) not installed.
Expand All @@ -519,8 +522,7 @@
end

function __init__()
CONFIG.interactive_matcher = choose_interactive_matcher()
maybe_warn_matcher()
setmatcher!(choose_interactive_matcher(), CONFIG)
end

include("taskmanager.jl")
Expand Down
14 changes: 7 additions & 7 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module TestInteractiveCodeSearch
include("preamble.jl")
using InteractiveCodeSearch:
Shallow, Recursive, list_locatables, module_methods, choose_method,
read_stdout, parse_loc, single_macrocall, isliteral
read_stdout, parse_loc, single_macrocall, isliteral, convertCmd
using Base: find_source_file

function with_config(f; kwargs...)
Expand All @@ -22,8 +22,8 @@ function with_config(f; kwargs...)
end

@testset "read_stdout" begin
@test strip(String(read_stdout("spam", `cat`))) == "spam"
@test strip(String(read_stdout(io -> write(io, "egg"), `cat`))) == "egg"
@test strip(String(read_stdout("spam", convertCmd(`cat`)))) == "spam"
@test strip(String(read_stdout(io -> write(io, "egg"), convertCmd(`cat`)))) == "egg"
end

@testset "parse_loc" begin
Expand Down Expand Up @@ -70,7 +70,7 @@ end

with_config(
open = (_...) -> error("must not be called"),
interactive_matcher = `echo " at test.jl:249"`,
interactive_matcher = convertCmd(`echo " at test.jl:249"`),
auto_open = true,
) do
# when function has only one method, `auto_open` has to kick-in:
Expand All @@ -91,7 +91,7 @@ end

with_config(
open = (_...) -> error("must not be called"),
interactive_matcher = `echo " at test.jl:249"`,
interactive_matcher = convertCmd(`echo " at test.jl:249"`),
auto_open = false,
) do
# When `auto_open = false`, the matcher has to be called
Expand Down Expand Up @@ -127,7 +127,7 @@ end
dummy_openline(args...) = push!(open_args, args)

with_config(
interactive_matcher = `echo " at test.jl:249"`,
interactive_matcher = convertCmd(`echo " at test.jl:249"`),
open = dummy_openline,
auto_open = false,
) do
Expand All @@ -149,7 +149,7 @@ end
end

with_config(
interactive_matcher = `true`,
interactive_matcher = convertCmd(`true`),
open = (args...) -> error("open must not be called"),
auto_open = false,
) do
Expand Down