Created
November 13, 2025 02:22
-
-
Save lopesivan/0f91bf7e82e3bccb39e0c0d1469e6a61 to your computer and use it in GitHub Desktop.
correção:
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| " filein.vim - Navigate between files in the same directory | |
| " Maintainer: Ivan Lopes | |
| " Description: Provides mappings to jump to next/previous files alphabetically | |
| " Similar to ]b and [b for buffers, but for filesystem navigation | |
| " Prevent double loading and check compatibility | |
| if exists("g:loaded_filein") || v:version < 700 || &cp | |
| finish | |
| endif | |
| let g:loaded_filein = 1 | |
| " ============================================================================ | |
| " Core Functions | |
| " ============================================================================ | |
| " GetDirectoryFiles: Get all non-directory files in a given path | |
| " Filters out hidden parent directories (. and ..) and applies Vim's | |
| " 'suffixes' option to ignore backup/temporary files | |
| " | |
| " Args: | |
| " path: Directory path to scan | |
| " Returns: | |
| " List of file paths (excluding directories) | |
| function! GetDirectoryFiles(path) abort | |
| " Remove trailing slashes for consistency | |
| let path = substitute(a:path, '[\\/]$', '', '') | |
| " Get hidden files (.*) and regular files (*) | |
| let files = split(glob(path . "/.*"), "\n") | |
| let files += split(glob(path . "/*"), "\n") | |
| " Clean up trailing slashes from results | |
| call map(files, 'substitute(v:val, "[\\/]$", "", "")') | |
| " Remove . and .. entries | |
| call filter(files, 'v:val !~# "[\\\\/]\\.\\.\\=$"') | |
| " Remove directories, keep only files | |
| call filter(files, '!isdirectory(v:val)') | |
| " Filter out files matching suffixes (.bak, .swp, etc) | |
| let filter_suffixes = substitute(escape(&suffixes, '~.*$^'), ',', '$\\|', 'g') . '$' | |
| call filter(files, 'v:val !~# filter_suffixes') | |
| return files | |
| endfunction | |
| " NavigateToFileByOffset: Navigate to a file N positions away from current | |
| " Wraps around directory boundaries - if at last file and going forward, | |
| " stays at last file (same for first file going backward) | |
| " | |
| " Args: | |
| " offset: Number of files to skip (positive = forward, negative = backward) | |
| " Returns: | |
| " Full path to target file | |
| function! NavigateToFileByOffset(offset) abort | |
| " Get current file or use current directory if no file open | |
| let current_file = expand('%:p') | |
| if empty(current_file) | |
| let current_file = getcwd() . '/' | |
| endif | |
| let remaining_steps = a:offset | |
| let target_file = current_file | |
| " Process one step at a time (allows skipping multiple files) | |
| while remaining_steps != 0 | |
| let files = GetDirectoryFiles(fnamemodify(target_file, ':h')) | |
| if a:offset < 0 | |
| " Going backward: get files before current, reverse sorted | |
| call reverse(sort(filter(files, 'v:val <# target_file'))) | |
| else | |
| " Going forward: get files after current, sorted | |
| call sort(filter(files, 'v:val ># target_file')) | |
| endif | |
| " Move to next/prev file if available | |
| if !empty(get(files, 0, '')) | |
| let target_file = get(files, 0, '') | |
| endif | |
| " Decrement/increment counter toward zero | |
| let remaining_steps += (remaining_steps > 0 ? -1 : 1) | |
| endwhile | |
| return target_file | |
| endfunction | |
| " GetFirstOrLastFile: Get the first or last file in current directory | |
| " Useful for jumping to directory boundaries | |
| " | |
| " Args: | |
| " direction: 1 for last file, -1 for first file | |
| " Returns: | |
| " Full path to first/last file | |
| function! GetFirstOrLastFile(direction) abort | |
| let current_file = expand('%:p') | |
| if empty(current_file) | |
| let current_file = getcwd() . '/' | |
| endif | |
| let files = GetDirectoryFiles(fnamemodify(current_file, ':h')) | |
| if a:direction > 0 | |
| " Get last file | |
| call reverse(sort(files)) | |
| else | |
| " Get first file | |
| call sort(files) | |
| endif | |
| return get(files, 0, '') | |
| endfunction | |
| " EscapeFilename: Properly escape filename for use in Ex commands | |
| " Wrapper for compatibility with older Vim versions | |
| " | |
| " Args: | |
| " file: Filename to escape | |
| " Returns: | |
| " Escaped filename string | |
| function! EscapeFilename(file) abort | |
| if exists('*fnameescape') | |
| return fnameescape(a:file) | |
| else | |
| " Manual escaping for Vim < 7.1.299 | |
| return escape(a:file, " \t\n*?[{`$\\%#'\"|!<") | |
| endif | |
| endfunction | |
| " ============================================================================ | |
| " Key Mappings | |
| " ============================================================================ | |
| " ]f - Edit next file in directory (alphabetically) | |
| " Supports count: 3]f jumps 3 files forward | |
| nnoremap <silent> ]f :<C-U>edit <C-R>=EscapeFilename(fnamemodify(NavigateToFileByOffset(v:count1), ':.'))<CR><CR> | |
| " [f - Edit previous file in directory (alphabetically) | |
| " Supports count: 2[f jumps 2 files backward | |
| nnoremap <silent> [f :<C-U>edit <C-R>=EscapeFilename(fnamemodify(NavigateToFileByOffset(-v:count1), ':.'))<CR><CR> | |
| " Optional mappings for jumping to first/last file in directory | |
| " Uncomment if desired: | |
| " | |
| " [F - Jump to first file in directory | |
| " nnoremap <silent> [F :<C-U>edit <C-R>=EscapeFilename(fnamemodify(GetFirstOrLastFile(-1), ':.'))<CR><CR> | |
| " | |
| " ]F - Jump to last file in directory | |
| " nnoremap <silent> ]F :<C-U>edit <C-R>=EscapeFilename(fnamemodify(GetFirstOrLastFile(1), ':.'))<CR><CR> | |
| " vim: fdm=marker:sw=4:sts=4:et |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment