-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathpel_keys.el
9502 lines (8478 loc) · 417 KB
/
pel_keys.el
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
;;; pel_keys.el --- PEL key binding definitions -*-lexical-binding: t; -*-
;; Copyright (C) 2020, 2021, 2022, 2023, 2024, 2025 Pierre Rouleau
;; Author: Pierre Rouleau <[email protected]>
;; This file is part of the PEL package
;; This file is not part of GNU Emacs.
;; This program is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;;
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;;---------------------------------------------------------------------------
;;; Commentary:
;;
;; This file defines most PEL key bindings, with some defined by the pel-skels
;; files and by pel__hydra file.
;;
;; This file is *only* loaded by pel-init, nothing else.
;; This way time is only spent when pel-init is executed, not when
;; Emacs starts.
;;
;; Note: the file and feature name has been selected so that the file name
;; sorts after all other pel files but before pel.el to help ensure
;; a byte-compilation order when the package system byte-compiles them
;; during installation. The use of an underscore in the file name is
;; a little unusual in the Emacs Lisp world but provides a simple way
;; to provide proper file name ordering.
;;
;; Declaration of the auto-loaded interactive functions
;; ----------------------------------------------------
;;
;; The code uses the `pel-autoload-file' macro to setup the auto-loading of
;; interactive functions. The macro generates a call to the `autoload'
;; function and also generates a call to `declare-function' to prevent
;; byte-compiler warnings on code that reference the interactive functions
;; that are autoloaded. The `declare-function' form does not generate any
;; extra code: it is removed by the byte-compiler, but it prevents the
;; warnings.
;;
;; Some of the defun forms in this file are not top-level forms and are
;; declared inside a conditional form. For those, the byte-compiler would
;; generate a warning since it cannot guarantee the existence of the
;; functions. Therefore these defun forms are followed by `declare-function'
;; forms. The logic must therefore be correct to ensure the existence of the
;; function at run-time.
;; Major Mode setup
;; ----------------
;;
;; Each major mode supported by PEL is initialized when its corresponding
;; `pel-use-<mode>' user-option is turned on.
;;
;; Each major mode has a `pel-<mode>-activates-minor-modes' user-option that
;; identifies the minor-modes that must be automatically activated for the
;; major mode. These user-options are accessed via the `pel-config-major-mode'
;; macro.
;; Minor Modes
;; -----------
;;
;; The definition of minor mode symbols must be done prior to the definition
;; of any major mode, since the user may request the automatic activation of a
;; minor mode for a given major mode and the `pel-config-major-mode' macro checks
;; the validity of the minor mode symbols by calling the function
;; `pel--check-minor-modes-in'. That issues a warning if the minor mode
;; symbol is not loaded, it does not prevent Emacs from starting but the
;; warning message will be annoying. This check is not absolutely necessary
;; but it prevents undetected invalid entries in the customization.
;; Package Installation
;; --------------------
;;
;; The code uses the following macros to control package installation:
;;
;; - `pel-ensure-package' Installs an elpa-compliant package.
;;
;; - `pel-install-github-file' Installs a file from source stored in Github.
;; Used to install a file that is not an elpa
;; complaint package. The file is stored in the
;; PEL utils directory.
;;
;; - `pel-install-github-files' Installs multiple files from source stored in
;; Github. Used to install several files from a
;; *package* stored in GitHub that is not
;; elpa-compliant. The files are stored in the
;; PEL utils directory.
;; Delayed evaluation
;; ------------------
;;
;; The code uses the following functions to delay execution:
;;
;; - `pel-eval-after-load' : macro that evaluates its BODY after the
;; specified FEATURE was loaded. Useful to
;; extend or configure a major or minor mode.
;; This macro extends `with-eval-after-load' with
;; protection against error and formatted error
;; messages.
;;
;; - `with-eval-after-load' does the same with less error handling; it is used
;; in cases where less code is part of its BODY.
;;
;;; --------------------------------------------------------------------------
;;; Code:
;;;---------------------------------------------------------------------------
;; Required packages:
(eval-when-compile
(require 'cl-lib)) ; use: cl-eval-when
(require 'pel--base) ; use pel-system-is-macos-p
;; ; pel-system-is-windows-p
;; ; pel-emacs-is-a-tty-p
;; ; pel-emacs-is-graphic-p
;; ; pel-toggle
;; ; pel-mode-toggle-arg
;; ; pel-ensure-package
;; ;
;; ;
;; ;
;; ;
(require 'pel--macros) ; use: pel-setq, pel-seq-default
(require 'pel--keys-macros)
(require 'pel--options) ; all `pel-use-...' variables identify what to use.
;; ; also defines a set of utility functions to deal with
;; ; the options: pel-auto-complete-help
;; ---------------------------------------------------------------------------
;; Install Future-Proof Packages
;; -----------------------------
;;
;; Once you have PEL running and are comfortable with it, you should
;; activate the `pel-future-proof' user option.
(when pel-future-proof
;; - To ensure that the elpa signatures expiry becomes a problem
;; install gnu-elpa-keyring-update.
(pel-ensure-package gnu-elpa-keyring-update from: gnu)
;; Install Emacs backward compatibility package if required
(unless pel-emacs-29-or-later-p
(pel-ensure-package compat from: gnu)))
;; ---------------------------------------------------------------------------
;; Setup GUI launched Emacs environment
;; ------------------------------------
(defvar pel--init-called-once nil
"Remembers that `pel-init' was called. DO NOT MODIFY!")
(unless pel--init-called-once
(unless (getenv pel-shell-detection-envvar)
;; A GUI Emacs is running! Set up its process environment from user-option.
(when (and (require 'pel-process nil :no-error)
(fboundp 'pel-process-update-environment-from))
(pel-process-update-environment-from pel-gui-process-environment)))
(setq pel--init-called-once t))
;; ---------------------------------------------------------------------------
;; Configure PEL-level autoloading
;; -------------------------------
;; autoload all PEL functions
(require 'pel-autoload)
(if (fboundp 'pel--autoload-init)
(pel--autoload-init)
(message "ERROR! pel--autoload-init is not bound!"))
;; ---------------------------------------------------------------------------
;; Control Emacs prompting
;; -----------------------
(when pel-prompt-accept-y-n
;; Use 'y'/'n' or SPC/DEL instead of 'yes'/'no'
(fset 'yes-or-no-p 'y-or-n-p))
;; ---------------------------------------------------------------------------
;; Dual Environment Check
;; ----------------------
;;
;; When Emacs is running in graphic mode, verifies if the dual environment has
;; been requested and if so if it is set properly, activating it if necessary
;; and warning user on any remaining issue. Don't do it in terminal mode
;; because the terminal mode always uses the same files as Emacs usually does.
;; Schedule this check for some time after the initialization to prevent
;; slowing down Emacs startup.
(when (and pel-emacs-is-graphic-p
(or pel-support-dual-environment
(bound-and-true-p pel-init-support-dual-environment-p)
(bound-and-true-p pel-early-init-support-dual-environment-p))
(require 'pel-setup nil :no-error)
(fboundp 'pel-setup-check-dual-environment))
(run-at-time "3 sec" nil (function pel-setup-check-dual-environment)))
;; ---------------------------------------------------------------------------
;; Initialize Emacs source-directory if possible
;; ---------------------------------------------
(when pel-emacs-source-directory
(if (file-directory-p pel-emacs-source-directory)
(let ((src-subdir-name (expand-file-name "src" pel-emacs-source-directory)))
(if (file-directory-p src-subdir-name)
(setq source-directory pel-emacs-source-directory)
(message "\
Can't set Emacs source directory using %s : %s is not a directory!"
pel-emacs-source-directory
src-subdir-name)))
(message "\
Can't set Emacs source directory using %s : it's not a directory!"
pel-emacs-source-directory)))
;; ---------------------------------------------------------------------------
;; - PEL Modifier keys on different OS
;; -----------------------------------
;;
;; Ideally, mostly used keybindings are available on all platforms and
;; keyboards, with an easy to use layout.
;; The following is describing the use of modifier keys in the PEL system
;; so far.
;;
;; ======== ==== ======== ======== ============== =========== ===========
;; Modifier Symb Explicit Explicit 'darwin (gr) 'darwin (t) 'windows-nt
;; Key Key
;; ======== ==== ======== ======== ============== =========== ===========
;; Control C- Control Control Control Control Control
;; Meta M- Option Option Alt
;; Shift S- Shift Shift Shift
;; Hyper H- C-x @ h Fn Menu/App
;; Super s- C-x @ s Command⌘
;; Alt A- C-x @ a C-x 8
;; ======== ==== ======== ======== ============== =========== ===========
;; Use the macOS Function key (Fn) as emacs Hyper modifier
;; Note: this does not work on the terminal based emacs,
;; only on the graphics, Carbon-based emacs.
(when (and pel-system-is-macos-p
pel-emacs-is-graphic-p)
(pel-setq ns-function-modifier 'hyper))
;; On Windows, the Ctrl-Alt key combination works with letter keys
;; but does not work with the <right>, <left>, <up> and <down> keys.
;; As a work-around, this maps the apps key (between the right Windows
;; and Ctrl keys) to hyper and ensure that we add an extra binding
;; with hyper for the C-M-arrow keys.
(when pel-system-is-windows-p
;; The following do not seem to work:
;; - Ref: http://ergoemacs.org/emacs/emacs_hyper_super_keys.html
;; (setq w32-pass-lwindow-to-system nil)
;; (setq w32-lwindow-modifier 'hyper) ; Left Windows Key := hyper
;; (setq w32-pass-rwindow-to-system nil)
;; (setq w32-rwindow-modifier 'super) ; Right Windows key := super
;; but this works:
(pel-setq w32-pass-apps-to-system nil)
(pel-setq w32-apps-modifier 'hyper)) ; Menu/App key := hyper
;; ---------------------------------------------------------------------------
;; - Preserve negative-argument with C-- and C-_
;; ---------------------------------------------
;;
;; When running Emacs inside a terminal, the key C-- is not available since
;; there is no "Control -" in ASCII. On macOS, the terminal shells generate
;; the C-_ key when C-- is typed. Unfortunately C-_ is mapped to `undo' by
;; default, preventing quick access to the negative argument in a Control key
;; chord. By mapping C-_ to `negative-argument' we solve the problem.
;; We do it in graphics mode also, for consistency.
;;
;; PEL also bind M-_ to `negative-argument' to help accessing it when
;; the Meta key specifiers is used, to maintain typing velocity.
;;
;; PEL reserved key:: (kbd "C-M-_")
;;
;; The last possible combination, C-M-_ is *not* bound to the
;; negative-argument function. Instead it is *reserved* as a special
;; key sequence to use with a "lossless keyboard input" package such as
;; term-key.el to add ability to bind keys that are normally not accessible
;; in terminal mode.
(defun pel-bind-negative-argument ()
"Bind \\='C-_\\=' and \\='M-_\\=' to `negative-argument'.
Done in this function to allow advising libraries that remap these keys."
(global-set-key (kbd "C-_") 'negative-argument)
(global-set-key (kbd "M-_") 'negative-argument))
;; apply the binding - the function can be used also later - if needed
;; to advise functions in other libraries.
(pel-bind-negative-argument)
;; ---------------------------------------------------------------------------
;; Setting the mode of a fundamental-mode buffer
;; ---------------------------------------------
;;
;; Lots of script files have no extension and there's no logic in the
;; `auto-mode-alist' to identify the mode the buffer should use.
;; For those buffer you can type the <f12> key, which will prompt for
;; a major-mode to use, providing potential choices. Once a major mode is
;; selected that command binding is no longer available if PEL is controlling
;; the selected major mode.
;;
;; The mode selection is done by the logic of pel-as, which is aliased to the
;; shorter name `as'.
(global-set-key (kbd "<f12>") 'pel-as)
(when pel-has-alias-as
(defalias 'as 'pel-as "Select major mode for the buffer."))
;; ---------------------------------------------------------------------------
;; Inserting empty line above
;; --------------------------
(global-set-key (kbd "M-L") 'pel-insert-line-above)
;; ---------------------------------------------------------------------------
;; Binding for Greek Letter
;; ------------------------
(defconst pel-latin-to-greek
'(
("a" . "α")
("b" . "β")
("c" . "χ")
("d" . "δ")
("e" . "ε")
("f" . "ϕ")
("g" . "γ")
("h" . "η")
("i" . "ι")
("j" . "φ")
("k" . "κ")
("l" . "λ")
("m" . "μ")
("n" . "ν")
("o" . "ο")
("p" . "π")
("q" . "θ")
("r" . "ρ")
("s" . "σ")
("t" . "τ")
("u" . "υ")
("w" . "ω")
("x" . "ξ")
("y" . "ψ")
("z" . "ζ")
("A" . "Α")
("B" . "Β")
("C" . "Χ")
("D" . "Δ")
("E" . "Ε")
("F" . "Φ")
("G" . "Γ")
("H" . "Η")
("I" . "Ι")
("J" . "Φ")
("K" . "Κ")
("L" . "Λ")
("M" . "Μ")
("N" . "Ν")
("O" . "Ο")
("P" . "Π")
("Q" . "Θ")
("R" . "Ρ")
("S" . "Σ")
("T" . "Τ")
("U" . "Υ")
("W" . "Ω")
("X" . "Ξ")
("Y" . "Ψ")
("Z" . "Ζ"))
"Maps latin ASCII letter to the Greek equivalent.")
(defun pel-bind-greek-to (prefix)
"Add bindings for Greek letters under specified PREFIX."
(dolist (latin.greek pel-latin-to-greek)
(define-key
key-translation-map
(kbd
(format "%s %s"
prefix (car latin.greek)))
(cdr latin.greek))))
(pel-bind-greek-to "<f6> g")
(when pel-activate-f9-for-greek
(pel-bind-greek-to "<f9>"))
;; ---------------------------------------------------------------------------
;; tree-sitter support
;; -------------------
(when pel-use-tree-sitter
(if pel-emacs-has-dynamic-module-support-p
(if (and
(fboundp 'treesit-available-p)
(treesit-available-p))
(progn
(pel-ensure-package tree-sitter from: melpa)
(pel-ensure-package tree-sitter-langs from: melpa)
;; For some reason the treesit-extra-load-path variable is not always
;; set to the list of directories where tree sitter language dynamic
;; libraries are located. If pel-treesit-load-path is non-nil then
;; append it to the treesit-extra-load-path variable
(when (and (boundp 'treesit-extra-load-path)
pel-treesit-load-path)
(setq treesit-extra-load-path
(append treesit-extra-load-path pel-treesit-load-path)))
;; remember that PEL can now use tree-sitter modes.
(setq pel-uses-tree-sitter t))
(display-warning 'emacs-build
"Can't use tree-sitter:
Emacs must be compiled with --with-tree-sitter but it's not."))
(display-warning 'pel-package-install
"Can't install tree-sitter:
Tree-sitter requires Emacs built with dynamic module support.
Your version of Emacs does not support dynamic module.")))
;; ---------------------------------------------------------------------------
;; File format parsing support
;; ---------------------------
(add-to-list 'auto-mode-alist '("\\.repo\\'" . conf-unix-mode))
(add-to-list 'auto-mode-alist '("\\.permission\\'" . java-mode))
(add-to-list 'auto-mode-alist '("\\.properties\\'" . conf-javaprop-mode))
;; conf-mode further parses the file and selects an appropriate sub-mode.
(add-to-list 'auto-mode-alist '("\\.?.+rc\\'" . conf-mode))
;; files like /etc/ssh/ssh_config
(add-to-list 'auto-mode-alist '("\\.?.+config\\'" . conf-mode))
(when pel-system-is-linux-p
;; prevent Linux crypto-policy files to be opened as Pike programming language files.
(add-to-list 'auto-mode-alist
'("/usr/share/crypto-policies/policies/modules/.+\\.pmod\\'"
. conf-mode)))
(when pel-use-ini
(pel-install-github-file "pierre-rouleau/ini.el/master" "ini.el"))
(when pel-use-emacs-toml
(pel-ensure-package toml from: melpa)
(unless pel-use-tomlparse
(pel-major-mode-use-tree-sitter 'toml-mode 'toml-ts-mode)))
(when pel-use-tomlparse
;; This is only available when tree-sitter is available and
;; pel-use-tree-sitter is t.
(pel-install-github-file "johannes-mueller/tomlparse.el/master"
"tomlparse.el")
;; Use toml-ts-mode instead of Emacs standard `conf-toml-mode'
(add-to-list 'auto-mode-alist '("\\.toml\\'" . toml-ts-mode))
;; [:todo 2025-04-09, by Pierre Rouleau: May have to do the following code.
;; But I'm not sure it's required.]
;; (add-to-list
;; 'treesit-language-source-alist
;; '(toml "https://github.com/tree-sitter-grammars/tree-sitter-toml"))
;; (treesit-install-language-grammar "toml"
;; (expand-file-name
;; "tree-sitter"
;; user-emacs-directory))
;; [:todo 2025-04-09, by Pierre Rouleau: not sure if the following is needed]
(pel-autoload-function "tomlparse" for:
tomlparse-file
tomlparse-buffer
toml-string))
(when pel-use-kconfig-mode
(pel-install-github-file "delaanthonio/kconfig-mode/master" "kconfig-mode.el")
(add-to-list 'auto-mode-alist '("\\Kconfig\\'" . kconfig-mode))
(pel-autoload-file kconfig-mode for: kconfig-mode))
(when pel-use-dockerfile-mode
(pel-ensure-package dockerfile-mode from: melpa))
;; EditorConfig Support
;; --------------------
(when pel-use-editor-config
(pel-ensure-package editorconfig from: melpa)
(pel-require-at-load editorconfig)
(pel-eval-after-load editorconfig
(if (fboundp 'editorconfig-mode)
(editorconfig-mode 1)
(user-error "Failed loading editorconfig"))))
;; ---------------------------------------------------------------------------
;; - Font Control
;; --------------
(when pel-emacs-is-graphic-p
;; Activate the all-the-icons package to get nice icons in graphics mode if
;; requested.
;;
;; NOTE: you must install the icons manually by executing:
;; M-x all-the-icons-install-fonts
;;
(when (or pel-use-all-the-icons
pel-use-all-the-icons-ibuffer
pel-use-all-the-icons-dired
pel-use-all-the-icons-ivy
pel-neotree-font-in-graphics)
(pel-ensure-package all-the-icons from: melpa))
(when pel-use-all-the-icons-ibuffer
(pel-ensure-package all-the-icons-ibuffer)
(pel-require-at-load all-the-icons-ibuffer)
(pel-autoload-file all-the-icons-ibuffer for:
all-the-icons-ibuffer-mode)
(all-the-icons-ibuffer-mode 1))
(when pel-use-all-the-icons-dired
(pel-ensure-package all-the-icons-dired)
(pel-require-at-load all-the-icons-dired)
(add-hook 'dired-mode-hook 'all-the-icons-dired-mode))
(when pel-use-all-the-icons-ivy
(pel-ensure-package all-the-icons-ivy)
(pel-require-at-load all-the-icons-ivy)
(add-hook 'after-init-hook 'all-the-icons-ivy-setup))
;; On macOS, the keys used by the OS are the same as selected here, both in
;; GUI mode and in terminal (TTY) mode:
;; - In terminal mode: the Terminal.app uses the ⌘ command keys for fond size
;; control (it's not Emacs that acts on them, its the Terminal.app)
;; - In graphics mode the same keys handled by Emacs: the Super modifier is
;; assigned to the ⌘ Command key.
(when pel-system-is-macos-p
;; Bind the face-remap commands. The face-remap package
;; is part of Emacs standard distribution.
(global-set-key (kbd "s-=") #'text-scale-adjust)
(global-set-key (kbd "s-+") #'text-scale-adjust)
(global-set-key (kbd "s--") #'text-scale-adjust)
(global-set-key (kbd "s-0") #'text-scale-adjust)
;; Load the pel-font file only as needed.
;; Configure the pel-font commands as autoload.
(pel-autoload-file pel-font for:
pel-font-increase-size-all-buffers
pel-font-decrease-size-all-buffers
pel-font-reset-size-all-buffers)
(global-set-key (kbd "<s-kp-add>") 'pel-font-increase-size-all-buffers)
(global-set-key (kbd "<s-kp-subtract>") 'pel-font-decrease-size-all-buffers)
(global-set-key (kbd "<s-kp-0>") 'pel-font-reset-size-all-buffers)))
;; ---------------------------------------------------------------------------
;; - Buffer navigation
;; -------------------
;; Replace `list-buffer' by the nicer, more flexible and more
;; powerful `ibuffer'. Show in current window, not other one.
(global-set-key "\C-x\C-b" 'ibuffer)
;; ---------------------------------------------------------------------------
;; delight - control mode lighters
;; -------------------------------
(when pel-use-delight
(pel-ensure-package delight from: melpa)
(when (and pel-delight-specs
(fboundp 'delight))
(delight pel-delight-specs)))
(unless (string= pel-electric-pair-lighter "")
(add-to-list 'minor-mode-alist
(list 'electric-pair-mode pel-electric-pair-lighter)))
;; ---------------------------------------------------------------------------
;; ace-link
;; --------
;;
;; ace-link provides quick navigation in info-mode, help-mode, woman-mode,
;; eww-mode, compilation-mode, Custom mode and several other.
;; In these modes, the 'o' key puts a letter to identify the target links.
;; See URL https://github.com/abo-abo/ace-link
;; Delay its loading 1.5 seconds since it's normally not needed right away.
(when pel-use-ace-link
(pel-ensure-package ace-link from: melpa)
(pel-require-after-init ace-link 1.5)
(pel-eval-after-load ace-link
(if (fboundp 'ace-link-setup-default)
(ace-link-setup-default)
(display-warning 'pel-use-ace-link
"ace-link-setup-default is void"
:error))))
;; ---------------------------------------------------------------------------
;; avy: fast tree movement
;; -----------------------
;;
;; The avy package provides quick navigation inside any buffer and across
;; windows. See URL https://github.com/abo-abo/avy
(when pel-use-avy
(pel-ensure-package avy from: melpa)
(pel-autoload-file avy for:
avy-goto-char
avy-goto-char-2
avy-goto-char-timer
avy-goto-line
avy-goto-word-1
avy-goto-word-0)
;; Since avy uses home row keys for targets, the bindings also use keys
;; that are on the home row (at least for the the single key bindings).
;; This helps speed the typing. The meta key is used with some extra
;; bindings using the control key in graphics mode (since these keys are
;; not available in terminal mode).
(when pel-emacs-is-graphic-p
(global-set-key (kbd "C-:") 'avy-goto-char)
(global-set-key (kbd "C-'") 'avy-goto-char-2))
(global-set-key (kbd "M-G") 'avy-goto-char)
(global-set-key (kbd "M-g M-c") 'avy-goto-char)
(global-set-key (kbd "M-H") 'avy-goto-char-2)
(global-set-key (kbd "M-g M-j") 'avy-goto-char-2)
(global-set-key (kbd "M-g f") 'avy-goto-line)
(global-set-key (kbd "M-g l") 'avy-goto-line)
(global-set-key (kbd "M-g w") 'avy-goto-word-1)
(global-set-key (kbd "M-g e") 'avy-goto-word-0))
;; ---------------------------------------------------------------------------
;; Move to imenu symbol using Ido prompting
;; ----------------------------------------
(define-pel-global-prefix pel:cfg-goto (kbd "M-g <f4>"))
(global-set-key (kbd "M-g ?") 'pel-show-goto-symbol-settings)
(global-set-key (kbd "M-g M-SPC") 'pel-search-two-spaces)
(global-set-key (kbd "M-g M-RET") 'pel-search-empty-line)
(global-set-key (kbd "M-g i") 'imenu)
(global-set-key (kbd "M-g M-i") 'imenu)
(global-set-key (kbd "M-g h") 'pel-goto-symbol)
(global-set-key (kbd "M-g M-h") 'pel-goto-symbol)
(define-key pel:cfg-goto "h" 'pel-select-goto-symbol-UI)
(when pel-use-imenu-anywhere
(pel-ensure-package imenu-anywhere from: melpa)
(global-set-key (kbd "M-g y") 'pel-goto-symbol-any-buffer)
(global-set-key (kbd "M-g M-y") 'pel-goto-symbol-any-buffer)
(define-key pel:cfg-goto "y" 'pel-select-goto-symbol-any-buffer-UI))
;; pel-flimenu-mode is always available it displays info if flimenu-mode
;; is not available
(define-key pel:cfg-goto "f" 'pel-imenu-toggle-flatten)
(define-key pel:cfg-goto "o" 'pel-imenu-toggle-follows-order)
(define-key pel:cfg-goto "p" 'pel-imenu-toggle-popup)
(define-key pel:cfg-goto "R" 'pel-imenu-toggle-auto-rescan)
;; ---------------------------------------------------------------------------
;; PEL Top Level key prefix
;; ------------------------
;; <f11> Global key prefixes used for multiple packages:
(define-pel-global-prefix pel: (kbd "<f11>"))
(define-pel-global-prefix pel2: (kbd "<M-f11>"))
(define-pel-global-prefix pel:help (kbd "<f11> ?"))
(define-pel-global-prefix pel:mode (kbd "<f11> <f5>"))
;; ---------------------------------------------------------------------------
;; Dynamic configurations
;; ----------------------
;; <f11> <f4> will be used for commands that change the behaviour of
;; some basic operations, such as yank.
(define-pel-global-prefix pel:change (kbd "<f11> <f4>"))
(define-key pel:change (kbd "C-y") 'pel-toggle-overwrite-yank)
;; ---------------------------------------------------------------------------
;; Yank Operation
;; --------------
;;
;; PEL provides a basic yank command that behaves as Emacs standard yank
;; or as text replacement when the buffer is in overwrite mode.
;; This behaviour is controlled by the `pel-activate-overwrite-yank' user
;; option, which initializes the buffer local `pel--activate-overwrite-yank'.
;; That can be further modified dynamically in each buffer by execution of the
;; `pel-toggle-overwrite-yank' command.
(global-set-key (kbd "C-y") 'pel-overwrite-yank)
;; ---------------------------------------------------------------------------
;; Dired Extensions
;; ----------------
(define-pel-global-prefix pel:for-dired (kbd "<f11> SPC M-D"))
;;
;; activate the <f12> key binding for dired
(pel--mode-hook-maybe-call
(lambda ()
(pel-local-set-f12 'pel:for-dired))
'dired-mode 'dired-mode-hook)
;; Emacs ls emulation support
;; --------------------------
(when pel-use-emacs-ls-emulation
(defvar dired-use-ls-dired) ; prevent byte-compile warnings
(defvar ls-lisp-use-insert-directory-program) ; ditto
(setq dired-use-ls-dired nil)
(require 'ls-lisp)
(setq ls-lisp-use-insert-directory-program nil))
(when pel-use-undo-tree
(pel-eval-after-load dired
;; Ensure that `dired-undo' is available in Dired buffer.
(when (boundp 'dired-mode-map)
(define-key dired-mode-map (kbd "M-u") 'dired-undo)
(define-key dired-mode-map (kbd "C-x u") 'dired-undo)
(define-key dired-mode-map (kbd "C-/") 'dired-undo))))
(when pel-use-dired-sidebar
(pel-ensure-package dired-sidebar from: melpa)
(pel-autoload "dired-sidebar" for:
dired-sidebar-toggle-sidebar)
(add-hook 'dired-sidebar-mode-hook
(lambda ()
"Auto-refresh dired-sidebar for local directory."
(unless (file-remote-p default-directory)
(auto-revert-mode 1))))
(define-key pel: (kbd "C-d") 'dired-sidebar-toggle-sidebar)
(define-key pel:for-dired (kbd "C-d") 'dired-sidebar-toggle-sidebar))
;; Activate extra Dired-x features when requested.
(when pel-use-dired-x
(pel-eval-after-load dired
(load "dired-x" :noerror :nomessage)))
;; Activate dired-toggle-sudo when requested
;;
;; Future, if I have time to fork and fix its code.
;;
;; (when pel-use-dired-toggle-sudo
;; (pel-ensure-package dired-toggle-sudo from: melpa)
;; (with-eval-after-load 'dired
;; (when (boundp 'dired-mode-map)
;; (require 'dired-toggle-sudo)
;; (define-key dired-mode-map (kbd "C-c C-s") 'dired-toggle-sudo)
;; (with-eval-after-load 'tramp
;; (when (boundp 'tramp-default-proxies-alist)
;; ;; Allow to use: /sudo:user@host:/path/to/file
;; (add-to-list 'tramp-default-proxies-alist
;; '(".*" "\\`.+\\'" "/ssh:%h:")))))))
;; Open files with OS-registered applications from Dired
;; -----------------------------------------------------
(defvar dired-mode-map) ; forward declare - dired is loaded early in Emacs
(with-eval-after-load 'dired
(define-key dired-mode-map "z" 'pel-open-in-os-app))
;; dired-narrow
;; ------------
;; When dired-narrow is used, add <f12> prefix keys to dired-narrow specific
;; commands.
(when pel-use-dired-narrow
(pel-ensure-package dired-narrow from: melpa)
(pel-autoload-file dired-narrow for:
dired-narrow
dired-narrow-regexp
dired-narrow-fuzzy)
;; dired-narrow commands
(define-key pel:for-dired "s" 'dired-narrow)
(define-key pel:for-dired "r" 'dired-narrow-regexp)
(define-key pel:for-dired "f" 'dired-narrow-fuzzy))
(when pel-use-dired-hide-dotfiles
(pel-ensure-package dired-hide-dotfiles from: melpa)
(when (eq pel-use-dired-hide-dotfiles 'hide-dot-files-by-default)
(declare-function dired-hide-dotfiles-mode "dired-hide-dotfiles")
(add-hook 'dired-mode-hook (function dired-hide-dotfiles-mode)))
(with-eval-after-load 'dired
(define-key dired-mode-map "/" 'dired-hide-dotfiles-mode)))
(when pel-use-dired-git-info
(pel-ensure-package dired-git-info from: melpa)
(when (eq pel-use-dired-git-info 'on-for-git-directories)
(add-hook 'dired-after-readin-hook 'dired-git-info-auto-enable))
(with-eval-after-load 'dired
(define-key dired-mode-map ")" 'dired-git-info-mode)))
;; ---------------------------------------------------------------------------
;; - PEL: Window Behaviour & operations
;; ------------------------------------
;;
;; Uses: pel-window, which is autoloaded.
;;
;; Use multiple techniques to control creation, killing and navigation
;; across windows. Provide CRiSP-like function-key/cursor operations as
;; well as extra operations via 3 packages: windmove, ace-window and
;; winner-mode. All Emacs default windows operation key bindings are
;; retained (except for 'C-x o' which is remapped to ace-window).
;; The operations are:
;;
;; - CRiSP-like operations (implemented using windmove and PEL code):
;; - navigation: <f11> cursor (point where to move point to)
;; - creation : <f11> C-cursor (point to where to create window)
;; - kill : <f11> C-S-cursor (point to window to kill)
;;
;; - ace-window assigned to 'C-x o', replacing other-window, which
;; provides a single digit window number in the top left corner of each
;; window when moving windows.
;;
;; - Use winner-mode (assigned to '<f11> w p' and '<f11> w n') to restore previous
;; or next window layout.
;;
;; - '<f11> w s' based keys to resize windows with following keys:
;; - V : increase vertical size
;; - v : decrease vertical size
;; - H : increase horizontal size
;; - h : decrease horizontal size
;;
;; Since the above are long to type, once you type one, use 'C-x z' to
;; repeat, typing 'z' subsequently to repeat again, or even easier: <f5>.
;;
;; - Original window kill: 'C-x 0' and 'C-x 1'
;; - Original window split and creation: 'C-x 2' and 'C-x 3'
;;
;; - Mode Activation - cursor window movement: windmove and framemove
;; ------------------------------------------------------------------
;; In graphics mode, more keys are accessible and some of them
;; can be used with cursor keys to help navigation across Emacs
;; windows:
;; - for Windows: H-left, H-right, H-up and H-down
;; - for macOS : s-left, s-right, s-up and s-down.
;;
;; Also, in graphics mode, if a (modified) version of the
;; framemove.el file is available, then we can allow the
;; window move navigation to expand moving away from the
;; current frame into the others surrounding frames.
;; windmove is part of Emacs. It's loading is controlled by pel-window, where
;; it is used, via autoloading. Here, just identify default keybindings when
;; Emacs is running in graphics mode. Other keybindings are defined for the
;; pel: keybinding, somewhere else in this file.
(when pel-emacs-is-graphic-p
;; In graphics mode provide control over cursor color and type (shape): the
;; logic is in the pel-cursor.el file.
;; Don't delay loading: it's small enough.
(require 'pel-cursor)
(define-key pel: (kbd "C-c") 'pel-set-cursor-color)
;; Add key cursor bindings for windmove when Emacs runs in graphics mode.
;; The windmove package is autoloaded via the pel-window file. It's not
;; enough in graphics mode: we need to either set the default bindings (and
;; then we force autoload of windmove) or force users to use something else
;; of windmove to activate its special binding. None of this is a good
;; solution. So, as a compromise to delay the loading of windmove, just
;; defer it for a specific amount of time, and then schedule the setting of
;; the special binding when it is actually loaded.
(pel-require-after-init windmove 1)
(pel-autoload-file windmove for: windmove-default-keybindings)
(pel-eval-after-load windmove
(windmove-default-keybindings (if pel-system-is-macos-p
'super
'hyper)))
(when pel-use-framemove
;; In graphics mode, bindings to go directly to another frame
;; without having to move through all intervening windows in current
;; frame.
;; download and byte-compile framemove if not already present.
;; Do it after compiling pel_keys.el, when pel-init load pel_keys.
(pel-install-github-file "emacsmirror/framemove/master" "framemove.el")
(pel-autoload-file framemove for:
fm-up-frame
fm-down-frame
fm-left-frame
fm-right-frame)
(pel-eval-after-load framemove
(when (boundp 'framemove-hook-into-windmove)
(setq framemove-hook-into-windmove t)))
(global-set-key (kbd "ESC <S-up>") 'fm-up-frame)
(global-set-key (kbd "ESC <S-down>") 'fm-down-frame)
(global-set-key (kbd "ESC <S-right>") 'fm-right-frame)
(global-set-key (kbd "ESC <S-left>") 'fm-left-frame)
(define-key pel: (kbd "<S-down>") 'fm-down-frame)
(define-key pel: (kbd "<S-up>") 'fm-up-frame)
(define-key pel: (kbd "<S-left>") 'fm-left-frame)
(define-key pel: (kbd "<S-right>") 'fm-right-frame)))
;; - Full Screen and Mouse Control
;; -------------------------------
(define-key pel: (kbd "<f11>") 'pel-toggle-frame-fullscreen)
(when pel-emacs-is-a-tty-p
(define-key pel: (kbd "<f12>") #'xterm-mouse-mode))
;; - Uniquify: meaningful names when multiple buffers have the same name
;; ---------------------------------------------------------------------
;; Uniquify provides meaningful names for buffers with the same name.
;; The following code snippet evolved from what's available on
;; https://github.com/bbatsov/prelude.
;; uniquify is now part of Emacs distribution.
(when pel-use-uniquify
(pel-require-at-load uniquify)
(pel-eval-after-load uniquify
(pel-setq uniquify-buffer-name-style 'post-forward)
;; rationalize buffer after killing uniquified buffer
(pel-setq uniquify-after-kill-buffer-p t)
;; Don't not uniquify special buffers
(pel-setq uniquify-ignore-buffers-re "^\\*")))
;; - Use Hippie Expand
;; -------------------
(when pel-use-hippie-expand
(global-set-key [remap dabbrev-expand] 'hippie-expand)
;; Default PEL setup for Hippie Expand is to use DAbbrev *first*
;; as this is what most search need, then search in other buffers
;; and file names.
;; Don't do source code expansion: that will be handled by the
;; completion facilities (like completion-at-point, Company mode, etc...)
(setq hippie-expand-try-functions-list
(quote
(try-expand-dabbrev
try-expand-dabbrev-all-buffers
try-complete-file-name-partially
try-complete-file-name))))
;; Other search rules exist, they are:
;; - try-expand-all-abbrevs
;; - try-complete-lisp-symbol-partially
;; - try-complete-lisp-symbol
;; - try-expand-list
;; - try-expand-dabbrev-from-kill
;; - try-expand-line
;; ---------------------------------------------------------------------------
;; - Extra key bindings
;; --==================
;;
;; - Numeric Keypad Keys
;; ---------------------
;;
;; The nummeric keypad has 18 keys. They are shown here:
;;
;; +==========================+
;; |Numlock = / * |
;; | 7 8 9 - |
;; | 4 5 6 + |
;; | 1 2 3 Enter |
;; | ---0--- . Enter |
;; +==========================+
;;
;; The numeric keypad keys behave differently when Emacs is running in
;; graphics mode and when it is running in Terminal mode. Another difference
;; is between the PC-keyboard and the macOS keyboards. The PC-keyboard has a
;; numlock key, but the macOS keyboards do not: the Numlock is a clear key.
;;
;; PEL attempts to provide the exact same behaviour for these keys in both
;; modes for all environments despite the difference.
;;
;; -- Numlock/Clear
;;
;; For macOS, the top-left key, labelled as "NumLock" above, is detected only
;; in graphics mode and is the [clear] key. The Terminal mode does not detect
;; that key. So 2 key bindings are done: - [clear] is mapped to
;; pel-toggle-mac-numlock - <f11> # is also mapped to pel-toggle-mac-numlock
;; (see later)
(global-set-key [clear] 'pel-toggle-mac-numlock)
;; -- The keys +, / and *
;;
;; The "=", "/" and "*" keys are untouched, left to self-insert in all cases.
;;
;; -- The numeric keys: 0 to 9
;;
;; The numeric keys are mapped to pel-0 to pel-9 commands. These commands
;; check the state of num-locking managed by the pel-numkpad.el to determine
;; how they should behave: in num-lock they just self insert the corresponding
;; digit. When not num-locked, the keys implement other operations: cursor
;; movement, etc...
;;
;; On graphics mode Emacs is able to generate M-<kp-8> when the Meta key is
;; pressed while the keypad 8 is pressed. That does not work in Terminal mode.
;; On macOS the keypad 0 key registers as kp-0, but on Linux and Windows it
;; registers as <insertchar> when numlock is off.
(if (or pel-system-is-macos-p pel-keypad-0-is-kp-yank)
(global-set-key [kp-0] 'pel-0)
(global-set-key (kbd "<insertchar>") 'pel-0))
(global-set-key [kp-1] 'pel-1)
(global-set-key [kp-2] 'pel-2)
(global-set-key [kp-3] 'pel-3)
(global-set-key [kp-4] 'pel-4)
(global-set-key [kp-5] 'pel-5)
(global-set-key [kp-6] 'pel-6)
(global-set-key [kp-7] 'pel-7)
(global-set-key [kp-8] 'pel-8)
(global-set-key [kp-9] 'pel-9)
;; On some keyboards, when in non-numlock the key 0 acts as [kp-insert].
;; This is not available on macOS but it is under Windows keyboards.
;; Also under Windows the key '5' when not num-locked is [kp-space].
;; Therefore PEL configures these keys for Windows only,
;; on macOS it does not, instead it relies on the binding of [kp-0] to pel-0
;; and of [kp-5] to pel-5 to handle it.
(when pel-system-is-windows-p
(global-set-key [kp-insert] 'pel-overwrite-yank)
(global-set-key [kp-space] 'recenter-top-bottom))
;; -- The . ([kp-decimal]) key