-
-
Notifications
You must be signed in to change notification settings - Fork 293
/
Copy pathpath helpers.jl
201 lines (176 loc) Β· 5.13 KB
/
path helpers.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
import Base64: base64decode
# from https://github.com/JuliaLang/julia/pull/36425
function detectwsl()
Sys.islinux() &&
isfile("/proc/sys/kernel/osrelease") &&
occursin(r"Microsoft|WSL"i, read("/proc/sys/kernel/osrelease", String))
end
"""
maybe_convert_path_to_wsl(path)
Return the WSL path if the system is using the Windows Subsystem for Linux (WSL) and return `path` otherwise.
WSL mounts the windows drive to /mnt/ and provides a utility tool to convert windows
paths into WSL paths. This function will try to use this tool to automagically
convert paths pasted from windows (with the right click -> copy as path functionality)
into paths Pluto can understand.
Example:
$(raw"C:\Users\pankg\OneDrive\Desktop\pluto\bakery_pnl_ready2.jl")
β
"/mnt/c/Users/pankg/OneDrive/Desktop/pluto/bakery_pnl_ready2.jl"
but "/mnt/c/Users/pankg/OneDrive/Desktop/pluto/bakery_pnl_ready2.jl" stays the same
"""
function maybe_convert_path_to_wsl(path)
try
if detectwsl()
# wslpath utility prints path to stderr if it fails to convert
# (it used to fail for WSL-valid paths)
!isnothing(match(r"^/mnt/\w+/", path)) && return path
return readchomp(pipeline(`wslpath -u $(path)`; stderr=devnull))
end
catch e
return path
end
return path
end
const adjectives = [
"groundbreaking"
"revolutionary"
"important"
"novel"
"fun"
"interesting"
"fascinating"
"exciting"
"surprising"
"remarkable"
"wonderful"
"stunning"
"mini"
"small"
"tiny"
"cute"
"friendly"
"wild"
]
const nouns = [
"discovery"
"experiment"
"story"
"journal"
"notebook"
"revelation"
"computation"
"creation"
"analysis"
"invention"
"blueprint"
"report"
"science"
"magic"
"program"
"notes"
"lecture"
"theory"
"proof"
"conjecture"
]
"""
Generate a filename like `"Cute discovery"`. Does not end with `.jl`.
"""
function cutename()
titlecase(rand(adjectives)) * " " * rand(nouns)
end
function new_notebooks_directory()
try
path = joinpath(first(DEPOT_PATH), "pluto_notebooks")
if !isdir(path)
mkdir(path)
end
path
catch
homedir()
end
end
"""
Standard Pluto file extensions, including `.jl` and `.pluto.jl`. Pluto can open files with any extension, but the default extensions are used when searching for notebooks, or when trying to create a nice filename for something else, like the backup file.
"""
const pluto_file_extensions = [
".pluto.jl",
".Pluto.jl",
".nb.jl",
".jl",
".plutojl",
".pluto",
".nbjl",
".pljl",
".pluto.jl.txt", # MacOS can create these .txt files sometimes
".jl.txt",
]
endswith_pluto_file_extension(s) = any(endswith(s, e) for e in pluto_file_extensions)
function embedded_notebookfile(html_contents::AbstractString)::String
if !occursin("</html>", html_contents)
throw(ArgumentError("Pass the contents of a Pluto-exported HTML file as argument."))
end
m = match(r"pluto_notebookfile.*\"data\:.*base64\,(.*)\"", html_contents)
if m === nothing
throw(ArgumentError("Notebook does not have an embedded notebook file."))
else
String(base64decode(m.captures[1]))
end
end
"""
Does the path end with a pluto file extension (like `.jl` or `.pluto.jl`) and does the first line say `### A Pluto.jl notebook ###`?
"""
is_pluto_notebook(path::String) = endswith_pluto_file_extension(path) && readline(path) == "### A Pluto.jl notebook ###"
function without_pluto_file_extension(s)
for e in pluto_file_extensions
if endswith(s, e)
return s[1:prevind(s, ncodeunits(s), ncodeunits(e))]
end
end
s
end
"""
Return `base` * `suffix` if the file does not exist yet.
If it does, return `base * sep * string(n) * suffix`, where `n` is the smallest natural number such that the file is new. (no 0 is not a natural number you snake)
"""
function numbered_until_new(base::AbstractString; sep::AbstractString=" ", suffix::AbstractString=".jl", create_file::Bool=true, skip_original::Bool=false)
chosen = base * suffix
n = 1
while (n == 1 && skip_original) || isfile(chosen)
chosen = base * sep * string(n) * suffix
n += 1
end
if create_file
touch(chosen)
end
chosen
end
backup_filename(path) = numbered_until_new(without_pluto_file_extension(path); sep=" backup ", suffix=".jl", create_file=false, skip_original=true)
"Like `cp` except we create the file manually (to fix permission issues). (It's not plagiarism if you use this function to copy homework.)"
function readwrite(from::AbstractString, to::AbstractString)
write(to, read(from, String))
end
function tryexpanduser(path)
try
expanduser(path)
catch ex
path
end
end
tamepath = abspath β tryexpanduser
"Block until reading the file two times in a row gave the same result."
function wait_until_file_unchanged(filename::String, timeout::Real, last_contents::String="")::Nothing
new_contents = try
read(filename, String)
catch
""
end
@info "Waiting for file to stabilize..."# last_contents new_contents
if last_contents == new_contents
# yayyy
return
else
sleep(timeout)
wait_until_file_unchanged(filename, timeout, new_contents)
end
end