" Language: Vim script
" Description: Quickly replace the word that is under the cursor.
" Usage: Press the keys '<Leader>rr', type the new word, and
" then leave insert mode (<Esc>).
" License: MIT
" Author: James Cherti
" URL: https://www.jamescherti.com/vim-quickly-replace-word-under-cursor/
function! s:replace_word_under_cursor(...) abort
let l:action = 'main'
if len(a:000) > 0
let l:action = a:000[0]
endif
"
" Main action
"
if l:action ==# 'main'
let b:replace_word_data = {}
let b:replace_word_data['changenr'] = changenr()
let l:regex_prefix = ''
let l:regex_suffix = ''
if mode() ==# 'n'
normal! diw
let l:regex_prefix = '\<'
let l:regex_suffix = '\>'
else
echoerr 'Unsupported mode: ' . mode()
return
endif
let b:replace_word_data['string'] = substitute(@@, '\v\n+$', '', 'g')
let b:replace_word_data['escaped_string'] =
\ '\V' . l:regex_prefix .
\ escape(b:replace_word_data['string'], '/\') .
\ l:regex_suffix
startinsert
augroup ReplaceString
autocmd!
autocmd InsertLeave * call s:replace_word_under_cursor('insert_leave')
augroup END
return
endif
"
" Insert Leave
"
if l:action ==# 'insert_leave'
autocmd! ReplaceString InsertLeave
let l:new_string = expand('<cword>')
if empty(l:new_string)
execute 'undo ' . b:replace_word_data['changenr']
return
endif
let l:cursor_pos = getpos('.')
execute 'keeppatterns silent! %substitute/' .
\ b:replace_word_data['escaped_string'] . '/' .
\ escape(l:new_string, '/\') . '/g'
call setpos('.', l:cursor_pos)
echo 'Replace: ' . b:replace_word_data['string'] . ' -> ' . l:new_string
unlet b:replace_word_data
return
endif
endfunction
nnoremap <Leader>rr :call <SID>replace_word_under_cursor()<CR>
Code language: Vim Script (vim)
Author Archives: James Cherti
Python: Tab completion against a list of strings (readline)
#!/usr/bin/env python
# License: MIT
# Author: James Cherti
# URL: https://www.jamescherti.com/python-tab-completion-readline-against-list/
"""Tab completion against a list of strings (readline)"""
import readline
from typing import Any, List, Union
class ReadlineCompleter:
"""A readline completer."""
def __init__(self, options: List[str]):
"""Store the options = ['word1', 'word2']."""
readline.set_completer_delims('')
self.options = options
self.matches: List[str] = []
def complete(self, _, state):
"""Complete a readline sentence."""
if state == 0:
origline = readline.get_line_buffer()
begin = readline.get_begidx()
end = readline.get_endidx()
being_completed = origline[begin:end]
words = origline.split()
if not words:
self.matches = self.options[:]
else:
try:
if begin == 0:
matches = self.options[:] # First word
else:
first = words[0] # Later word
matches = self.options[first]
if being_completed:
# Match options with portion of input
# being completed
self.matches = [w for w in matches
if w.startswith(being_completed)]
else:
# Matching empty string so use all candidates
self.matches = matches
except (KeyError, IndexError):
self.matches = []
try:
return self.matches[state]
except IndexError:
return None
def input_completion(prompt: Any,
list_options: Union[None, List[str]] = None):
"""Read a string from standard input and complete against 'list_options'.
The trailing newline is stripped. The prompt string is printed to
standard output without a trailing newline before reading input.
If the user hits EOF (*nix: Ctrl-D, Windows: Ctrl-Z+Return), raise
EOFError. On *nix systems, readline is used if available.
"""
readline.parse_and_bind('tab: complete')
if list_options is None:
list_options = []
save_completer = readline.get_completer()
try:
readline.set_completer(
ReadlineCompleter(list_options).complete
)
return input(prompt)
finally:
readline.set_completer(save_completer)
def main():
"""Try input_completion()."""
list_options = ["yes", "no", "cancel"]
value = input_completion("Proceed (press the Tab key)? ",
list_options=list_options)
print("Value:", value)
if __name__ == "__main__":
main()
Code language: Python (python)
A tool to Execute a Command in a new Tmux Window
The Python script tmux-run.py allows executing a command in a new tmux window. A tmux window is similar to a tab in other software.
If the script is executed from within a tmux session, it creates a tmux window in the same tmux session. However, if the script is executed from outside of a tmux session, it creates a new tmux window in the first available tmux session.
(Requirement: libtmux)
The Python script: tmux-run.py
#!/usr/bin/env python
# License: MIT
# Author: James Cherti
# URL: https://www.jamescherti.com/python-script-run-command-new-tmux-window/
"""Execute a command in a new tmux window.
This script allows executing a command in a new tmux window (a tmux window is
similar to a tab in other software).
- If it is executed from within a tmux session, it creates a tmux window
in the same tmux session.
- However, if the script is executed from outside of a tmux
session, it creates a new tmux window in the first available tmux session.
"""
import os
import shlex
import shutil
import sys
import libtmux
SCRIPT_NAME = os.path.basename(sys.argv[0])
def parse_args():
if len(sys.argv) < 2:
print(f"Usage: {SCRIPT_NAME} <command> [args...]",
file=sys.stderr)
sys.exit(1)
args = sys.argv[1:]
args[0] = shutil.which(args[0])
if args[0] is None:
print(f"{SCRIPT_NAME}: no {args[0]} in "
f"({os.environ.get('PATH', '')})", file=sys.stderr)
sys.exit(1)
return args
def get_tmux_session():
tmux_server = libtmux.Server()
if not tmux_server.sessions:
print(f"{SCRIPT_NAME}: the tmux session was not found",
file=sys.stderr)
sys.exit(1)
tmux_session_id = os.environ["TMUX"].split(",")[-1]
if tmux_session_id:
try:
return tmux_server.sessions.get(id=f"${tmux_session_id}")
except Exception: # pylint: disable=broad-except
pass
return tmux_server.sessions[0]
def run_in_tmux_window():
try:
command_args = parse_args()
tmux_session = get_tmux_session()
command_str = shlex.join(command_args)
tmux_session.new_window(attach=True, window_shell=command_str)
except libtmux.exc.LibTmuxException as err:
print(f"Error: {err}.", file=sys.stderr)
sys.exit(1)
if __name__ == '__main__':
run_in_tmux_window()
Code language: Python (python)
Gentoo Linux: Unlocking a LUKS Encrypted LVM Root Partition at Boot Time using a Key File stored on an External USB Drive

Gentoo can be configured to use a key file stored on an external USB drive to unlock a LUKS encrypted LVM root partition.
We will explore in this article the general steps involved in configuring Gentoo to use an external USB drive as a key file to unlock a LUKS encrypted LVM root partition.
1. Create a key file on the USB stick and add it to the LUKS encrypted partition
Generate a key file on a mounted ext4 or vfat partition of a USB stick, which will be used by initramfs to unlock the LUKS partition:
dd if=/dev/urandom of=/PATH/TO/USBSTICK/keyfile bs=1024 count=4
Code language: plaintext (plaintext)
Ensure that the partition on the USB drive has a label, as the initramfs will use this label to find where the key file is located.
Afterward, add the key file to the LUKS partition to enable decryption of the partition using that key file:
cryptsetup luksAddKey /dev/PART1 /PATH/TO/USBSTICK/keyfile
In this example, “/dev/PART1” is the partition where the LUKS encryption is enabled, and “/PATH/TO/USBSTICK/keyfile” is the location of the keyfile.
2 – Find the UUID of the encrypted partition and the label of the USB drive
Use the lsblk command to find the UUID of the encrypted partition and the label of the USB drive:
lsblk -o +UUID,LABEL
3. Configure the boot loader (such as Systemd-boot, GRUB, Syslinux…)
Add to the boot loader configuration the following initramfs kernel parameters:
- crypt_root=UUID=A1111111-A1AA-11A1-AAAA-111AA11A1111
- root=/dev/LVMVOLUME/root
- root_keydev=/dev/disk/by-label/LABELNAME
- root_key=keyfile
Here is an example for Systemd-boot:
options dolvm crypt_root=UUID=A1111111-A1AA-11A1-AAAA-111AA11A1111 root=/dev/LVMVOLUME/root root_keydev=/dev/disk/by-label/LABELNAME root_key=keyfile
Code language: plaintext (plaintext)
To ensure proper setup:
- Customize the initramfs options for LVMVOLUME, LABELNAME, and UUID=A1111111-A1AA-11A1-AAAA-111AA11A1111 to match your specific case.
- Verify that the ext4 or vfat partition of the USB drive that is labeled “LABELNAME” contains a file named “keyfile”.
- Make sure that the modules “dm_mod” and “usb_storage” are included in the initramfs.
This method offers a convenient way to unlock a LUKS encrypted root LVM partition. The implementation process is well-documented, making it a suitable choice for those looking to secure their Gentoo Linux systems.
How to make Vim edit/diff files from outside of Vim? (e.g. from a shell like Bash, Zsh, Fish..)
The Vim editor offers the ability to connect to a Vim server and make it perform various tasks from outside of Vim. The command-line tools vim-client-edit, vim-client-diff and the vim_client Python module, written by James Cherti, can be used to easily find and connect to a Vim server and make it perform the following tasks:
- Edit files or directories in new tabs (The command-line tool vim-client-edit),
- Diff/Compare up to eight files (The command-line tool vim-client-diff),
- Evaluate expressions and return their result (The Python module vim_client),
- Send commands and expressions to Vim (The Python module vim_client).
The command-line tools vim-client-edit and vim-client-diff are especially useful when a quick edit or comparison needs to be performed on a file from outside of Vim (e.g. from a shell like Bash, Zsh, Fish, etc.).
Additionally, the vim_client Python module allows running expressions on a Vim server and retrieving their output, which can be useful for automating tasks or scripting. For example, you can use vim-client to run a search and replace operation on a file or directory, or to perform a complex diff operation between two files.
Overall, vim-client is a powerful tool for interacting with Vim from the vim-client-edit and vim-client-diff command-line tools. The vim_client Python module can also be used to run and retrieve the output of Vim expressions, which can help automate various tasks.
Please star vim-client on GitHub to support the project!
Requirements
To use vim-client, you will need to have Vim and Python installed on your system.
Installation
The vim-client package can be installed with pip:
$ sudo pip install vim-client
Code language: Bash (bash)
Execute Vim server
The Vim editor must be started with the option “–servername”, which enables the Vim server feature that allows clients to connect and send commands to Vim:
$ vim --servername SERVERNAME
Code language: plaintext (plaintext)
Make Vim server edit multiple files in tabs
Editing a list of files in new tabs:
$ vim-client-edit file1 file2 file3
Make Vim server diff files (like vimdiff)
Comparing/diff up to eight files:
$ vim-client-diff file1 file2
Useful ~/.bashrc aliases:
Adding the following aliases to ~/.bashrc is recommended as it makes it easy to execute the command-line tools vim-client-edit and vim-client-diff:
alias gvim=vim-client-edit
alias vim=vim-client-edit
alias vi=vim-client-edit
alias vimdiff=vim-client-diff
Links related to vim-client
Vim: Edit all the files in the current directory of a Git repository in new tabs (git ls-files)
" Language: Vim script
" Description: edit all the Git files in the current
" directory in new tabs (git ls-files
" License: MIT
" Author: James Cherti
" URL: https://www.jamescherti.com/vim-edit-git-ls-files-new-tabs/
function! GitEditFiles() abort
if &modified
echoerr 'fatal: No write since last change.'
return
endif
let l:list_lines = systemlist('git ls-files')
if v:shell_error !=# 0
echomsg 'fatal: Git: ' . join(l:list_lines, "\n")
return
endif
let l:list_files = []
for l:filename in l:list_lines
if filereadable(l:filename)
call add(l:list_files, l:filename)
endif
endfor
if len(l:list_files) ==# 0
echo 'No Git files were found in the directory ' . getcwd()
return
endif
if len(l:list_files) > 7
for l:filename in l:list_lines
echo l:filename
endfor
echo "\n"
echo 'Git directory: ' . getcwd()
echo 'Number of Git files: ' . len(l:list_files)
echo "\n"
let l:answer = input('Edit? [y,n]')
if l:answer !=# 'y'
return
endif
endif
let l:first = 1
for l:file in l:list_files
if l:first
let l:first = 0
else
execute 'tabnew'
endif
execute 'edit ' . fnameescape(l:file)
endfor
endfunction
command! -nargs=0 GitEditFiles call GitEditFiles()
Code language: Vim Script (vim)
Vim theme: tomorrow-night-deepblue, a refreshing color scheme with a deep blue background
The Vim color scheme jamescherti/vim-tomorrow-night-deepblue is a beautiful deep blue variant of the “Tomorrow Night” colorscheme, which is renowned for its elegant color palette. It is pleasing to the eyes and is easy to read (The colorscheme was previously called tomorrow-night-seablue).
The “Tomorrow Night Deepblue” color scheme features a deep blue background color that creates a calming atmosphere. The contrasting colors make it easy to distinguish between different elements of your code. The tomorrow-night-deepblue colorscheme is also a great choice for programmer who miss the blue themes that were trendy a few years ago.

The theme was inspired by classic DOS text editors such as QuickBASIC, RHIDE, and Turbo Pascal, which featured blue backgrounds by default. There’s something special about the early days of programming and the tools we used that brings back fond memories.
Install the tomorrow-night-deepblue colorscheme with Vim’s built-in package manager (Vim 8 and above)
mkdir -p ~/.vim/pack/jamescherti/start
cd ~/.vim/pack/jamescherti/start
git clone --depth 1 https://github.com/jamescherti/vim-tomorrow-night-deepblue
vim -u NONE -c "helptags vim-tomorrow-night-deepblue/doc" -c q
Code language: Bash (bash)
Activate the color scheme
:color tomorrow-night-deepblue
Code language: Vim Script (vim)
Links
- Git repository of the Vim color scheme: jamescherti/tomorrow-night-deepblue
- There is also an Emacs version of this theme: Emacs Theme: Tomorrow Night Deepblue
Bash shell: Perform tab-completion for aliases (bash-completion)
# Author: James Cherti
# License: MIT
# Requirements: bash-completion
# Description: Perform tab-completion for aliases in Bash (bash-completion).
# URL: https://www.jamescherti.com/bash-shell-perform-tab-completion-for-aliases/
#
# Add the following function to ~/.bashrc :
alias_completion() {
local func_name='alias_completion'
if [[ $# -lt 2 ]]; then
echo "Usage: $func_name <cmd> <alias> <alias2> <...>" >&2
return 1
fi
local cmd; cmd="$1"
shift
# Load the completion
if ! type _completion_loader >/dev/null 2>&1; then
echo "Error: $func_name: '_completion_loader' was not found." >&2
return 1
fi
_completion_loader "$cmd"
if ! complete -p "$cmd" >/dev/null; then
echo "Error: $func_name: 'complete -p $cmd' failed." >&2
return 1
fi
# Add aliases
local alias
for alias in "$@"; do
complete_cmd=$(complete -p "$cmd" 2>/dev/null | sed -e 's/[[:space:]][^[:space:]]\+$//')
complete_cmd="${complete_cmd} $alias"
if ! ( echo "$complete_cmd" | grep -P '^\s*complete\s' >/dev/null 2>&1 ); then
echo "Error: $func_name: alias '$alias': '$complete_cmd' is an invalid command." >&2
return 1
fi
eval "$complete_cmd"
done
return 0
}
Code language: Bash (bash)
Examples of aliases:
alias s='ssh'
alias_completion ssh s
alias g='git'
alias_completion git g
Code language: Bash (bash)
Bash shell: A better version of the default bash built-in command “cd”
#!/usr/bin/env bash
# Author: James Cherti
# License: MIT
# URL: https://www.jamescherti.com/shell-bash-replacement-bash-cd-change-directory/
#
# Description:
# 1. 'cd path/to/file' will change the directory to 'path/to'
# (the parent directory of 'file').
#
# 2. 'cd path/to/dir with spaces' will change the directory to
# "path/to/dir with spaces".
#
# 3. 'cd file:///home/user' will change the directory to "/home/user".
#
# 4. You can switch to the previous directory with 'popd' or 'cd -'.
#
# Add the following function and alias to ~/.bashrc :
#
_better_cd() {
# Previous directory ('cd -')
if [[ $# -eq 1 ]] && [[ $1 = '-' ]]; then
popd >/dev/null || return 1
return 0
fi
# Join paths
local path
if [[ $# -eq 0 ]]; then
path="$HOME"
else
path=$(echo "$1" | sed -e 's/^file:\/\///')
shift
local item
for item in "$@"; do
path="${path} ${item}"
done
fi
# Checks
local errno=0
if [[ -f "$path" ]]; then
path=$(dirname "$path")
fi
if ! [[ -d "$path" ]]; then
echo "$(basename "$0"):" "cd: $path: No such file or directory" >&2
return 1
fi
# Change the directory
local oldcwd; oldcwd=$(pwd)
pushd . >/dev/null || return 1
builtin cd "$path" >/dev/null 2>&1 || errno=1
if [[ $oldcwd = "$(pwd)" ]]; then
popd >/dev/null || return 1
fi
return "$errno"
}
alias cd=_better_cd
Code language: Bash (bash)
Vim: Open documentation in a new tab for the word under the cursor (Vim help, Python, man pages, Markdown, Ansible…)
The following Vim script (VimL) function can be used to make Vim open the documentation of the word under the cursor in a new tab for various languages and tools such as Vim help (:help), Python (Pydoc), Markdown (sdcv dictionary), man pages (Vim’s built-in ‘:Man’), and Ansible (ansible-doc).
The VimL function is also extensible, meaning that you can adapt it to work with any other documentation tool. By default, the key mapping upper-case “K” can be used to open the documentation for the word under the cursor in a new tab.
" Language: Vim script
" Author: James Cherti
" License: MIT
" Description: Vim: open help/documentation in a new tab
" (Vim script, Python, Markdown, man pages, Ansible...).
" Press upper-case K to open help for the word under the cursor.
" URL: https://www.jamescherti.com/vim-open-help-documentation-in-a-new-tab/
function! TabHelp(word) abort
let l:cmd = ''
let l:tabhelpprg = get(b:, 'tabhelpprg', '')
if l:tabhelpprg ==# ''
normal! K
return
endif
if l:tabhelpprg[0] ==# ':'
if stridx(l:tabhelpprg, '%s') ==# -1
execute l:tabhelpprg
else
execute printf(l:tabhelpprg, fnameescape(a:word))
endif
return
else
let l:cmd = 'silent read! '
if stridx(l:tabhelpprg, '%s') ==# -1
let l:cmd .= l:tabhelpprg
else
let l:cmd .= printf(l:tabhelpprg, shellescape(a:word))
endif
endif
execute 'silent tabnew help:' . fnameescape(a:word)
setlocal modifiable
silent normal! ggdG
silent normal! 1Gdd
if l:cmd !=# ''
execute l:cmd
endif
silent normal! gg0
setlocal nomodifiable
setlocal noswapfile
setlocal nowrap
setlocal nonumber
setlocal nomodified
setlocal buftype=nofile
setlocal bufhidden=delete
if exists('&relativenumber')
setlocal norelativenumber
endif
if exists('&signcolumn')
setlocal signcolumn=no
endif
setlocal nofoldenable
setlocal foldcolumn=0
endfunction
augroup TabHelp
autocmd!
autocmd FileType vim let b:tabhelpprg = ':tab help %s'
autocmd FileType sh,zsh,csh if ! exists(':Man') | runtime ftplugin/man.vim | endif | let b:tabhelpprg = ':tab Man %s'
autocmd FileType yaml.ansible if executable('ansible-doc') | let b:tabhelpprg = 'ansible-doc %s' | endif
autocmd FileType markdown if executable('sdcv') | let b:tabhelpprg = 'sdcv %s' | endif
autocmd FileType vim,sh,zsh,csh,yaml.ansible,markdown nnoremap <silent> <buffer> K :call TabHelp(expand('<cword>'))<CR>
augroup END
Code language: Vim Script (vim)
Gentoo Linux: Printer driver for the Brother QL-1110NWB
Installing the printer driver for the Brother QL-1110NWB on Gentoo Linux can be a bit tricky, but thanks to a helpful ebuild written by James Cherti, the process becomes a breeze. The ebuild automates the whole process of downloading and installing the appropriate driver for the Brother QL-1110NWB on Gentoo Linux.
Brother QL-111NWB Driver installation on Gentoo
Create the file /etc/portage/repos.conf/motley-overlay.conf
containing:
[motley-overlay]
location = /usr/local/portage/motley-overlay
sync-type = git
sync-uri = https://github.com/jamescherti/motley-overlay
priority = 9999
Code language: plaintext (plaintext)
Update the repository:
emerge --sync motley-overlay
Code language: plaintext (plaintext)
Install the Brother QL-1110NWB printer driver:
emerge -av net-print/brother-ql1110nwb-bin
Code language: plaintext (plaintext)
The ebuild will automatically download the necessary driver package from Brother and install it on your system.
Finally, restart CUPS with:
systemctl restart cups
Code language: plaintext (plaintext)
You can now register your new printer using the web interface at: http://localhost:631/
(Please add a star to the Git repository jamescherti/motley-overlay to support the project!)
Vim: Tango color scheme for Vim’s built-in Terminal
The following code snippet will allow you to apply the Tango Dark color scheme to the Vim’s built-in terminal and ensure that the terminal’s color scheme remains consistent, even if you change the Vim color scheme with the ‘:colorscheme’ command.
The snippet uses autocmd to ensures that the Vim terminal’s color scheme remains Tango Dark.

For more information about Vim’s built-in terminal:
- :help terminal
" Language: Vim script
" Author: James Cherti
" License: MIT
" Description: Improve the color scheme of Vim Terminal (Tango dark theme),
" and prevent :colorscheme from changing the terminal color scheme.
" URL: https://www.jamescherti.com/vim-tango-color-scheme-vim-terminal/
" Gnome-Terminal Tango Dark
let g:terminal_ansi_colors_black = '#2E3436'
let g:terminal_ansi_colors_darkred = '#CC0000'
let g:terminal_ansi_colors_darkgreen = '#4E9A06'
let g:terminal_ansi_colors_brown = '#C4A000'
let g:terminal_ansi_colors_darkblue = '#3465A4'
let g:terminal_ansi_colors_darkmagenta = '#75507B' " dark purple
let g:terminal_ansi_colors_darkcyan = '#06989A' " dark turquoise
let g:terminal_ansi_colors_lightgrey = '#D3D7CF'
let g:terminal_ansi_colors_darkgrey = '#555753'
let g:terminal_ansi_colors_red = '#EF2929'
let g:terminal_ansi_colors_green = '#8AE234'
let g:terminal_ansi_colors_yellow = '#FCE94F'
let g:terminal_ansi_colors_blue = '#729FCF'
let g:terminal_ansi_colors_magenta = '#AD7FA8' " purple
let g:terminal_ansi_colors_cyan = '#34E2E2' " turquoise
let g:terminal_ansi_colors_white = '#EEEEEC'
" Text and background: Gnome dark
let g:terminal_ctermbg = 'black'
let g:terminal_ctermfg = 'white'
let g:terminal_statuslineterm_ctermbg = 'black'
let g:terminal_statuslineterm_ctermfg = 'white'
let g:terminal_statuslinetermnc_ctermbg = 'black'
let g:terminal_statuslinetermnc_ctermfg = 'white'
let g:terminal_guibg = '#000000'
let g:terminal_guifg = '#D0CFCC'
let g:terminal_statuslineterm_guibg = g:terminal_guibg
let g:terminal_statuslineterm_guifg = g:terminal_guifg
let g:terminal_statuslinetermnc_guibg = g:terminal_guibg
let g:terminal_statuslinetermnc_guifg = g:terminal_guifg
function! SetTerminalColorScheme() abort
if !has('terminal')
return
endif
let g:terminal_ansi_colors = [
\ g:terminal_ansi_colors_black,
\ g:terminal_ansi_colors_darkred,
\ g:terminal_ansi_colors_darkgreen,
\ g:terminal_ansi_colors_brown,
\ g:terminal_ansi_colors_darkblue,
\ g:terminal_ansi_colors_darkmagenta,
\ g:terminal_ansi_colors_darkcyan,
\ g:terminal_ansi_colors_lightgrey,
\ g:terminal_ansi_colors_darkgrey,
\ g:terminal_ansi_colors_red,
\ g:terminal_ansi_colors_green,
\ g:terminal_ansi_colors_yellow,
\ g:terminal_ansi_colors_blue,
\ g:terminal_ansi_colors_magenta,
\ g:terminal_ansi_colors_cyan,
\ g:terminal_ansi_colors_white
\ ]
execute printf(
\ 'highlight Terminal ctermbg=%s ctermfg=%s guibg=%s guifg=%s',
\ g:terminal_ctermbg, g:terminal_ctermfg, g:terminal_guibg,
\ g:terminal_guifg
\ )
execute printf(
\ 'highlight StatusLineTerm ctermbg=%s ctermfg=%s guibg=%s guifg=%s',
\ g:terminal_statuslineterm_ctermbg, g:terminal_statuslineterm_ctermfg,
\ g:terminal_statuslineterm_guibg, g:terminal_statuslineterm_guifg
\ )
execute printf(
\ 'highlight StatusLineTermNC ctermbg=%s ctermfg=%s guibg=%s guifg=%s',
\ g:terminal_statuslinetermnc_ctermbg, g:terminal_statuslinetermnc_ctermfg,
\ g:terminal_statuslinetermnc_guibg, g:terminal_statuslinetermnc_guifg
\ )
endfunction
if has('terminal')
augroup TerminalColorScheme
autocmd!
autocmd ColorScheme * call SetTerminalColorScheme()
autocmd VimEnter * call SetTerminalColorScheme()
augroup END
call SetTerminalColorScheme()
endif
Code language: Vim Script (vim)
Vim: Enhance Vim tabs (file name only, file status, and the ability to rename tabs)
" Language: Vim script
" Author: James Cherti
" License: MIT
" Description: Enhance the tab line. The tabs will show the base name of
" the file and its status. Tabs can be renamed with 'TabRename'.
" URL: https://www.jamescherti.com/vim-improve-the-tab-line-basename-of-the-file-and-status/
function! MyTabLabel(tabnr) abort
let l:bufnr = tabpagebuflist(a:tabnr)[tabpagewinnr(a:tabnr) - 1]
let l:modified = 0
if getbufvar(l:bufnr, '&modified')
let l:modified = 1
endif
let l:tablabel = ''
let l:custom_tablabel = gettabvar(a:tabnr, 'tablabel', '')
if empty(l:custom_tablabel)
let l:bufname = bufname(l:bufnr)
if empty(l:bufname)
let l:tablabel = empty(&buftype) ? 'No Name' : '<' . &buftype . '>'
else
let l:tablabel = fnamemodify(l:bufname, ':t')
endif
else
let l:tablabel .= l:custom_tablabel
endif
if l:modified
let l:tablabel .= '*'
endif
return l:tablabel
endfunction
function! MyTabLine() abort
let l:tabline = ''
for l:num in range(1, tabpagenr('$'))
let l:tabline .= (l:num != tabpagenr()) ? '%#TabLine#' : '%#TabLineSel#'
let l:tabline .= '%' . l:num . 'T %{MyTabLabel(' . l:num . ')} '
endfor
let l:tabline .= '%#TabLineFill#%T%='
let l:tabline .= repeat('%#TabLine#%999X[X]', l:num > 1)
return l:tabline
endfunction
function! MyGuiTabLine() abort
return MyTabLabel(tabpagenr())
endfunction
function! TabRename(tablabel) abort
let t:tablabel = a:tablabel
execute 'redrawtabline'
endfunction
if exists('+showtabline')
command! -nargs=1 TabRename call TabRename(<q-args>)
set tabline=%!MyTabLine()
set guitablabel=%{MyGuiTabLine()}
endif
Code language: Vim Script (vim)
Vim script: Replace the home directory with a tilde ~
The following Vim script (VimL) code snippet can be used to replace the full path of a home directory in a string with a tilde (“~”). This can be useful as a way to shorten the path to a file or directory, making it more readable.
" Language: Vim script
" Author: James Cherti
" License: MIT
" Description: A function that replaces the home directory
" with a tilde (e.g. '/home/user/file.txt' will
" be replaced with '~/file.txt').
" URL: https://www.jamescherti.com/vim-script-replace-the-home-directory-with-a-tilde/
function! ReplaceHomeWithTilde(path) abort
let l:path = fnamemodify(a:path, ':p')
let l:path_sep = (!exists('+shellslash') || &shellslash) ? '/' : '\'
let l:home = fnamemodify('~', ':p')
if l:path[0:len(l:home)-1] ==# l:home
return '~' . l:path_sep . l:path[len(l:home):]
elseif l:path == l:home
return '~' . l:path_sep
endif
return l:path
endfunction
Code language: Vim Script (vim)
Python: Read the shebang line of a script
#!/usr/bin/env python
# Author: James Cherti
# License: MIT
# URL: https://www.jamescherti.com/python-read-the-shebang-line-of-a-script/
"""Read the shebang line of a script."""
import sys
import os
import shlex
from pathlib import Path
from typing import Union
class ShebangError(Exception):
"""Error with the method read_shebang()."""
def read_shebang(script_path: Union[Path, str]) -> list:
"""Return the shebang line of a file.
>>> shebang("file.sh")
['/usr/bin/env', 'bash']
"""
with open(script_path, "rb") as fhandler:
line = fhandler.readline().strip().decode()
if len(line) > 2 and line[0:2] == '#!':
shebang_split = shlex.split(line[2:].strip())
if not Path(shebang_split[0]).is_file():
raise ShebangError(f"the shebang '{shebang_split}' does not exist")
if not os.access(shebang_split[0], os.X_OK):
raise ShebangError(f"the shebang '{shebang_split}' is not "
"executable")
return shebang_split
raise ShebangError("the shebang line was not found")
if __name__ == "__main__":
try:
print(read_shebang(sys.argv[1]))
except IndexError:
print(f"Usage: {sys.argv[0]} <file>", file=sys.stderr)
sys.exit(1)
Code language: Python (python)