# Copyright 2015 Koichi Murase <myoga.murase@gmail.com>. All rights reserved.
# This script is a part of blesh (https://github.com/akinomyoga/ble.sh)
# provided under the BSD-3-Clause license.  Do not edit this file because this
# is not the original source code: Various pre-processing has been applied.
# Also, the code comments and blank lines are stripped off in the installation
# process.  Please find the corresponding source file(s) in the repository
# "akinomyoga/ble.sh".
#
# Source: /lib/keymap.emacs.sh
ble/is-function ble-edit/bind/load-editing-mode:emacs && return 0
function ble-edit/bind/load-editing-mode:emacs { return 0; }
ble/util/autoload "$_ble_base/lib/keymap.vi.sh" \
                  ble/widget/vi-rlfunc/{prev,end,next}-word \
                  ble/widget/vi-command/{forward,backward}-{v,u}word \
                  ble/widget/vi-command/forward-{v,u}word-end
bleopt/declare -v keymap_emacs_mode_string_multiline $'\e[1m-- MULTILINE --\e[m'
_ble_keymap_emacs_white_list=(
  self-insert
  batch-insert
  nop
  magic-space magic-slash
  copy{,-forward,-backward}-{c,f,s,u}word
  copy-region{,-or}
  clear-screen
  command-help
  display-shell-version
  redraw-line
)
function ble/keymap:emacs/is-command-white {
  if [[ $1 == ble/widget/self-insert ]]; then
    return 0
  elif [[ $1 == ble/widget/* ]]; then
    local IFS=$_ble_term_IFS
    local cmd=${1#ble/widget/}; cmd=${cmd%%["$_ble_term_IFS"]*}
    [[ $cmd == emacs/* || " ${_ble_keymap_emacs_white_list[*]} " == *" $cmd "*  ]] && return 0
  fi
  return 1
}
function ble/widget/emacs/__before_widget__ {
  if ! ble/keymap:emacs/is-command-white "$WIDGET"; then
    ble-edit/undo/add
  fi
}
function ble/widget/emacs/undo {
  local arg; ble-edit/content/get-arg 1
  ble-edit/undo/undo "$arg" || ble/widget/.bell 'no more older undo history'
}
function ble/widget/emacs/redo {
  local arg; ble-edit/content/get-arg 1
  ble-edit/undo/redo "$arg" || ble/widget/.bell 'no more recent undo history'
}
function ble/widget/emacs/revert {
  local arg; ble-edit/content/clear-arg
  ble-edit/undo/revert
}
function ble/keymap:emacs/.get-emacs-keymap {
  ble/prompt/unit/add-hash '$_ble_decode_keymap,${_ble_decode_keymap_stack[*]}'
  local i=${#_ble_decode_keymap_stack[@]}
  keymap=$_ble_decode_keymap
  while [[ $keymap != vi_?map && $keymap != emacs ]]; do
    ((i--)) || return 1
    keymap=${_ble_decode_keymap_stack[i]}
  done
  [[ $keymap == emacs ]]
}
bleopt/declare -v prompt_emacs_mode_indicator '\q{keymap:emacs/mode-indicator}'
function bleopt/check:prompt_emacs_mode_indicator {
  local bleopt_prompt_emacs_mode_indicator=$value
  [[ $_ble_attached ]] && ble/keymap:emacs/update-mode-indicator
  return 0
}
_ble_keymap_emacs_mode_indicator_data=()
function ble/prompt/unit:_ble_keymap_emacs_mode_indicator/update {
  local trace_opts=truncate:relative:noscrc:ansi
  local prompt_rows=1
  local prompt_cols=${COLUMNS:-80}
  ((prompt_cols&&prompt_cols--))
  local "${_ble_prompt_cache_vars[@]/%/=}" # WA #D1570 checked
  ble/prompt/unit:{section}/update _ble_keymap_emacs_mode_indicator "$bleopt_prompt_emacs_mode_indicator" "$trace_opts"
}
function ble/keymap:emacs/update-mode-indicator {
  local keymap
  ble/keymap:emacs/.get-emacs-keymap || return 0
  local opt_multiline=
  [[ $_ble_edit_str == *$'\n'* ]] && opt_multiline=1
  local footprint=$opt_multiline:$_ble_edit_arg:$_ble_edit_kbdmacro_record
  [[ $footprint == "$_ble_keymap_emacs_modeline" ]] && return 0
  _ble_keymap_emacs_modeline=$footprint
  local version=$COLUMNS,$_ble_edit_lineno,$_ble_history_count,$_ble_edit_CMD
  local prompt_hashref_base='$version'
  ble/prompt/unit#update _ble_keymap_emacs_mode_indicator
  local ret; ble/prompt/unit:{section}/get _ble_keymap_emacs_mode_indicator; local str=$ret
  [[ $_ble_edit_arg ]] &&
    str=${str:+"$str "}$'(arg: \e[1;34m'$_ble_edit_arg$'\e[m)'
  [[ $_ble_edit_kbdmacro_record ]] &&
    str=${str:+"$str "}$'\e[1;31mREC\e[m'
  ble/edit/info/default ansi "$str"
}
blehook internal_PRECMD!=ble/keymap:emacs/update-mode-indicator
function ble/prompt/backslash:keymap:emacs/mode-indicator {
  ble/prompt/unit/add-hash '$_ble_edit_str'
  [[ $_ble_edit_str == *$'\n'* ]] || return 0
  ble/prompt/unit/add-hash '$bleopt_keymap_emacs_mode_string_multiline'
  local str=$bleopt_keymap_emacs_mode_string_multiline
  ble/prompt/unit/add-hash '${_ble_edit_arg:+1}${_ble_edit_kbdmacro_record:+1}'
  if [[ ! ${_ble_edit_arg:+1}${_ble_edit_kbdmacro_record:+1} ]]; then
    local keybinding_C_m=${_ble_decode_emacs_kmap_[_ble_decode_Ctrl|0x6d]}
    local keybinding_C_j=${_ble_decode_emacs_kmap_[_ble_decode_Ctrl|0x6a]}
    [[ $keybinding_C_m == *:ble/widget/accept-single-line-or-newline ]] &&
      [[ $keybinding_C_j == *:ble/widget/accept-line ]] &&
      str=${str:+"$str "}$'(\e[35mRET\e[m or \e[35mC-m\e[m: insert a newline, \e[35mC-j\e[m: run)'
  fi
  [[ ! $str ]] || ble/prompt/print "$str"
}
function ble/widget/emacs/__after_widget__ {
  ble/keymap:emacs/update-mode-indicator
}
function ble/widget/emacs/quoted-insert-char {
  _ble_edit_mark_active=
  _ble_decode_char__hook=ble/widget/emacs/quoted-insert-char.hook
  return 147
}
function ble/widget/emacs/quoted-insert-char.hook {
  ble/widget/quoted-insert-char.hook
  ble/keymap:emacs/update-mode-indicator
}
function ble/widget/emacs/quoted-insert {
  _ble_edit_mark_active=
  _ble_decode_key__hook=ble/widget/emacs/quoted-insert.hook
  return 147
}
function ble/widget/emacs/quoted-insert.hook {
  ble/widget/quoted-insert.hook
  ble/keymap:emacs/update-mode-indicator
}
function ble/widget/emacs/bracketed-paste {
  ble/widget/bracketed-paste
  _ble_edit_bracketed_paste_proc=ble/widget/emacs/bracketed-paste.proc
  return 147
}
function ble/widget/emacs/bracketed-paste.proc {
  ble/widget/bracketed-paste.proc "$@"
  ble/keymap:emacs/update-mode-indicator
}
function ble/widget/emacs/execute-named-command/accept.hook {
  ble/keymap:emacs/update-mode-indicator
  ble/widget/execute-named-command/accept.hook "$1"
}
function ble/widget/emacs/execute-named-command {
  ble/edit/async-read-mode 'ble/widget/emacs/execute-named-command/accept.hook'
  _ble_edit_PS1='!'
  _ble_edit_async_read_before_widget=ble/edit/async-read-mode/empty-cancel.hook
  ble/history/set-prefix _ble_edit_rlfunc
  return 147
}
function ble-decode/keymap:emacs/define {
  local ble_bind_nometa=
  ble-decode/keymap:safe/bind-common
  ble-decode/keymap:safe/bind-history
  ble-decode/keymap:safe/bind-complete
  ble-decode/keymap:safe/bind-arg
  ble-bind -f 'C-d'      'delete-region-or delete-forward-char-or-exit'
  ble-bind -f 'M-^'      history-expand-line
  ble-bind -f 'SP'       magic-space
  ble-bind -f '/'        magic-slash
  ble-bind -f __attach__        safe/__attach__
  ble-bind -f __before_widget__ emacs/__before_widget__
  ble-bind -f __after_widget__  emacs/__after_widget__
  ble-bind -f __line_limit__    __line_limit__
  ble-bind -f 'C-c'      discard-line
  ble-bind -f 'C-j'      accept-line
  ble-bind -f 'C-RET'    accept-line
  ble-bind -f 'C-m'      accept-single-line-or-newline
  ble-bind -f 'RET'      accept-single-line-or-newline
  ble-bind -f 'C-o'      accept-and-next
  ble-bind -f 'C-x C-e'  edit-and-execute-command
  ble-bind -f 'M-#'      insert-comment
  ble-bind -f 'M-C-e'    shell-expand-line
  ble-bind -f 'M-&'      tilde-expand
  ble-bind -f 'C-g'      bell
  ble-bind -f 'C-x C-g'  bell
  ble-bind -f 'C-M-g'    bell
  ble-bind -f 'C-l'      clear-screen
  ble-bind -f 'C-M-l'    redraw-line
  ble-bind -f 'f1'       command-help
  ble-bind -f 'C-x C-v'  display-shell-version
  ble-bind -c 'C-z'      fg
  ble-bind -f 'M-z'      zap-to-char
  ble-bind -f 'C-\'      bell
  ble-bind -f 'C-^'      bell
  ble-bind -f 'C-_'       emacs/undo
  ble-bind -f 'C-DEL'     emacs/undo
  ble-bind -f 'C-BS'      emacs/undo
  ble-bind -f 'C-/'       emacs/undo
  ble-bind -f 'C-x u'     emacs/undo
  ble-bind -f 'C-x C-u'   emacs/undo
  ble-bind -f 'C-x U'     emacs/redo
  ble-bind -f 'C-x C-S-u' emacs/redo
  ble-bind -f 'M-r'       emacs/revert
  ble-bind -f 'C-q'       emacs/quoted-insert
  ble-bind -f 'C-v'       emacs/quoted-insert
  ble-bind -f paste_begin emacs/bracketed-paste
  ble-bind -f 'M-x'       emacs/execute-named-command
}
function ble-decode/keymap:emacs/initialize {
  local fname_keymap_cache=$_ble_base_cache/keymap.emacs
  if [[ -s $fname_keymap_cache &&
          $fname_keymap_cache -nt $_ble_base/lib/keymap.emacs.sh &&
          $fname_keymap_cache -nt $_ble_base/lib/init-cmap.sh ]]; then
    source "$fname_keymap_cache" && return 0
  fi
  ble/edit/info/immediate-show text "ble.sh: updating cache/keymap.emacs..."
  {
    ble/decode/keymap#load isearch dump
    ble/decode/keymap#load nsearch dump
    ble/decode/keymap#load emacs   dump
  } 3>| "$fname_keymap_cache"
  ble/edit/info/immediate-show text "ble.sh: updating cache/keymap.emacs... done"
}
ble-decode/keymap:emacs/initialize
ble_bind_keymap=emacs blehook/invoke keymap_load
ble_bind_keymap=emacs blehook/invoke keymap_emacs_load
return 0
