tags:

views:

1278

answers:

6

I'm an avid vim user and have started to write some SQL code recently. I like to write my SQL statements in CAPS and sometimes forget to switch CAPS LOCK off and I then quickly wreak havoc on my code before I realise what's happening.

I have so far not found any way to tell whether the CAPS LOCK key is on other than looking at my keyboard (which requires me to look away from the screen which I consider a big delay).

Ideally I would like vim to automatically change my background colour whenever CAPS LOCK is on but I'd be willing to settle for some other on-screen indicator of CAPS LOCK status as a compromise.

+2  A: 

What I did is bound my caps lock key to the "Compose" key, so my capslock key is effectively missing and I just force myself to use SHIFT instead. :)

You might want to try it, it may sound masochistic, but its better in the long run. Some argue the Caps lock is redundant.

Kent Fredric
That's an option but I prefer not to go down this route.I find that the Caps Lock key does help and would prefer to keep using it.
snth
+1  A: 

The best I can give you is to have vim toggle the background color whenever the CAPSLOCK key is hit in vim.

Vim can't detect the CAPSLOCK key alone. What I can give you is a mapping so you can use some other key (in this example, F3) to act like the CAPSLOCK key for insert mode, and change the background color when all-caps is on. Hopefully this will give you the functionality you need.

Put the following in your ~/.vimrc or in the appropriate ~/.vim/ftplugin/<filetype>.vim :

 " let the case be toggled in normal mode
 map <expr> <F3> ToggleInsertCase()
 " let the case be toggled in insert mode
 imap <expr> <F3> ToggleInsertCase()

 let toUpper = 0
 func! ToggleInsertCase() 
  let g:toUpper = 1 - g:toUpper
  if (g:toUpper == 1)
   highlight Normal ctermbg=Blue " the background color you want when uppercased
   " convert all the letters to uppercase in insert mode
   let i = char2nr('a')
   while i <= char2nr('z')
    let c = nr2char(i)
    exe 'inoremap' c toupper(c)
    let i = i + 1
   endwhile
  else
   highlight Normal ctermbg=Black " the background color you want normally
   " let letters be as normal in insert mode
   let i = char2nr('a')
   while i <= char2nr('z')
    let c = nr2char(i)
    exe 'iunmap' c 
    let i = i + 1
   endwhile
  endif
  " don't insert anything when this function is called in normal mode
  return ""
 endfunc

This borrows some from Tim Pope's capslock.vim.

If you really want to use the CAPSLOCK key for this, depending on your platform, there's a bunch of free apps that let you remap your CAPSLOCK key to something else, so you could set it up so that when you hit CAPSLOCK, vim (and everything else) got F3. Or whatever. This would interfere with other apps getting the CAPSLOCK key though (unless the key-remapper app is clever), so that could be troublesome.

rampion
This approach would be perfect as all I need to ensure then is that I don't have Caps Lock on when I enter vim from another window.Could you perhaps flesh this out a bit more? I haven't written vimscript before and playing around with the commands you gave didn't give quite what I expected.Thanks.
snth
+2  A: 

The closest you can get is Kent's answer. Vim cannot see CAPS LOCK (or NUM LOCK, or SCROLL LOCK, or any other modifier key by itself) because the status of these keys is not sent across a terminal.

Note that, in theory, gVim could see these modifiers, but in practice it does not. gVim's keyboard handling is superior to vim's though in many other ways.

Zathrus
A: 

Why not have a filetype plugin for .sql files that contain imap commands to convert all your keystrokes to caps. That way, you never have to toggle the actual capslock key on the keyboard and things will be fine when you go back to code.

Add the following in the file $VIM/vimfiles/ftplugin/sql_too.vim :

imap a A
imap b B
imap c C
imap d D
imap e E
imap f F
imap g G
imap h H
imap i I
imap j J
imap k K
imap l L
imap m M
imap n N
imap o O
imap p P
imap q Q
imap r R
imap s S
imap t T
imap u U
imap v V
imap w W
imap x X
imap y Y
imap z Z
Gowri
That's an idea but there are also other occasions where I like to write caps, like in shell scripts that use environment variables. Also, in the SQL code I still need to be able to write the table names and column names in CamelCase and mixed case and how would I do that here?
snth
A: 

I agree with Kent, and remap the Caps Lock key to the control key. I used AutoHotKey to do this on Windows boxes, but there's a registry setting as described here and many other places. If you're not using Windows, you can also easily remap the caps lock key on MacOS and unix X window platforms.

The convenience of not accidentally having caps lock on, far outweighes the few times a year I would actually want it!

Jon DellOro
+2  A: 

The person who suggested mapping lowercase letters to upper case is on the right track but we need to add some more details. The trick is to map SQL keywords to upper case. Then you can type them in lowercase and vim will convert them to uppercase for you. This is done using abbreviations, not mappings. For example, if you create the abbreviation

:iab ATT American Telephone and Telegraph

then every time you type 'ATT' in your code, Vim will automatically translate it to 'American Telephone and Telegraph' as soon as you hit the space bar. (Try it! It's fun!)

So, create a new file and start entering abbreviations for all the SQL keywords.

iab select SELECT
iab like LIKE
iab where WHERE
...

Since you only want these abbreviations to apply when you're editing SQL source, save this file to ~/.vim/after/ftplugin/sql.vim The commands in this file will be executed when Vim detects it has opened a SQL file.

The file type detection only works if you turn it on so make sure your .vimrc has lines like:

set nocompat
filet detect plugin on

Once you get this working you should save time and have less carpal tunnel from holding down the shift key all the time!

Steve K