1module util 2 3import os 4import time 5 6// iterates through a list of known diff cli commands 7// and returns it with basic options 8pub fn find_working_diff_command() ?string { 9 env_difftool := os.getenv('VDIFF_TOOL') 10 env_diffopts := os.getenv('VDIFF_OPTIONS') 11 mut known_diff_tools := []string{} 12 if env_difftool.len > 0 { 13 known_diff_tools << env_difftool 14 } 15 known_diff_tools << [ 16 'colordiff', 'gdiff', 'diff', 'colordiff.exe', 17 'diff.exe', 'opendiff', 'code', 'code.cmd' 18 ] 19 // NOTE: code.cmd is the Windows variant of the `code` cli tool 20 for diffcmd in known_diff_tools { 21 if diffcmd == 'opendiff' { // opendiff has no `--version` option 22 if opendiff_exists() { 23 return diffcmd 24 } 25 continue 26 } 27 p := os.exec('$diffcmd --version') or { 28 continue 29 } 30 if p.exit_code == 127 && diffcmd == env_difftool { 31 // user setup is wonky, fix it 32 return error('could not find specified VDIFF_TOOL $diffcmd') 33 } 34 if p.exit_code == 0 { // success 35 if diffcmd in ['code', 'code.cmd'] { 36 // there is no guarantee that the env opts exist 37 // or include `-d`, so (harmlessly) add it 38 return '$diffcmd $env_diffopts -d' 39 } 40 return '$diffcmd $env_diffopts' 41 } 42 } 43 return error('No working "diff" command found') 44} 45 46// determine if the FileMerge opendiff tool is available 47fn opendiff_exists() bool { 48 o := os.exec('opendiff') or { 49 return false 50 } 51 if o.exit_code == 1 { // failed (expected), but found (i.e. not 127) 52 if o.output.contains('too few arguments') { // got some exptected output 53 return true 54 } 55 } 56 return false 57} 58 59pub fn color_compare_files(diff_cmd, file1, file2 string) string { 60 if diff_cmd != '' { 61 full_cmd := '$diff_cmd --minimal --text --unified=2 ' + 62 ' --show-function-line="fn " "$file1" "$file2" ' 63 x := os.exec(full_cmd) or { 64 return 'comparison command: `$full_cmd` failed' 65 } 66 return x.output.trim_right('\r\n') 67 } 68 return '' 69} 70 71pub fn color_compare_strings(diff_cmd, expected, found string) string { 72 cdir := os.cache_dir() 73 ctime := time.sys_mono_now() 74 e_file := os.join_path(cdir, '${ctime}.expected.txt') 75 f_file := os.join_path(cdir, '${ctime}.found.txt') 76 os.write_file(e_file, expected) 77 os.write_file(f_file, found) 78 res := color_compare_files(diff_cmd, e_file, f_file) 79 os.rm(e_file) 80 os.rm(f_file) 81 return res 82} 83