Skip to content

Instantly share code, notes, and snippets.

@lopesivan
Created November 13, 2025 02:22
Show Gist options
  • Select an option

  • Save lopesivan/0f91bf7e82e3bccb39e0c0d1469e6a61 to your computer and use it in GitHub Desktop.

Select an option

Save lopesivan/0f91bf7e82e3bccb39e0c0d1469e6a61 to your computer and use it in GitHub Desktop.
correção:
" 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