v: run code from stdin `echo println(2+2) | v run -`, with no repl limits (#6884)
parent
55a7c907ad
commit
159932d59b
|
@ -1,8 +1,11 @@
|
|||
Usage: v [build flags] run <file.v|directory> [arguments...]
|
||||
Usage: v [build flags] run <file.v|directory|-> [arguments...]
|
||||
|
||||
This command is equivalent to running `v build` and running the compiled executable.
|
||||
The executable is passed the arguments as provided in [arguments...].
|
||||
|
||||
If the target is '-', it means that the V source code to build comes from stdin.
|
||||
If the '-o' option is not specified, and the target is '-', a temporary base name for the executable will be used.
|
||||
|
||||
The exit status of run will be:
|
||||
* `1` if the compilation failed.
|
||||
* The exit code of the compiled executable otherwise.
|
||||
|
|
|
@ -6,6 +6,7 @@ module pref
|
|||
import os.cmdline
|
||||
import os
|
||||
import v.vcache
|
||||
import rand
|
||||
|
||||
pub enum BuildMode {
|
||||
// `v program.v'
|
||||
|
@ -408,6 +409,44 @@ pub fn parse_args(args []string) (&Preferences, string) {
|
|||
}
|
||||
res.path = args[command_pos + 1]
|
||||
res.run_args = args[command_pos + 2..]
|
||||
if res.path == '-' {
|
||||
tmp_file_path := rand.ulid()
|
||||
mut tmp_exe_file_path := res.out_name
|
||||
mut output_option := ''
|
||||
if tmp_exe_file_path == '' {
|
||||
tmp_exe_file_path = '${tmp_file_path}.exe'
|
||||
output_option = '-o "$tmp_exe_file_path"'
|
||||
}
|
||||
tmp_v_file_path := '${tmp_file_path}.v'
|
||||
mut lines := []string{}
|
||||
for {
|
||||
iline := os.get_raw_line()
|
||||
if iline.len == 0 {
|
||||
break
|
||||
}
|
||||
lines << iline
|
||||
}
|
||||
contents := lines.join('')
|
||||
os.write_file(tmp_v_file_path, contents) or {
|
||||
panic('Failed to create temporary file $tmp_v_file_path')
|
||||
}
|
||||
run_options := cmdline.options_before(args, ['run']).join(' ')
|
||||
command_options := cmdline.options_after(args, ['run'])[1..].join(' ')
|
||||
vexe := vexe_path()
|
||||
tmp_cmd := '"$vexe" $output_option $run_options run "$tmp_v_file_path" $command_options'
|
||||
//
|
||||
res.vrun_elog('tmp_cmd: $tmp_cmd')
|
||||
tmp_result := os.system(tmp_cmd)
|
||||
res.vrun_elog('exit code: $tmp_result')
|
||||
//
|
||||
if output_option.len != 0 {
|
||||
res.vrun_elog('remove tmp exe file: $tmp_exe_file_path')
|
||||
os.rm(tmp_exe_file_path)
|
||||
}
|
||||
res.vrun_elog('remove tmp v file: $tmp_v_file_path')
|
||||
os.rm(tmp_v_file_path)
|
||||
exit(tmp_result)
|
||||
}
|
||||
must_exist(res.path)
|
||||
if !res.path.ends_with('.v') && os.is_executable(res.path) && os.is_file(res.path) &&
|
||||
os.is_file(res.path + '.v') {
|
||||
|
@ -430,6 +469,12 @@ pub fn parse_args(args []string) (&Preferences, string) {
|
|||
return res, command
|
||||
}
|
||||
|
||||
fn (pref &Preferences) vrun_elog(s string) {
|
||||
if pref.is_verbose {
|
||||
eprintln('> v run -, $s')
|
||||
}
|
||||
}
|
||||
|
||||
fn must_exist(path string) {
|
||||
if !os.exists(path) {
|
||||
eprintln('v expects that `$path` exists, but it does not')
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
import os
|
||||
|
||||
const (
|
||||
vexe = os.getenv('VEXE')
|
||||
)
|
||||
|
||||
fn test_vexe_is_set() {
|
||||
assert vexe != ''
|
||||
}
|
||||
|
||||
fn test_pipe_to_v_run() ? {
|
||||
cat_cmd := if os.user_os() == 'windows' { 'type' } else { 'cat' }
|
||||
tmp_v_file := os.join_path(os.temp_dir(), 'generated_piped_program.v')
|
||||
os.write_file(tmp_v_file, 'println(1 + 3)\nprintln("hello")\n') ?
|
||||
assert os.is_file(tmp_v_file)
|
||||
cmd := '"$cat_cmd" "$tmp_v_file" | "$vexe" run -'
|
||||
res := os.exec(cmd) ?
|
||||
// eprintln('>> cmd: $cmd | res: $res')
|
||||
assert res.exit_code == 0
|
||||
assert res.output.trim_space().split('\n') == ['4', 'hello']
|
||||
os.rm(tmp_v_file)
|
||||
assert !os.exists(tmp_v_file)
|
||||
}
|
Loading…
Reference in New Issue