Monday, May 13, 2013

Keyboard shortcuts for the SciTE code editor

One of the reasons I use the SciTE code editor is that keyboard shortcuts can be easily changed in a plain-text configuration file.

If you use SciTE, here is a Python script to list current keyboard shortcuts. You will need to have downloaded SciTE's source code, or at least download the file SciTERes.rc.

# list SciTE shortcuts
# Ben Fisher,
# 1) shortcuts from user.shortcuts
# 2) shortcuts from commands
# 3) shortcuts from SciTE's rc
# does not include scintilla's simple keybindings (see KeyMap.cxx KeyMap::MapDefault)

scite_src = 'path/to/scite'
scite_props = 'path/to/sciteinstall/properties'
specificfiletypes = []
# specificfiletypes = ['*.py', '$(']

import os, sys, re

class Shortcut(object):
  def __init__(self, name='',keys='',filetypes='',type='plugin'):; self.keys=keys; self.filetypes=filetypes; self.type=type
  def __str__(self):
    return self.keys.ljust(20) + self.type
  def getsortkey(self):
    # create a tuple specifying sort priority. length of key-shortcut is most important.
    sortvallastpart = self.keys.split('+')[-1]
    sortlenlastpart = len(sortvallastpart)
    sorttypepriority = dict(builtin=3, usershortcuts=2, plugin=1).get(self.type, 0)
    return (sortlenlastpart, sortvallastpart,self.keys, sorttypepriority)

def go():
  scite_src_rc = os.path.join(scite_src, 'win32', 'SciTERes.rc')
  assert os.path.exists(scite_src)
  assert os.path.exists(scite_src)
  assert os.path.exists(scite_props)
  if not os.path.exists(os.path.join(scite_props, '')):
    print 'warning: not found.'
  results = []
  f = open(scite_src_rc, 'r')
  bAccels = False
  for line in f:
    if bAccels:
      if line=='BEGIN' or not line or line=='*/': continue
      if line.startswith('//') or line.startswith('#') or line.startswith('/*'): continue
      if line=='END': break
      items = [item.strip() for item in line.split(',')]
      keys = items[0].replace('"','').replace('VK_','')
      keys = keys[0].upper() + keys[1:].lower()
      if 'SHIFT' in items: keys = 'Shift+'+keys
      if 'ALT' in items: keys = 'Alt+'+keys
      if 'CONTROL' in items: keys = 'Ctrl+'+keys
      results.append(Shortcut(items[1], keys, '*', 'builtin'))
    if line=='ACCELS ACCELERATORS': bAccels = True
  propcmds = {}
  for filename in os.listdir(scite_props):
    if not filename.lower().endswith('.properties'): continue
    f = open(os.path.join(scite_props, filename))
    bUsershort=False # are we currently looking at user.shortcuts
    for line in f:
      if bUsershort:
        if '|' in line:
          shortcut, cmd, unused = line.split('|')
          results.append(Shortcut(cmd, shortcut, '*', 'usershortcuts'))
        if not line.endswith('\\'): bUsershort=False
        parse = re.match(r'command\.(name|shortcut)\.(\w+)\.([^=]+)=(.*)', line)
        if parse and in specificfiletypes:
          # add to a dict of in-progress commands
          obj = propcmds.setdefault(';', Shortcut())
          obj.filetypes =
          if len( obj.keys = 'Ctrl+'
          if'name': =;
          elif'shortcut': obj.keys =

        if line.startswith('user.shortcuts='): bUsershort=True
  for propcmd in propcmds: results.append(propcmds[propcmd])
  results.sort(key = lambda item: item.getsortkey())
  for res in results:
    if not'IDM_BUFFER+'):
      if not'IDM_TOOLS+'):

if __name__=='__main__':