6

In Vim, I want to have a certain mapping set only if and only if the filetype is markdown, text, or none (ie NULL). Specifying "none" is the hard part.

The command below works if :set filetype? returns filetype=markdown or filetype=text. But if :set filetype? returns filetype= (shows as none in my status line) it does not work.

autocmd FileType markdown,text,none  nnoremap <leader>f :%! cat<CR>

What is the correct way to to specify filetype is not set? In other words this mapping should be defined only when filetype is not set (or is text or markdown). On any other filetype the mapping should be undefined.

NB: the mapping is contrived because it is not the interesting part of the question.

MERM
  • 629
  • 7
  • 21

3 Answers3

9

Here's one way:

autocmd FileType markdown,text nnoremap <buffer> <leader>f :1,$! cat
autocmd BufNewFile,BufRead * if empty(&filetype) | execute 'nnoremap <buffer> <leader>f :1,$! cat' | endif

As the FileType event is not triggered when no filetype is detected, you have to use the original filetype detection events, and check for an empty filetype. Put those lines after :filetype on in your ~/.vimrc, so that the autocmd ordering is right.

Note that the code in your question still defines global mappings (after one of your filetypes is loaded); you need to add <buffer> to make those mappings truly local. (And to be 100% correct use <LocalLeader>, though most users don't have a separate key defined for that.)

If you're fine with a global mapping, you could also get rid of all the autocmds and just perform the filetype check (if that's really necessary; I don't see a bad behavior with other filetypes for your example) at runtime, e.g. with :help :map-expr:

nnoremap <expr> <leader>f index(['markdown', 'text', ''], &filetype) == -1 ? '': ':1,$! cat')

Postscript

  • Your mapping is incomplete, i.e. it leaves the cursor in command-line mode; is that intended? Append <CR> to complete it.
  • Instead of 1,$, you can use the % range.
Ingo Karkat
  • 167,457
  • 16
  • 250
  • 324
  • Thanks. Your method worked. What I was really trying to learn was how to detect if the filetype was undefined. My "cat" filter was just a simplified example for the purposes of the question. However, I didn't know about and will now use that where apropos. Thanks also for your helpful postscript. – MERM Oct 11 '17 at 13:50
  • Perhaps `:help did_filetype()` is a safer bet in lieu of `empty(&filetype)`. – Enno Jul 04 '19 at 14:13
1

How about this?

autocmd BufEnter * :call SetFiletypeNewBuffer()
function! SetFiletypeNewBuffer()
  if @% == ""
    :set filetype=none
  endif
endfunction
autocmd FileType markdown,text,none  nnoremap <leader>f :1,$! cat
  • I was not tying to set the filetype to "none" I wanted to take an action when the filetype was not set (ie "none"). I probably was not clear on this. – MERM Oct 11 '17 at 14:20
1

if someone was interest for an equivalent solution in Lua for Neovim

    vim.api.nvim_create_autocmd('BufEnter', {
    pattern = '*',
    callback = function ()
        if (vim.tbl_contains({'', 'text', 'markdown'}, vim.o.filetype)) then
            -- add your autocmd logic here
            vim.schedule(function() print('empty/text/markdown file type detected') end)
        end
    end
})




Fedor
  • 17,146
  • 13
  • 40
  • 131