Skip to content

Commit 480ca57

Browse files
authored
Merge pull request #209 from JunoLab/avi/betterutils
better utils:
2 parents 5538ffe + 28eb7ac commit 480ca57

5 files changed

Lines changed: 117 additions & 46 deletions

File tree

src/completions.jl

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -145,19 +145,14 @@ completionurl(c::REPLCompletions.ModuleCompletion) = begin
145145
mod, name = c.parent, c.mod
146146
val = getfield′(mod, name)
147147
if val isa Module # module info
148-
parentmodule(val) == val || val (Main, Base, Core) ?
149-
"atom://julia-client/?moduleinfo=true&mod=$(name)" :
150-
"atom://julia-client/?moduleinfo=true&mod=$(mod).$(name)"
148+
urimoduleinfo(parentmodule(val) == val || val (Base, Core) ? name : "$mod.$name")
151149
else
152-
"atom://julia-client/?docs=true&mod=$(mod)&word=$(name)"
150+
uridocs(mod, name)
153151
end
154152
end
155-
completionurl(c::REPLCompletions.MethodCompletion) =
156-
"atom://julia-client/?docs=true&mod=$(c.method.module)&word=$(c.method.name)"
157-
completionurl(c::REPLCompletions.PackageCompletion) =
158-
"atom://julia-client/?moduleinfo=true&mod=$(c.package)"
159-
completionurl(c::REPLCompletions.KeywordCompletion) =
160-
"atom://julia-client/?docs=true&mod=Main&word=$(c.keyword)"
153+
completionurl(c::REPLCompletions.MethodCompletion) = uridocs(c.method.module, c.method.name)
154+
completionurl(c::REPLCompletions.PackageCompletion) = urimoduleinfo(c.package)
155+
completionurl(c::REPLCompletions.KeywordCompletion) = uridocs("Main", c.keyword)
161156

162157
completionmodule(mod, c) = shortstr(mod)
163158
completionmodule(mod, c::REPLCompletions.ModuleCompletion) = shortstr(c.parent)
@@ -183,8 +178,6 @@ completiontype(::REPLCompletions.DictCompletion) = "property"
183178
completiontype(::REPLCompletions.KeywordCompletion) = "keyword"
184179
completiontype(::REPLCompletions.PathCompletion) = "path"
185180

186-
ismacro(ct::AbstractString) = startswith(ct, '@') || endswith(ct, '"')
187-
188181
completionicon(c) = ""
189182
completionicon(c::REPLCompletions.ModuleCompletion) = begin
190183
ismacro(c.mod) && return "icon-mention"

src/docs.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ function renderitem(x)
3232

3333
mod = getmodule(x.mod)
3434
name = Symbol(x.name)
35-
r[:typ], r[:icon], r[:nativetype] = if (name !== :ans || mod === Base) && name keys(Docs.keywords)
35+
r[:typ], r[:icon], r[:nativetype] = if (name !== :ans || mod === Base) && iskeyword(name)
3636
"keyword", "k", x.typ
3737
else
3838
val = getfield′(mod, name)

src/utils.jl

Lines changed: 78 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,20 @@
1+
# file utilities
2+
# --------------
3+
4+
function isfile′(p)
5+
try
6+
isfile(p)
7+
catch
8+
false
9+
end
10+
end
11+
12+
iswritablefile(file) = Base.uperm(file) == 0x06
13+
nonwritablefiles(files) = filter(!iswritablefile, files)
14+
15+
# path utilities
16+
# --------------
17+
118
include("path_matching.jl")
219

320
isuntitled(p) = occursin(r"^(\.\\|\./)?untitled-[\d\w]+(:\d+)?$", p)
@@ -12,14 +29,6 @@ function realpath′(p)
1229
end
1330
end
1431

15-
function isfile′(p)
16-
try
17-
isfile(p)
18-
catch
19-
false
20-
end
21-
end
22-
2332
using Pkg, OrderedCollections
2433
function finddevpackages()
2534
usage_file = joinpath(Pkg.logdir(), "manifest_usage.toml")
@@ -99,6 +108,9 @@ function md_hlines(md)
99108
return MD(v)
100109
end
101110

111+
# string utilties
112+
# ---------------
113+
102114
function strlimit(str::AbstractString, limit::Int = 30, ellipsis::AbstractString = "")
103115
will_append = length(str) > limit
104116

@@ -122,34 +134,56 @@ shortstr(val) = strlimit(string(val), 20)
122134
struct Undefined end
123135

124136
# get utilities
137+
# -------------
138+
125139
using CodeTools
126140

127141
"""
128-
getfield′(mod::Module, name::String, default = Undefined())
142+
getfield′(mod::Module, name::AbstractString, default = Undefined())
129143
getfield′(mod::Module, name::Symbol, default = Undefined())
144+
getfield′(mod::AbstractString, name::Symbol, default = Undefined())
130145
getfield′(object, name::Symbol, default = Undefined())
146+
getfield′(object, name::AbstractString, default = Undefined())
131147
132148
Returns the specified field of a given `Module` or some arbitrary `object`,
133149
or `default` if no such a field is found.
134150
"""
135-
getfield′(mod::Module, name::String, default = Undefined()) = CodeTools.getthing(mod, name, default)
151+
getfield′(mod::Module, name::AbstractString, default = Undefined()) = CodeTools.getthing(mod, name, default)
136152
getfield′(mod::Module, name::Symbol, default = Undefined()) = getfield′(mod, string(name), default)
153+
getfield′(mod::AbstractString, name::Symbol, default = Undefined()) = getfield′(getmodule(mod), string(name), default)
137154
getfield′(@nospecialize(object), name::Symbol, default = Undefined()) = isdefined(object, name) ? getfield(object, name) : default
155+
getfield′(@nospecialize(object), name::AbstractString, default = Undefined()) = isdefined(object, name) ? getfield(object, Symbol(name)) : default
138156

139157
"""
140-
getmodule(mod::String)
141-
getmodule(parent::Union{Nothing, Module}, mod::String)
158+
getmodule(mod::AbstractString)
159+
getmodule(parent::Union{Nothing, Module}, mod::AbstractString)
142160
getmodule(code::AbstractString, pos; filemod)
143161
144162
Calls `CodeTools.getmodule(args...)`, but returns `Main` instead of `nothing` in a fallback case.
145163
"""
146164
getmodule(args...) = (m = CodeTools.getmodule(args...)) === nothing ? Main : m
147165

148-
getmethods(mod::Module, word::String) = methods(CodeTools.getthing(mod, word))
149-
getmethods(mod::String, word::String) = getmethods(getmodule(mod), word)
166+
"""
167+
getmethods(mod::Module, word::AbstractString)
168+
getmethods(mod::AbstractString, word::AbstractString)
169+
170+
Returns the [`MethodList`](@ref) for `word`, which is bound within `mod` module.
171+
"""
172+
getmethods(mod::Module, word::AbstractString) = methods(CodeTools.getthing(mod, word))
173+
getmethods(mod::AbstractString, word::AbstractString) = getmethods(getmodule(mod), word)
174+
175+
"""
176+
getdocs(mod::Module, word::AbstractString, fallbackmod::Module = Main)
177+
getdocs(mod::AbstractString, word::AbstractString, fallbackmod::Module = Main)
178+
179+
Retrieves docs for `mod.word` with [`@doc`](@ref) macro. If `@doc` is not available
180+
within `mod` module, `@doc` will be evaluated in `fallbackmod` module if possible.
150181
151-
getdocs(mod::Module, word::String, fallbackmod::Module = Main) = begin
152-
md = if Symbol(word) in keys(Docs.keywords)
182+
!!! note
183+
You may want to run [`cangetdocs`](@ref) in advance.
184+
"""
185+
getdocs(mod::Module, word::AbstractString, fallbackmod::Module = Main) = begin
186+
md = if iskeyword(word)
153187
Core.eval(Main, :(@doc($(Symbol(word)))))
154188
else
155189
docsym = Symbol("@doc")
@@ -164,13 +198,39 @@ getdocs(mod::Module, word::String, fallbackmod::Module = Main) = begin
164198
end
165199
md_hlines(md)
166200
end
167-
getdocs(mod::String, word::String, fallbackmod::Module = Main) =
201+
getdocs(mod::AbstractString, word::AbstractString, fallbackmod::Module = Main) =
168202
getdocs(getmodule(mod), word, fallbackmod)
169203

204+
"""
205+
cangetdocs(mod::Module, word::Symbol)
206+
cangetdocs(mod::Module, word::AbstractString)
207+
cangetdocs(mod::AbstractString, word::Union{Symbol, AbstractString})
208+
209+
Checks if the documentation bindings for `mod.word` is resolved and `mod.word`
210+
is not deprecated.
211+
"""
170212
cangetdocs(mod::Module, word::Symbol) =
171213
Base.isbindingresolved(mod, word) &&
172214
!Base.isdeprecated(mod, word)
173-
cangetdocs(mod::Module, word::String) = cangetdocs(mod, Symbol(word))
215+
cangetdocs(mod::Module, word::AbstractString) = cangetdocs(mod, Symbol(word))
216+
cangetdocs(mod::AbstractString, word::Union{Symbol, AbstractString}) = cangetdocs(getmodule(mod), word)
217+
218+
# is utilities
219+
# ------------
220+
221+
iskeyword(word::Symbol) = word in keys(Docs.keywords)
222+
iskeyword(word::AbstractString) = iskeyword(Symbol(word))
223+
224+
ismacro(ct::AbstractString) = startswith(ct, '@') || endswith(ct, '"')
225+
ismacro(f::Function) = startswith(string(methods(f).mt.name), "@")
226+
227+
# uri utilties
228+
# ------------
229+
230+
uriopen(file, line = 0) = "atom://julia-client/?open=true&file=$(file)&line=$(line)"
231+
uridocs(mod, word) = "atom://julia-client/?docs=true&mod=$(mod)&word=$(word)"
232+
urigoto(mod, word) = "atom://julia-client/?goto=true&mod=$(mod)&word=$(word)"
233+
urimoduleinfo(mod) = "atom://julia-client/?moduleinfo=true&mod=$(mod)"
174234

175235
#=
176236
module file detections

src/workspace.jl

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,5 +56,3 @@ wsicon(mod, name, ::Expr) = "icon-code"
5656
wsicon(mod, name, ::Symbol) = "icon-code"
5757
wsicon(mod, name, ::Exception) = "icon-bug"
5858
wsicon(mod, name, ::Undefined) = "icon-circle-slash"
59-
60-
ismacro(f::Function) = startswith(string(methods(f).mt.name), "@")

test/utils.jl

Lines changed: 33 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ end
4848
@test Atom.finddevpackages() isa AbstractDict
4949
end
5050

51-
#TODO: baselink, edit
51+
# TODO: baselink, edit
5252

5353
cd(old_pwd)
5454
end
@@ -79,18 +79,38 @@ end
7979
end
8080
end
8181

82-
@testset "limiting excessive strings" begin
83-
using Atom: strlimit
82+
@testset "is utilities" begin
83+
@testset "iskeyword" begin
84+
using Atom: iskeyword
8485

85-
# only including ASCII
86-
@test strlimit("julia", 5) == "julia"
87-
@test strlimit("julia", 4) == "jul…"
88-
@test strlimit("Julia in the Nutshell", 21, " ...") == "Julia in the Nutshell"
89-
@test strlimit("Julia in the Nutshell", 20, " ...") == "Julia in the Nut ..."
86+
@test iskeyword(:begin)
87+
@test iskeyword("begin")
88+
@test !iskeyword(:iskeyword)
89+
end
90+
91+
@testset "ismacro" begin
92+
using Atom: ismacro
93+
94+
@test ismacro("@view")
95+
@test ismacro("r\"")
96+
@test ismacro(getfield(Main, Symbol("@view")))
97+
end
98+
end
9099

91-
# including Unicode: should respect _length_ of strings, not code units
92-
@test strlimit("jμλια", 5) == "jμλια"
93-
@test strlimit("jμλια", 4) == "jμλ…"
94-
@test strlimit("Jμλια in the Nutshell", 21, " ...") == "Jμλια in the Nutshell"
95-
@test strlimit("Jμλια in the Nutshell", 20, " ...") == "Jμλια in the Nut ..."
100+
@testset "string utilities" begin
101+
@testset "limiting excessive strings" begin
102+
using Atom: strlimit
103+
104+
# only including ASCII
105+
@test strlimit("julia", 5) == "julia"
106+
@test strlimit("julia", 4) == "jul…"
107+
@test strlimit("Julia in the Nutshell", 21, " ...") == "Julia in the Nutshell"
108+
@test strlimit("Julia in the Nutshell", 20, " ...") == "Julia in the Nut ..."
109+
110+
# including Unicode: should respect _length_ of strings, not code units
111+
@test strlimit("jμλια", 5) == "jμλια"
112+
@test strlimit("jμλια", 4) == "jμλ…"
113+
@test strlimit("Jμλια in the Nutshell", 21, " ...") == "Jμλια in the Nutshell"
114+
@test strlimit("Jμλια in the Nutshell", 20, " ...") == "Jμλια in the Nut ..."
115+
end
96116
end

0 commit comments

Comments
 (0)