|
| 1 | +# editing |
| 2 | + |
| 3 | +function edit(file::String, line::Integer) |
| 4 | + if OS_NAME == :Windows || OS_NAME == :Darwin |
| 5 | + default_editor = "open" |
| 6 | + elseif isreadable("/etc/alternatives/editor") |
| 7 | + default_editor = "/etc/alternatives/editor" |
| 8 | + else |
| 9 | + default_editor = "emacs" |
| 10 | + end |
| 11 | + editor = get(ENV,"JULIA_EDITOR", get(ENV,"VISUAL", get(ENV,"EDITOR", default_editor))) |
| 12 | + if ispath(editor) |
| 13 | + if isreadable(editor) |
| 14 | + edpath = realpath(editor) |
| 15 | + edname = basename(edpath) |
| 16 | + else |
| 17 | + error("can't find \"$editor\"") |
| 18 | + end |
| 19 | + else |
| 20 | + edpath = edname = editor |
| 21 | + end |
| 22 | + issrc = length(file)>2 && file[end-2:end] == ".jl" |
| 23 | + if issrc |
| 24 | + file = find_source_file(file) |
| 25 | + end |
| 26 | + if beginswith(edname, "emacs") |
| 27 | + jmode = joinpath(JULIA_HOME, "..", "..", "contrib", "julia-mode.el") |
| 28 | + if issrc && isreadable(jmode) |
| 29 | + run(`$edpath $file --eval "(progn |
| 30 | + (require 'julia-mode \"$jmode\") |
| 31 | + (julia-mode) |
| 32 | + (goto-line $line))"`) |
| 33 | + else |
| 34 | + run(`$edpath $file --eval "(goto-line $line)"`) |
| 35 | + end |
| 36 | + elseif edname == "vim" |
| 37 | + run(`$edpath $file +$line`) |
| 38 | + elseif edname == "textmate" || edname == "mate" |
| 39 | + spawn(`$edpath $file -l $line`) |
| 40 | + elseif beginswith(edname, "subl") |
| 41 | + spawn(`$edpath $file:$line`) |
| 42 | + elseif OS_NAME == :Windows && (edname == "start" || edname == "open") |
| 43 | + spawn(`start /b $file`) |
| 44 | + elseif OS_NAME == :Darwin && (edname == "start" || edname == "open") |
| 45 | + spawn(`open -t $file`) |
| 46 | + elseif edname == "kate" |
| 47 | + spawn(`$edpath $file -l $line`) |
| 48 | + elseif edname == "nano" |
| 49 | + run(`$edpath +$line $file`) |
| 50 | + else |
| 51 | + run(`$(shell_split(edpath)) $file`) |
| 52 | + end |
| 53 | + nothing |
| 54 | +end |
| 55 | +edit(file::String) = edit(file, 1) |
| 56 | + |
| 57 | +function less(file::String, line::Integer) |
| 58 | + pager = get(ENV, "PAGER", "less") |
| 59 | + run(`$pager +$(line)g $file`) |
| 60 | +end |
| 61 | +less(file::String) = less(file, 1) |
| 62 | + |
| 63 | +edit(f::Union(Function,DataType)) = edit(functionloc(f)...) |
| 64 | +edit(f::Union(Function,DataType), t) = edit(functionloc(f,t)...) |
| 65 | +less(f::Union(Function,DataType)) = less(functionloc(f)...) |
| 66 | +less(f::Union(Function,DataType), t) = less(functionloc(f,t)...) |
| 67 | + |
| 68 | +function edit( m::Method ) |
| 69 | + tv, decls, file, line = arg_decl_parts(m) |
| 70 | + edit( string(file), line ) |
| 71 | +end |
| 72 | + |
| 73 | + |
| 74 | +# clipboard copy and paste |
| 75 | + |
| 76 | +@osx_only begin |
| 77 | + function clipboard(x) |
| 78 | + w,p = writesto(`pbcopy`) |
| 79 | + print(w,x) |
| 80 | + close(w) |
| 81 | + wait(p) |
| 82 | + end |
| 83 | + clipboard() = readall(`pbpaste`) |
| 84 | +end |
| 85 | + |
| 86 | +@linux_only begin |
| 87 | + _clipboardcmd = nothing |
| 88 | + function clipboardcmd() |
| 89 | + global _clipboardcmd |
| 90 | + _clipboardcmd !== nothing && return _clipboardcmd |
| 91 | + for cmd in (:xclip, :xsel) |
| 92 | + success(`which $cmd` |> DevNull) && return _clipboardcmd = cmd |
| 93 | + end |
| 94 | + error("no clipboard command found, please install xsel or xclip") |
| 95 | + end |
| 96 | + function clipboard(x) |
| 97 | + c = clipboardcmd() |
| 98 | + cmd = c == :xsel ? `xsel --nodetach --input --clipboard` : |
| 99 | + c == :xclip ? `xclip -quiet -in -selection clipboard` : |
| 100 | + error("unexpected clipboard command: $c") |
| 101 | + w,p = writesto(cmd) |
| 102 | + print(w,x) |
| 103 | + close(w) |
| 104 | + wait(p) |
| 105 | + end |
| 106 | + function clipboard() |
| 107 | + c = clipboardcmd() |
| 108 | + cmd = c == :xsel ? `xsel --nodetach --output --clipboard` : |
| 109 | + c == :xclip ? `xclip -quiet -out -selection clipboard` : |
| 110 | + error("unexpected clipboard command: $c") |
| 111 | + readall(cmd) |
| 112 | + end |
| 113 | +end |
| 114 | + |
| 115 | +@windows_only begin |
| 116 | + function clipboard(x::String) |
| 117 | + ccall((:OpenClipboard, "user32"), stdcall, Bool, (Ptr{Void},), C_NULL) |
| 118 | + ccall((:EmptyClipboard, "user32"), stdcall, Bool, ()) |
| 119 | + p = ccall((:GlobalAlloc, "kernel32"), stdcall, Ptr{Void}, (Uint16,Int32), 2, length(x)+1) |
| 120 | + p = ccall((:GlobalLock, "kernel32"), stdcall, Ptr{Void}, (Ptr{Void},), p) |
| 121 | + # write data to locked, allocated space |
| 122 | + ccall(:memcpy, Ptr{Void}, (Ptr{Void},Ptr{Uint8},Int32), p, x, length(x)+1) |
| 123 | + ccall((:GlobalUnlock, "kernel32"), stdcall, Void, (Ptr{Void},), p) |
| 124 | + # set clipboard data type to 13 for Unicode text/string |
| 125 | + p = ccall((:SetClipboardData, "user32"), stdcall, Ptr{Void}, (Uint32, Ptr{Void}), 1, p) |
| 126 | + ccall((:CloseClipboard, "user32"), stdcall, Void, ()) |
| 127 | + end |
| 128 | + clipboard(x) = clipboard(sprint(io->print(io,x))::ByteString) |
| 129 | + |
| 130 | + function clipboard() |
| 131 | + ccall((:OpenClipboard, "user32"), stdcall, Bool, (Ptr{Void},), C_NULL) |
| 132 | + s = bytestring(ccall((:GetClipboardData, "user32"), stdcall, Ptr{Uint8}, (Uint32,), 1)) |
| 133 | + ccall((:CloseClipboard, "user32"), stdcall, Void, ()) |
| 134 | + return s |
| 135 | + end |
| 136 | +end |
| 137 | + |
| 138 | +if !isdefined(:clipboard) |
| 139 | + clipboard(x="") = error("clipboard functionality not implemented for $OS_NAME") |
| 140 | +end |
| 141 | + |
| 142 | +# system information |
| 143 | + |
| 144 | +function versioninfo(io::IO=STDOUT, verbose::Bool=false) |
| 145 | + println(io, "Julia Version $VERSION") |
| 146 | + if !isempty(GIT_VERSION_INFO.commit_short) |
| 147 | + println(io, "Commit $(GIT_VERSION_INFO.commit_short) ($(GIT_VERSION_INFO.date_string))") |
| 148 | + end |
| 149 | + if ccall(:jl_is_debugbuild, Cint, ())!=0 |
| 150 | + println(io, "DEBUG build") |
| 151 | + end |
| 152 | + println(io, "Platform Info:") |
| 153 | + println(io, " System: ", Sys.OS_NAME, " (", Sys.MACHINE, ")") |
| 154 | + |
| 155 | + cpu = Sys.cpu_info() |
| 156 | + println(io, " CPU: ", cpu[1].model) |
| 157 | + println(io, " WORD_SIZE: ", Sys.WORD_SIZE) |
| 158 | + if verbose |
| 159 | + lsb = "" |
| 160 | + @linux_only try lsb = readchomp(`lsb_release -ds` .> DevNull) end |
| 161 | + @windows_only try lsb = strip(readall(`$(ENV["COMSPEC"]) /c ver`)) end |
| 162 | + if lsb != "" |
| 163 | + println(io, " ", lsb) |
| 164 | + end |
| 165 | + println(io, " uname: ",readchomp(`uname -mprsv`)) |
| 166 | + println(io, "Memory: $(Sys.total_memory()/2^30) GB ($(Sys.free_memory()/2^20) MB free)") |
| 167 | + try println(io, "Uptime: $(Sys.uptime()) sec") catch end |
| 168 | + print(io, "Load Avg: ") |
| 169 | + print_matrix(io, Sys.loadavg()') |
| 170 | + println(io ) |
| 171 | + Sys.cpu_summary(io) |
| 172 | + println(io ) |
| 173 | + end |
| 174 | + if Base.libblas_name == "libopenblas" || blas_vendor() == :openblas |
| 175 | + openblas_config = openblas_get_config() |
| 176 | + println(io, " BLAS: libopenblas (", openblas_config, ")") |
| 177 | + else |
| 178 | + println(io, " BLAS: ",libblas_name) |
| 179 | + end |
| 180 | + println(io, " LAPACK: ",liblapack_name) |
| 181 | + println(io, " LIBM: ",libm_name) |
| 182 | + if verbose |
| 183 | + println(io, "Environment:") |
| 184 | + for (k,v) in ENV |
| 185 | + if !is(match(r"JULIA|PATH|FLAG|^TERM$|HOME",bytestring(k)), nothing) |
| 186 | + println(io, " $(k) = $(v)") |
| 187 | + end |
| 188 | + end |
| 189 | + println(io ) |
| 190 | + println(io, "Package Directory: ", Pkg.dir()) |
| 191 | + Pkg.status(io) |
| 192 | + end |
| 193 | +end |
| 194 | +versioninfo(verbose::Bool) = versioninfo(STDOUT,verbose) |
| 195 | + |
| 196 | +# searching definitions |
| 197 | + |
| 198 | +function which(f::Callable, args...) |
| 199 | + if !isgeneric(f) |
| 200 | + throw(ErrorException("not a generic function, no methods available")) |
| 201 | + end |
| 202 | + ms = methods(f, map(a->(isa(a,Type) ? Type{a} : typeof(a)), args)) |
| 203 | + isempty(ms) && throw(MethodError(f, args)) |
| 204 | + ms[1] |
| 205 | +end |
| 206 | + |
| 207 | +macro which(ex0) |
| 208 | + if isa(ex0,Expr) && |
| 209 | + any(a->(Meta.isexpr(a,:kw) || Meta.isexpr(a,:parameters)), ex0.args) |
| 210 | + # keyword args not used in dispatch, so just remove them |
| 211 | + args = filter(a->!(Meta.isexpr(a,:kw) || Meta.isexpr(a,:parameters)), ex0.args) |
| 212 | + return Expr(:call, :which, map(esc, args)...) |
| 213 | + end |
| 214 | + if isa(ex0, Expr) && ex0.head == :call |
| 215 | + return Expr(:call, :which, map(esc, ex0.args)...) |
| 216 | + end |
| 217 | + ex = expand(ex0) |
| 218 | + exret = Expr(:call, :error, "expression is not a function call") |
| 219 | + if !isa(ex, Expr) |
| 220 | + # do nothing -> error |
| 221 | + elseif ex.head == :call |
| 222 | + if any(e->(isa(e,Expr) && e.head==:(...)), ex0.args) && |
| 223 | + isa(ex.args[1],TopNode) && ex.args[1].name == :apply |
| 224 | + exret = Expr(:call, ex.args[1], :which, |
| 225 | + Expr(:tuple, esc(ex.args[2])), |
| 226 | + map(esc, ex.args[3:end])...) |
| 227 | + else |
| 228 | + exret = Expr(:call, :which, map(esc, ex.args)...) |
| 229 | + end |
| 230 | + elseif ex.head == :body |
| 231 | + a1 = ex.args[1] |
| 232 | + if isa(a1, Expr) && a1.head == :call |
| 233 | + a11 = a1.args[1] |
| 234 | + if a11 == :setindex! |
| 235 | + exret = Expr(:call, :which, a11, map(esc, a1.args[2:end])...) |
| 236 | + end |
| 237 | + end |
| 238 | + elseif ex.head == :thunk |
| 239 | + exret = Expr(:call, :error, "expression is not a function call, or is too complex for @which to analyze; " |
| 240 | + * "break it down to simpler parts if possible") |
| 241 | + end |
| 242 | + exret |
| 243 | +end |
| 244 | + |
| 245 | +# `methodswith` -- shows a list of methods using the type given |
| 246 | + |
| 247 | +function methodswith(t::Type, m::Module, showparents::Bool=false) |
| 248 | + meths = Method[] |
| 249 | + for nm in names(m) |
| 250 | + try |
| 251 | + mt = eval(m, nm) |
| 252 | + d = mt.env.defs |
| 253 | + while !is(d,()) |
| 254 | + if any(map(x -> x == t || (showparents && t <: x && x != Any && x != ANY && !isa(x, TypeVar)), d.sig)) |
| 255 | + push!(meths, d) |
| 256 | + end |
| 257 | + d = d.next |
| 258 | + end |
| 259 | + end |
| 260 | + end |
| 261 | + return meths |
| 262 | +end |
| 263 | + |
| 264 | +function methodswith(t::Type, showparents::Bool=false) |
| 265 | + meths = Method[] |
| 266 | + mainmod = current_module() |
| 267 | + # find modules in Main |
| 268 | + for nm in names(mainmod) |
| 269 | + if isdefined(mainmod,nm) |
| 270 | + mod = eval(mainmod, nm) |
| 271 | + if isa(mod, Module) |
| 272 | + meths = [meths, methodswith(t, mod, showparents)] |
| 273 | + end |
| 274 | + end |
| 275 | + end |
| 276 | + return meths |
| 277 | +end |
| 278 | + |
| 279 | +## file downloading ## |
| 280 | + |
| 281 | +downloadcmd = nothing |
| 282 | +function download(url::String, filename::String) |
| 283 | + global downloadcmd |
| 284 | + if downloadcmd === nothing |
| 285 | + for checkcmd in (:curl, :wget, :fetch) |
| 286 | + if success(`which $checkcmd` |> DevNull) |
| 287 | + downloadcmd = checkcmd |
| 288 | + break |
| 289 | + end |
| 290 | + end |
| 291 | + end |
| 292 | + if downloadcmd == :wget |
| 293 | + run(`wget -O $filename $url`) |
| 294 | + elseif downloadcmd == :curl |
| 295 | + run(`curl -o $filename -L $url`) |
| 296 | + elseif downloadcmd == :fetch |
| 297 | + run(`fetch -f $filename $url`) |
| 298 | + else |
| 299 | + error("no download agent available; install curl, wget, or fetch") |
| 300 | + end |
| 301 | + filename |
| 302 | +end |
| 303 | +function download(url::String) |
| 304 | + filename = tempname() |
| 305 | + download(url, filename) |
| 306 | +end |
0 commit comments