Make a separate byte-compiled function for each file, using closure support in emacs with lexical bindings: (defun sw/make-find-file-function (file) (lambda () (interactive) (find-file file))) At emacs startup, make an uninterned symbol with the filename as its name, and fset its function definition to this closure: (defmacro sw/define-file-key (keymap key file) (unless (stringp file) (signal 'wrong-type-argument (list 'stringp file))) (let ((fn (sw/make-find-file-function file))) `(let ((sym (make-symbol ,file))) (fset sym ',fn) (define-key ,keymap ,key sym)))) Byte code for (sw/define-file-key ctl-x-map [?t ?f] "~/git/foo/tests/foo.el"): 190 constant make-symbol 193 constant "~/git/foo/tests/foo.el" 196 call 1 ; Make an uninterned symbol 197 dup ; that gets displayed as the ; keybinding 198 constant args: nil interactive: nil 0 constant find-file 1 constant "~/git/foo/tests/foo.el" 2 call 1 3 return 201 fset ; Set the function slot to a ; function constant that calls ; find-file on this file 202 discard 203 constant define-key 206 varref ctl-x-map 207 constant [116 102] 210 stack-ref 3 211 call 3 ; Call define-key to bind ; C-x tf to this symbol 212 discardN 2 Now describe-bindings and helm-descbinds show the filename instead of "??".