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