It's typically pretty hard to be able to tell the mode from a function or even a mapping, since usually the commands you'd have to execute to retrieve the current mode will switch you to another mode already.
For example, when you do
:echo mode() you'll have switched to command-line mode with the
:, so it will simply return
c rather than the normal or visual mode you were in.
This is mentioned in
This is useful in the
'statusline' option or when used with
remote_expr() In most other places it always returns
For specific situations, such as querying which Visual mode was used last, you can use
visualmode(), but that tells you nothing about whether you're coming to the current mode from Visual mode, or how long ago Visual mode was last used...
You might have less interference by using an
<expr> mapping, in which case
mode() will be evaluated before most mode changes happen.
function! Debug(mode, saymode)
let cmd = "echom 'Mode is [".strtrans(a:saymode)."]'\r"
if a:mode ==# 'n'
elseif a:mode ==# 'i'
elseif a:mode ==# 'v'
nnoremap <expr> <F2> Debug('n', mode())
inoremap <expr> <F2> Debug('i', mode())
vnoremap <expr> <F2> Debug('v', mode())
But even in that case, it's not really completely reliable. For example, if you're in "Select" mode, Vim will switch you to the corresponding Visual mode before executing a mapping, so this will show the Visual mode rather than Select mode...