Skip to content
Yuriy Artemyev edited this page Jun 25, 2026 · 2 revisions

Welcome to the Hel wiki!

This section describes how to extend zsh-helix-mode to mimic Hel keys that extends the default Helix keys.

# C-; — flip selection (native M-;)
bindkey -M hxnor '\e[59;5u' zhm_flip_selections

Duplicate mi keys under m prefix

# Patch `zhm_select_surround_pair_inner` so wrappers can pass the bracket
# character via _ZHM_SURROUND_CHAR instead of through $KEYS (which is
# a read-only ZLE parameter; regular shell variables use dynamic scoping).
() {
  local fn old new
  fn=$(typeset -f zhm_select_surround_pair_inner)
  old='local char="${KEYS:2}"'
  new='local char="${_ZHM_SURROUND_CHAR:-${KEYS:2}}"'
  eval "${fn/$old/$new}"
}

# m( m)
function _zhm_select_paren_inner {
  local _ZHM_SURROUND_CHAR='('
  zhm_select_surround_pair_inner
}
zle -N _zhm_select_paren_inner

# m[ m]
function _zhm_select_bracket_inner {
  local _ZHM_SURROUND_CHAR='['
  zhm_select_surround_pair_inner
}
zle -N _zhm_select_bracket_inner

# m{ m}
function _zhm_select_brace_inner {
  local _ZHM_SURROUND_CHAR='{'
  zhm_select_surround_pair_inner
}
zle -N _zhm_select_brace_inner

# m< m>
function _zhm_select_angle_inner {
  local _ZHM_SURROUND_CHAR='<'
  zhm_select_surround_pair_inner
}
zle -N _zhm_select_angle_inner

# m'
function _zhm_select_squote_inner {
  local _ZHM_SURROUND_CHAR="'"
  zhm_select_surround_pair_inner
}
zle -N _zhm_select_squote_inner

# m"
function _zhm_select_dquote_inner {
  local _ZHM_SURROUND_CHAR='"'
  zhm_select_surround_pair_inner
}
zle -N _zhm_select_dquote_inner

# m`
function _zhm_select_bquote_inner {
  local _ZHM_SURROUND_CHAR='`'
  zhm_select_surround_pair_inner
}
zle -N _zhm_select_bquote_inner

bindkey -M hxnor 'mw' zhm_select_word_inner
bindkey -M hxnor 'mW' zhm_select_long_word_inner
bindkey -M hxnor 'm)' _zhm_select_paren_inner
bindkey -M hxnor 'm[' _zhm_select_bracket_inner
bindkey -M hxnor 'm]' _zhm_select_bracket_inner
bindkey -M hxnor 'm{' _zhm_select_brace_inner
bindkey -M hxnor 'm}' _zhm_select_brace_inner
bindkey -M hxnor 'm<' _zhm_select_angle_inner
bindkey -M hxnor 'm>' _zhm_select_angle_inner
bindkey -M hxnor "m'" _zhm_select_squote_inner
bindkey -M hxnor 'm"' _zhm_select_dquote_inner
bindkey -M hxnor 'm"' _zhm_select_dquote_inner
bindkey -M hxnor 'm`' _zhm_select_bquote_inner

gh, gs, gl make selections

function _zhm_goto_line_start_sel {
  for i in {1..$#zhm_cursors_pos}; do
    local cursor=$zhm_cursors_pos[$i]
    __zhm_trailing_goto $i $(__zhm_find_line_start $cursor "$BUFFER") 0
  done
  __zhm_update_last_moved
  __zhm_update_region_highlight
}
zle -N _zhm_goto_line_start_sel


function _zhm_goto_line_end_sel {
  for i in {1..$#zhm_cursors_pos}; do
    local cursor=$zhm_cursors_pos[$i]
    local line_end=$(__zhm_find_line_end $cursor "$BUFFER")
    local goto=
    if [[
      "$BUFFER[$((line_end + 1))]" == $'\n'
      && "$BUFFER[$line_end]" != $'\n'
    ]]; then
      goto=$((line_end - 1))
    else
      goto=$line_end
    fi
    __zhm_trailing_goto $i $goto 0
  done
  __zhm_update_last_moved
  __zhm_update_region_highlight
}
zle -N _zhm_goto_line_end_sel


function _zhm_goto_line_first_nonwhitespace_sel {
  setopt localoptions rematchpcre
  for i in {1..$#zhm_cursors_pos}; do
    local cursor=$zhm_cursors_pos[$i]
    local line_start=$(__zhm_find_line_start $cursor "$BUFFER")
    if [[ "${BUFFER:$line_start}" =~ '\A[^\S\n]*' ]]; then
      __zhm_trailing_goto $i $((line_start + MEND)) 0
    fi
  done
  __zhm_update_last_moved
  __zhm_update_region_highlight
}
zle -N _zhm_goto_line_first_nonwhitespace_sel


bindkey -M hxnor 'gh' _zhm_goto_line_start_sel
bindkey -M hxnor 'gl' _zhm_goto_line_end_sel
bindkey -M hxnor 'gs' _zhm_goto_line_first_nonwhitespace_sel