From 8d10edf59cd79339d471115e5461fc44546167ec Mon Sep 17 00:00:00 2001 From: "Steven G. Johnson" Date: Sat, 30 Nov 2013 17:14:46 -0500 Subject: [PATCH 1/2] add text/html writemime for MethodList and Method (fix #4952) --- base/methodshow.jl | 134 +++++++++++++++++++++++++++++++++++++++++++++ base/show.jl | 76 ------------------------- base/sysimg.jl | 1 + 3 files changed, 135 insertions(+), 76 deletions(-) create mode 100644 base/methodshow.jl diff --git a/base/methodshow.jl b/base/methodshow.jl new file mode 100644 index 0000000000000..5ea0f129703f1 --- /dev/null +++ b/base/methodshow.jl @@ -0,0 +1,134 @@ +# Method and method-table pretty-printing + +function argtype_decl(n, t) # -> (argname, argtype) + if isa(n,Expr) + n = n.args[1] # handle n::T in arg list + end + s = string(n) + i = search(s,'#') + if i > 0 + s = s[1:i-1] + end + if t === Any && !isempty(s) + return s, "" + end + if t <: Vararg && t !== None && t.parameters[1] === Any + return string(s, "..."), "" + end + return s, string(t) +end + +function arg_decl_parts(m::Method) + tv = m.tvars + if !isa(tv,Tuple) + tv = (tv,) + end + li = m.func.code + e = uncompressed_ast(li) + argnames = e.args[1] + s = symbol("?") + decls = [argtype_decl(get(argnames,i,s), m.sig[i]) for i=1:length(m.sig)] + return tv, decls, li.file, li.line +end + +function show(io::IO, m::Method) + tv, decls, file, line = arg_decl_parts(m) + if !isempty(tv) + show_delim_array(io, tv, '{', ',', '}', false) + end + print(io, "(") + print_joined(io, [isempty(d[2]) ? d[1] : d[1]*"::"*d[2] for d in decls], + ",", ",") + print(io, ")") + if line > 0 + print(io, " at ", file, ":", line) + end +end + +function show_method_table(io::IO, mt::MethodTable, max::Int=-1, header::Bool=true) + name = mt.name + n = length(mt) + if header + m = n==1 ? "method" : "methods" + print(io, "# $n $m for generic function \"$name\":") + end + d = mt.defs + n = rest = 0 + while !is(d,()) + if max==-1 || n 0 + println(io) + print(io,"... $rest methods not shown (use methods($name) to see them all)") + end +end + +show(io::IO, mt::MethodTable) = show_method_table(io, mt) + +inbase(m::Module) = m == Base ? true : m == Main ? false : inbase(module_parent(m)) +function url(m::Method) + M = m.func.code.module + file = string(m.func.code.file) + line = m.func.code.line + line <= 0 || ismatch(r"In\[[0-9]+\]", file) && return "" + if inbase(M) + return "https://github.com/JuliaLang/julia/tree/$(Base.BUILD_INFO.commit)/base/$file#L$line" + else + try + pkg = Pkg.dir(string(M)) + if file[1:length(pkg)] != pkg + return "file://"*find_source_file(file) + end + u = Git.readchomp(`config remote.origin.url`, dir=pkg) + u = match(Git.GITHUB_REGEX,u).captures[1] + commit = Git.readchomp(`rev-parse HEAD`, dir=pkg) + return "https://github.com/$u/tree/$commit/"*file[length(pkg)+2:end]*"#L$line" + catch + return "file://"*find_source_file(file) + end + end +end + +function writemime(io::IO, ::MIME"text/html", m::Method) + tv, decls, file, line = arg_decl_parts(m) + if !isempty(tv) + print(io,"") + show_delim_array(io, tv, '{', ',', '}', false) + print(io,"") + end + print(io, "(") + print_joined(io, [isempty(d[2]) ? d[1] : d[1]*"::"*d[2]*"" + for d in decls], ",", ",") + print(io, ")") + if line > 0 + u = url(m) + if isempty(u) + print(io, " at ", file, ":", line) + else + print(io, """ at """, + file, ":", line, "") + end + end +end + +function writemime(io::IO, mime::MIME"text/html", mt::MethodTable) + name = mt.name + n = length(mt) + meths = n==1 ? "method" : "methods" + print(io, "$n $meths for generic function $name:") +end diff --git a/base/show.jl b/base/show.jl index c05a0f60aff3a..d8b0aadd35187 100644 --- a/base/show.jl +++ b/base/show.jl @@ -388,82 +388,6 @@ function show_unquoted(io::IO, ex::SymbolNode) show_expr_type(io, ex.typ) end -function clean_gensym(s::Symbol) - s = string(s) - i = search(s,'#') - if i > 0 - return s[1:i-1] - end - return s -end - -function argtype_decl_string(n, t) - if isa(n,Expr) - n = n.args[1] # handle n::T in arg list - end - n = clean_gensym(n) - if t === Any && !isempty(n) - return n - end - if t <: Vararg && t !== None && t.parameters[1] === Any - return string(n, "...") - end - return string(n, "::", t) -end - -function show(io::IO, m::Method) - tv = m.tvars - if !isa(tv,Tuple) - tv = (tv,) - end - if !isempty(tv) - show_delim_array(io, tv, '{', ',', '}', false) - end - li = m.func.code - e = uncompressed_ast(li) - argnames = e.args[1] - if length(argnames) != length(m.sig) - s = symbol("?") - decls = map(argtype_decl_string, { s for i=1:length(m.sig) }, {m.sig...}) - else - decls = map(argtype_decl_string, argnames, {m.sig...}) - end - print(io, "(") - print_joined(io, decls, ",", ",") - print(io, ")") - if li.line > 0 - print(io, " at ", li.file, ":", li.line) - end -end - -function show_method_table(io::IO, mt::MethodTable, max::Int=-1, header::Bool=true) - name = mt.name - n = length(mt) - if header - m = n==1 ? "method" : "methods" - print(io, "# $n $m for generic function \"$name\":") - end - d = mt.defs - n = rest = 0 - while !is(d,()) - if max==-1 || n 0 - println(io) - print(io,"... $rest methods not shown (use methods($name) to see them all)") - end -end - -show(io::IO, mt::MethodTable) = show_method_table(io, mt) - # dump & xdump - structured tree representation like R's str() # - dump is for the user-facing structure # - xdump is for the internal structure diff --git a/base/sysimg.jl b/base/sysimg.jl index 7d7a4e4e6b746..e5da016db2fba 100644 --- a/base/sysimg.jl +++ b/base/sysimg.jl @@ -105,6 +105,7 @@ import .Grisu.print_shortest include("printf.jl") importall .Printf include("file.jl") +include("methodshow.jl") # core math functions include("floatfuncs.jl") From 4861ee2cced89f9249f07c13d23c7d46dbe30551 Mon Sep 17 00:00:00 2001 From: "Steven G. Johnson" Date: Sun, 1 Dec 2013 11:31:03 -0500 Subject: [PATCH 2/2] hopefully more robust way of getting github URL (don't assume module name is Pkg name) --- base/methodshow.jl | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/base/methodshow.jl b/base/methodshow.jl index 5ea0f129703f1..611686c067db6 100644 --- a/base/methodshow.jl +++ b/base/methodshow.jl @@ -83,14 +83,18 @@ function url(m::Method) return "https://github.com/JuliaLang/julia/tree/$(Base.BUILD_INFO.commit)/base/$file#L$line" else try - pkg = Pkg.dir(string(M)) - if file[1:length(pkg)] != pkg + d = dirname(file) + u = Git.readchomp(`config remote.origin.url`, dir=d) + u = match(Git.GITHUB_REGEX,u).captures[1] + root = cd(d) do # dir=d confuses --show-toplevel, apparently + Git.readchomp(`rev-parse --show-toplevel`) + end + if beginswith(file, root) + commit = Git.readchomp(`rev-parse HEAD`, dir=d) + return "https://github.com/$u/tree/$commit/"*file[length(root)+2:end]*"#L$line" + else return "file://"*find_source_file(file) end - u = Git.readchomp(`config remote.origin.url`, dir=pkg) - u = match(Git.GITHUB_REGEX,u).captures[1] - commit = Git.readchomp(`rev-parse HEAD`, dir=pkg) - return "https://github.com/$u/tree/$commit/"*file[length(pkg)+2:end]*"#L$line" catch return "file://"*find_source_file(file) end