Improve the run program command in vim
This commit is contained in:
		
							parent
							
								
									bc21059ea6
								
							
						
					
					
						commit
						05c46303c8
					
				
							
								
								
									
										247
									
								
								.vimrc
									
									
									
									
									
								
							
							
						
						
									
										247
									
								
								.vimrc
									
									
									
									
									
								
							| 
						 | 
					@ -689,8 +689,7 @@ fu! CreateCtags()
 | 
				
			||||||
    " First determine if we're in a root drive directory. If we are then
 | 
					    " First determine if we're in a root drive directory. If we are then
 | 
				
			||||||
    " we bail because we don't want to recurse across the entire drive!
 | 
					    " we bail because we don't want to recurse across the entire drive!
 | 
				
			||||||
    let l:path = expand('%:p:h')
 | 
					    let l:path = expand('%:p:h')
 | 
				
			||||||
    let l:path_without_slashes = substitute(l:path, "/", "", "g")
 | 
					    if IsRootDrive(l:path)
 | 
				
			||||||
    if (strchars(l:path) - strchars(l:path_without_slashes)) <= 1
 | 
					 | 
				
			||||||
        call PrintError("Not going to run ctags because the file is in a root drive directory")
 | 
					        call PrintError("Not going to run ctags because the file is in a root drive directory")
 | 
				
			||||||
        return
 | 
					        return
 | 
				
			||||||
    endif
 | 
					    endif
 | 
				
			||||||
| 
						 | 
					@ -1037,6 +1036,34 @@ command -nargs=0 EditColorScheme call EditColorScheme()
 | 
				
			||||||
"|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
 | 
					"|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
 | 
				
			||||||
"|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
 | 
					"|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fu! IsRootDrive(path) abort
 | 
				
			||||||
 | 
					    let l:path_without_slashes = substitute(a:path, "/", "", "g")
 | 
				
			||||||
 | 
					    return strchars(l:path_without_slashes) <= 1
 | 
				
			||||||
 | 
					endfu
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fu! IsPathContained(path1, path2) abort
 | 
				
			||||||
 | 
					    let l:normalized_path1 = substitute(fnamemodify(a:path1, ':p'), '\', '/', 'g')
 | 
				
			||||||
 | 
					    let l:normalized_path2 = substitute(fnamemodify(a:path2, ':p'), '\', '/', 'g')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    " Ensure paths end with a directory separator
 | 
				
			||||||
 | 
					    if l:normalized_path1[-1:] != '/'
 | 
				
			||||||
 | 
					        let l:normalized_path1 .= '/'
 | 
				
			||||||
 | 
					    endif
 | 
				
			||||||
 | 
					    if l:normalized_path2[-1:] != '/'
 | 
				
			||||||
 | 
					        let l:normalized_path2 .= '/'
 | 
				
			||||||
 | 
					    endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    echo l:normalized_path1
 | 
				
			||||||
 | 
					    echo l:normalized_path2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return match(l:normalized_path1, '^' . escape(l:normalized_path2, '\')) != -1
 | 
				
			||||||
 | 
					endfu
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fu! CountChar(str, char) abort
 | 
				
			||||||
 | 
					    " Remove all characters that are not the target character.
 | 
				
			||||||
 | 
					    let l:filtered = substitute(a:str, '[^' . a:char . ']', '', 'g')
 | 
				
			||||||
 | 
					    return strlen(l:filtered)
 | 
				
			||||||
 | 
					endfu
 | 
				
			||||||
 | 
					
 | 
				
			||||||
"##################################################################################
 | 
					"##################################################################################
 | 
				
			||||||
" COMPILING CODE
 | 
					" COMPILING CODE
 | 
				
			||||||
| 
						 | 
					@ -1242,68 +1269,172 @@ fu! Build(optimized=0, silent=0)
 | 
				
			||||||
    exec l:async_cmd . l:cmd
 | 
					    exec l:async_cmd . l:cmd
 | 
				
			||||||
endfu
 | 
					endfu
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fu! RunProgram()
 | 
					fu! RunProgram() abort
 | 
				
			||||||
    let l:ran = 0
 | 
					    if tolower(expand('%:e')) == "py"
 | 
				
			||||||
    let l:ext = tolower(expand('%:e'))
 | 
					 | 
				
			||||||
    let l:path_to_use = ""
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if l:ext == "jai"
 | 
					 | 
				
			||||||
        " Maybe the current file has an exe, i.e. wasn't compiled with a build script.
 | 
					 | 
				
			||||||
        if filereadable(expand('%:p:r') . '.exe')
 | 
					 | 
				
			||||||
            let l:ran = 1
 | 
					 | 
				
			||||||
            exec "AsyncRun! " . expand('%:p:r') . ".exe"
 | 
					 | 
				
			||||||
        elseif tolower(expand('%:h:t')) == "modules" || tolower(expand('%:h:h:t')) == "modules"
 | 
					 | 
				
			||||||
            " This is likely a jai module inside a project. We will want to do the exe/run script checks in the parent project folder.
 | 
					 | 
				
			||||||
            " The :h:h tests for a module inside a folder, e.g. modules/Basic/module.jai
 | 
					 | 
				
			||||||
            echo "module"
 | 
					 | 
				
			||||||
            if tolower(expand('%:h:t')) == "modules"
 | 
					 | 
				
			||||||
                let l:path_to_use = "/.."
 | 
					 | 
				
			||||||
            else
 | 
					 | 
				
			||||||
                let l:path_to_use = "/../.."
 | 
					 | 
				
			||||||
            endif
 | 
					 | 
				
			||||||
        endif
 | 
					 | 
				
			||||||
    elseif l:ext == "py"
 | 
					 | 
				
			||||||
        let l:ran = 1
 | 
					 | 
				
			||||||
        exec "AsyncRun! python %"
 | 
					        exec "AsyncRun! python %"
 | 
				
			||||||
 | 
					        return
 | 
				
			||||||
    endif
 | 
					    endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if l:ran == 0
 | 
					    let l:file_exe_name = expand('%:t:r').'.exe'   " Just the filename without the path
 | 
				
			||||||
        " First check the current file's directory (and one directory back)
 | 
					
 | 
				
			||||||
        " for a run script, falling back to the current working directory (and
 | 
					    " Easy case is the current file has an exe with the same name in the
 | 
				
			||||||
        " one directory back) of the editor.
 | 
					    " same directory. We run that if found.
 | 
				
			||||||
        if filereadable(expand('%:h') . '/run')
 | 
					    if filereadable(expand('%:p:h') . '/' . l:file_exe_name)
 | 
				
			||||||
            echo "file here"
 | 
					        exec 'AsyncRun! ' . expand('%:p:h') . '/' . l:file_exe_name
 | 
				
			||||||
            exec "AsyncRun! " . expand('%:h') . "/run"
 | 
					        return
 | 
				
			||||||
        elseif filereadable(expand('%:h') . '/../run')
 | 
					    endif
 | 
				
			||||||
            " Handles editing a file in a code/ or src/ and there's a run script one directory back.
 | 
					
 | 
				
			||||||
            echo "file one back"
 | 
					    " We start by looking for something to run relative to the current file's
 | 
				
			||||||
            exec "AsyncRun! " . expand('%:h') . "/../run"
 | 
					    " path. If nothing is found then we start over looking in the current
 | 
				
			||||||
        elseif filereadable("run")
 | 
					    " working directory (the directory vim was opened in).
 | 
				
			||||||
            echo "cwd here"
 | 
					    let l:current_path = expand('%:p:h')
 | 
				
			||||||
            exec "AsyncRun! ./run"
 | 
					
 | 
				
			||||||
        elseif filereadable("../run")
 | 
					    if !RunProgramInDirectory(l:current_path, l:file_exe_name)
 | 
				
			||||||
            " Handles editing a file in a code/ or src/ and there's a run script one directory back.
 | 
					        let l:cwd = getcwd()
 | 
				
			||||||
            echo "cwd one back"
 | 
					        if !RunProgramInDirectory(l:cwd, l:file_exe_name)
 | 
				
			||||||
            exec "AsyncRun! ../run"
 | 
					            call PrintError("No exe or run script found in current file path '" . l:current_path . "' or working directory '". l:cwd ."'")
 | 
				
			||||||
        else
 | 
					 | 
				
			||||||
            " Final attempt is to run any exe that's found nearby.
 | 
					 | 
				
			||||||
            " We start with an exe relative to the open file's path.
 | 
					 | 
				
			||||||
            let l:files = systemlist('ls '.expand('%:h').''.l:path_to_use.'/*.exe 2>/dev/null')
 | 
					 | 
				
			||||||
            if len(l:files) > 0
 | 
					 | 
				
			||||||
                exec "AsyncRun! " . l:files[0]
 | 
					 | 
				
			||||||
            else
 | 
					 | 
				
			||||||
                " Last attempt is any exe in the current working directory.
 | 
					 | 
				
			||||||
                let l:files = systemlist('ls *.exe 2>/dev/null')
 | 
					 | 
				
			||||||
                if len(l:files) > 0
 | 
					 | 
				
			||||||
                    exec "AsyncRun! " . l:files[0]
 | 
					 | 
				
			||||||
                else
 | 
					 | 
				
			||||||
                    call PrintError("No exe or run script found!")
 | 
					 | 
				
			||||||
                endif
 | 
					 | 
				
			||||||
            endif
 | 
					 | 
				
			||||||
        endif
 | 
					        endif
 | 
				
			||||||
    endif
 | 
					    endif
 | 
				
			||||||
endfu
 | 
					endfu
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fu! RunProgramInDirectory(starting_path, file_exe_name) abort
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let l:search_path = a:starting_path
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if tolower(expand('%:e')) == "jai"
 | 
				
			||||||
 | 
					        " Check if we're editing inside a modules file and if so then get a
 | 
				
			||||||
 | 
					        " path that takes us outside of it. We'll use that path for finding an
 | 
				
			||||||
 | 
					        " exe or run script.
 | 
				
			||||||
 | 
					        let l:pos = match(l:search_path, "modules")
 | 
				
			||||||
 | 
					        if l:pos != -1
 | 
				
			||||||
 | 
					            " e.g. if the current path is
 | 
				
			||||||
 | 
					            " /z/jai/examples/wasm/modules/Blah/blah.jai then this is /z/jai/examples/wasm/
 | 
				
			||||||
 | 
					            let l:module_root_path = l:search_path[:l:pos-1]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            " We don't want to proceed if the path is in the jai compiler's modules folder.
 | 
				
			||||||
 | 
					            let l:jai_path = tolower(g:campo_jai_path)
 | 
				
			||||||
 | 
					            if l:jai_path[-1:] != '/'
 | 
				
			||||||
 | 
					                let l:jai_path .= '/'
 | 
				
			||||||
 | 
					            endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            "echo 'modules root path: ' . l:module_root_path . ' | jai path: ' . l:jai_path
 | 
				
			||||||
 | 
					            if tolower(l:module_root_path) == l:jai_path
 | 
				
			||||||
 | 
					                "echo 'inside jai modules. Aborting run'
 | 
				
			||||||
 | 
					                return 0
 | 
				
			||||||
 | 
					            endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            let l:search_path = l:module_root_path
 | 
				
			||||||
 | 
					        endif
 | 
				
			||||||
 | 
					    endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let l:search_path = fnamemodify(l:search_path, ':p') " Normalize the path just in case.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    " Search the current path for a run script, an exe with the current
 | 
				
			||||||
 | 
					    " filename, a bin/filename exe, a run_tree/filename exe - if nothing is
 | 
				
			||||||
 | 
					    " found then repeat one directory back when the current folder doesn't
 | 
				
			||||||
 | 
					    " contain a .git/ or it's not a root directory, e.g. /z/.
 | 
				
			||||||
 | 
					    "
 | 
				
			||||||
 | 
					    " If nothing is found after exhausting the search then we start over and
 | 
				
			||||||
 | 
					    " find the first exe with any name.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let l:current_path = l:search_path
 | 
				
			||||||
 | 
					    while 1
 | 
				
			||||||
 | 
					        " Run script has higher priority over an exe named after the current file.
 | 
				
			||||||
 | 
					        let l:search = l:current_path . 'run'
 | 
				
			||||||
 | 
					        if filereadable(l:search)
 | 
				
			||||||
 | 
					            exec "AsyncRun! " . l:search
 | 
				
			||||||
 | 
					            return 1
 | 
				
			||||||
 | 
					        endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        " filename exe
 | 
				
			||||||
 | 
					        let l:search = l:current_path . a:file_exe_name
 | 
				
			||||||
 | 
					        if filereadable(l:search)
 | 
				
			||||||
 | 
					            exec "AsyncRun! " . l:search
 | 
				
			||||||
 | 
					            return 1
 | 
				
			||||||
 | 
					        endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        " bin/filename exe
 | 
				
			||||||
 | 
					        let l:search = l:current_path . 'bin/' . a:file_exe_name
 | 
				
			||||||
 | 
					        if filereadable(l:search)
 | 
				
			||||||
 | 
					            exec "AsyncRun! " . l:search
 | 
				
			||||||
 | 
					            return 1
 | 
				
			||||||
 | 
					        endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        " run_tree/filename exe
 | 
				
			||||||
 | 
					        let l:search = l:current_path . 'run_tree/' . a:file_exe_name
 | 
				
			||||||
 | 
					        if filereadable(l:search)
 | 
				
			||||||
 | 
					            exec "AsyncRun! " . l:search
 | 
				
			||||||
 | 
					            return 1
 | 
				
			||||||
 | 
					        endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        " Only go back a directory if the current path doesn't have a .git folder or we're not in a root drive path.
 | 
				
			||||||
 | 
					        if isdirectory(l:current_path . '.git') || IsRootDrive(l:current_path)
 | 
				
			||||||
 | 
					            break
 | 
				
			||||||
 | 
					        endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let l:current_path = fnamemodify(l:current_path."../", ':p')
 | 
				
			||||||
 | 
					    endwhile
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
 | 
				
			||||||
 | 
					    " Start over but look for the first exe. The user will confirm if they
 | 
				
			||||||
 | 
					    " want to run it.
 | 
				
			||||||
 | 
					    "
 | 
				
			||||||
 | 
					    " @improve maybe provide the first 4 or 5 exes found and let them input
 | 
				
			||||||
 | 
					    " which one they want?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fu! GetFirstExePath(path)
 | 
				
			||||||
 | 
					        let l:files = systemlist('ls '.a:path.'*.exe 2>/dev/null')
 | 
				
			||||||
 | 
					        if len(l:files) > 0
 | 
				
			||||||
 | 
					            return l:files[0]
 | 
				
			||||||
 | 
					        endif
 | 
				
			||||||
 | 
					        return ""
 | 
				
			||||||
 | 
					    endfu
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let l:current_path = l:search_path
 | 
				
			||||||
 | 
					    let l:exe_to_confirm = ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    while 1
 | 
				
			||||||
 | 
					        let l:exe = GetFirstExePath(l:current_path)
 | 
				
			||||||
 | 
					        if l:exe != ""
 | 
				
			||||||
 | 
					            let l:exe_to_confirm = l:exe
 | 
				
			||||||
 | 
					            break
 | 
				
			||||||
 | 
					        endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        " bin/filename exe
 | 
				
			||||||
 | 
					        let l:exe = GetFirstExePath(l:current_path."bin/")
 | 
				
			||||||
 | 
					        if l:exe != ""
 | 
				
			||||||
 | 
					            let l:exe_to_confirm = l:exe
 | 
				
			||||||
 | 
					            break
 | 
				
			||||||
 | 
					        endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        " run_tree/filename exe
 | 
				
			||||||
 | 
					        let l:exe = GetFirstExePath(l:current_path."run_tree/")
 | 
				
			||||||
 | 
					        if l:exe != ""
 | 
				
			||||||
 | 
					            let l:exe_to_confirm = l:exe
 | 
				
			||||||
 | 
					            break
 | 
				
			||||||
 | 
					        endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        " Only go back a directory if the current path doesn't have a .git folder or we're not in a root drive path.
 | 
				
			||||||
 | 
					        if isdirectory(l:current_path . '.git') || IsRootDrive(l:current_path)
 | 
				
			||||||
 | 
					            break
 | 
				
			||||||
 | 
					        endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let l:current_path = fnamemodify(l:current_path."../", ':p')
 | 
				
			||||||
 | 
					    endwhile
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if l:exe_to_confirm != ""
 | 
				
			||||||
 | 
					        let l:confirm = confirm("Found exe ".l:exe_to_confirm." - run this?", "&Yes\n&No")
 | 
				
			||||||
 | 
					        if l:confirm == 1
 | 
				
			||||||
 | 
					            exec "AsyncRun! " . l:exe_to_confirm
 | 
				
			||||||
 | 
					            return 1
 | 
				
			||||||
 | 
					        endif
 | 
				
			||||||
 | 
					        redraw!
 | 
				
			||||||
 | 
					    endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return 0
 | 
				
			||||||
 | 
					endfu
 | 
				
			||||||
 | 
					
 | 
				
			||||||
" Show results window the moment the async job starts
 | 
					" Show results window the moment the async job starts
 | 
				
			||||||
augroup asyncPluginCmds
 | 
					augroup asyncPluginCmds
 | 
				
			||||||
    autocmd!
 | 
					    autocmd!
 | 
				
			||||||
| 
						 | 
					@ -1528,9 +1659,9 @@ fu! RenameFile()
 | 
				
			||||||
        if l:confirm == 1
 | 
					        if l:confirm == 1
 | 
				
			||||||
            exec 'saveas' l:new_name
 | 
					            exec 'saveas' l:new_name
 | 
				
			||||||
            exec 'silent! !rm' l:old_name
 | 
					            exec 'silent! !rm' l:old_name
 | 
				
			||||||
            redraw!
 | 
					 | 
				
			||||||
        endif
 | 
					        endif
 | 
				
			||||||
    endif
 | 
					    endif
 | 
				
			||||||
 | 
					    redraw!
 | 
				
			||||||
endfu
 | 
					endfu
 | 
				
			||||||
noremap <leader>n :call RenameFile()<cr>
 | 
					noremap <leader>n :call RenameFile()<cr>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user