Skip to content

Commit ffb3458

Browse files
committed
Add support for determining name of script #14109
Note that PROGRAM_FILE was chosen as the name for this variable as it matches the help for the Julia CLI.
1 parent 5ac7f75 commit ffb3458

File tree

9 files changed

+61
-23
lines changed

9 files changed

+61
-23
lines changed

NEWS.md

+3
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,8 @@ New language features
173173

174174
* `@__LINE__` special macro now available to reflect invocation source line number ([#12727]).
175175

176+
* `PROGRAM_FILE` global is now available for determining the name of the running script ([#14114]).
177+
176178
Language changes
177179
----------------
178180

@@ -1768,3 +1770,4 @@ Too numerous to mention.
17681770
[#14413]: https://github.com/JuliaLang/julia/issues/14413
17691771
[#14424]: https://github.com/JuliaLang/julia/issues/14424
17701772
[#14759]: https://github.com/JuliaLang/julia/issues/14759
1773+
[#14114]: https://github.com/JuliaLang/julia/issues/14114

base/client.jl

+7-8
Original file line numberDiff line numberDiff line change
@@ -177,10 +177,9 @@ end
177177
# try to include() a file, ignoring if not found
178178
try_include(path::AbstractString) = isfile(path) && include(path)
179179

180-
function process_options(opts::JLOptions, args::Vector{UTF8String})
181-
if !isempty(args)
182-
arg = first(args)
183-
idxs = find(x -> x == "--", args)
180+
function process_options(opts::JLOptions)
181+
if !isempty(ARGS)
182+
idxs = find(x -> x == "--", ARGS)
184183
if length(idxs) > 1
185184
println(STDERR, "julia: redundant option terminator `--`")
186185
exit(1)
@@ -234,15 +233,15 @@ function process_options(opts::JLOptions, args::Vector{UTF8String})
234233
eval(Main, parse_input_line(bytestring(opts.postboot)))
235234
end
236235
# load file
237-
if !isempty(args) && !isempty(args[1])
236+
if !isempty(ARGS) && !isempty(ARGS[1])
238237
# program
239238
repl = false
240239
# remove filename from ARGS
241-
shift!(ARGS)
240+
global PROGRAM_FILE = UTF8String(shift!(ARGS))
242241
if !is_interactive
243242
ccall(:jl_exit_on_sigint, Void, (Cint,), 1)
244243
end
245-
include(args[1])
244+
include(PROGRAM_FILE)
246245
end
247246
break
248247
end
@@ -298,7 +297,7 @@ function _start()
298297
append!(ARGS, Core.ARGS)
299298
opts = JLOptions()
300299
try
301-
(quiet,repl,startup,color_set,history_file) = process_options(opts,copy(ARGS))
300+
(quiet,repl,startup,color_set,history_file) = process_options(opts)
302301

303302
local term
304303
global active_repl

base/docs/helpdb/Base.jl

+3-2
Original file line numberDiff line numberDiff line change
@@ -8368,8 +8368,9 @@ graphemes
83688368
"""
83698369
@__FILE__ -> AbstractString
83708370
8371-
`@__FILE__` expands to a string with the absolute path and file name of the script being
8372-
run. Returns `nothing` if run from a REPL or an empty string if evaluated by `julia -e <expr>`.
8371+
`@__FILE__` expands to a string with the absolute file path of the file containing the
8372+
macro. Returns `nothing` if run from a REPL or an empty string if evaluated by
8373+
`julia -e <expr>`. Alternatively see [`PROGRAM_FILE`](:data:`PROGRAM_FILE`).
83738374
"""
83748375
:@__FILE__
83758376

base/exports.jl

+1
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@ export
180180
JULIA_HOME,
181181
LOAD_PATH,
182182
OS_NAME,
183+
PROGRAM_FILE,
183184
STDERR,
184185
STDIN,
185186
STDOUT,

base/initdefs.jl

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
## initdefs.jl - initialization and runtime management definitions
44

5+
PROGRAM_FILE = UTF8String("")
56
const ARGS = UTF8String[]
67

78
exit(n) = ccall(:jl_exit, Void, (Int32,), n)

doc/manual/getting-started.rst

+9-6
Original file line numberDiff line numberDiff line change
@@ -51,19 +51,22 @@ argument to the julia command::
5151

5252
As the example implies, the following command-line arguments to julia
5353
are taken as command-line arguments to the program ``script.jl``, passed
54-
in the global constant ``ARGS``. ``ARGS`` is also set when script code
55-
is given using the ``-e`` option on the command line (see the ``julia``
56-
help output below). For example, to just print the arguments given to a
57-
script, you could do this::
54+
in the global constant ``ARGS``. The name of the script itself is passed
55+
in as the global ``PROGRAM_FILE``. Note that ``ARGS`` is also set when script
56+
code is given using the ``-e`` option on the command line (see the ``julia``
57+
help output below) but ``PROGRAM_FILE`` will be empty. For example, to just
58+
print the arguments given to a script, you could do this::
59+
60+
$ julia -e 'println(PROGRAM_FILE); for x in ARGS; println(x); end' foo bar
5861

59-
$ julia -e 'for x in ARGS; println(x); end' foo bar
6062
foo
6163
bar
6264

6365
Or you could put that code into a script and run it::
6466

65-
$ echo 'for x in ARGS; println(x); end' > script.jl
67+
$ echo 'println(PROGRAM_FILE); for x in ARGS; println(x); end' > script.jl
6668
$ julia script.jl foo bar
69+
script.jl
6770
foo
6871
bar
6972

doc/stdlib/constants.rst

+5
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@ Constants
1414
A symbol representing the name of the operating system. Possible values
1515
are ``:Linux``, ``:Darwin`` (OS X), or ``:Windows``.
1616

17+
.. data:: PROGRAM_FILE
18+
19+
A string containing the script name passed to Julia from the command line. Note that the
20+
script name remains unchanged from within included files. Alternatively see :data:`@__FILE__`.
21+
1722
.. data:: ARGS
1823

1924
An array of the command line arguments passed to Julia, as strings.

doc/stdlib/file.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,7 @@
337337

338338
.. Docstring generated from Julia source
339339
340-
``@__FILE__`` expands to a string with the absolute path and file name of the script being run. Returns ``nothing`` if run from a REPL or an empty string if evaluated by ``julia -e <expr>``\ .
340+
``@__FILE__`` expands to a string with the absolute file path of the file containing the macro. Returns ``nothing`` if run from a REPL or an empty string if evaluated by ``julia -e <expr>``. Alternatively see :data:`PROGRAM_FILE`.
341341

342342
.. function:: @__LINE__ -> Int
343343

test/cmdlineargs.jl

+31-6
Original file line numberDiff line numberDiff line change
@@ -204,24 +204,49 @@ let exename = `$(joinpath(JULIA_HOME, Base.julia_exename())) --precompiled=yes`
204204
# --worker takes default / custom as arugment (default/custom arguments tested in test/parallel.jl, test/examples.jl)
205205
@test !success(`$exename --worker=true`)
206206

207+
escape(str) = replace(str, "\\", "\\\\")
208+
207209
# test passing arguments
208210
let testfile = tempname()
209211
try
210-
# write a julia source file that just prints ARGS to STDOUT and exits
212+
# write a julia source file that just prints ARGS to STDOUT
211213
write(testfile, """
212214
println(ARGS)
213-
exit(0)
214215
""")
215-
@test readchomp(`$exename $testfile foo -bar --baz`) == "UTF8String[\"foo\",\"-bar\",\"--baz\"]"
216-
@test readchomp(`$exename $testfile -- foo -bar --baz`) == "UTF8String[\"foo\",\"-bar\",\"--baz\"]"
217-
@test readchomp(`$exename -L $testfile -- foo -bar --baz`) == "UTF8String[\"foo\",\"-bar\",\"--baz\"]"
216+
@test readchomp(`$exename $testfile foo -bar --baz`) == "UTF8String[\"foo\",\"-bar\",\"--baz\"]"
217+
@test readchomp(`$exename $testfile -- foo -bar --baz`) == "UTF8String[\"foo\",\"-bar\",\"--baz\"]"
218+
@test readchomp(`$exename -L $testfile -e 'exit(0)' -- foo -bar --baz`) == "UTF8String[\"foo\",\"-bar\",\"--baz\"]"
219+
@test split(readchomp(`$exename -L $testfile $testfile`), '\n') == ["UTF8String[\"$(escape(testfile))\"]", "UTF8String[]"]
218220
@test !success(`$exename --foo $testfile`)
219-
@test !success(`$exename -L $testfile -- foo -bar -- baz`)
221+
@test !success(`$exename -L $testfile -e 'exit(0)' -- foo -bar -- baz`)
220222
finally
221223
rm(testfile)
222224
end
223225
end
224226

227+
# test the script name
228+
let a = tempname(), b = tempname()
229+
try
230+
write(a, """
231+
println(@__FILE__)
232+
println(PROGRAM_FILE)
233+
println(length(ARGS))
234+
include(\"$(escape(b))\")
235+
""")
236+
write(b, """
237+
println(@__FILE__)
238+
println(PROGRAM_FILE)
239+
println(length(ARGS))
240+
""")
241+
@test split(readchomp(`$exename $a`), '\n') == ["$a", "$a", "0", "$b", "$a", "0"]
242+
@test split(readchomp(`$exename -L $b -e 'exit(0)'`), '\n') == ["$(realpath(b))", "", "0"]
243+
@test split(readchomp(`$exename -L $b $a`), '\n') == ["$(realpath(b))", "", "1", "$a", "$a", "0", "$b", "$a", "0"]
244+
finally
245+
rm(a)
246+
rm(b)
247+
end
248+
end
249+
225250
# issue #10562
226251
@test readchomp(`$exename -e 'println(ARGS);' ''`) == "UTF8String[\"\"]"
227252

0 commit comments

Comments
 (0)