-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathspacemacs.el
1794 lines (1673 loc) · 84.5 KB
/
spacemacs.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
;; -*- mode: emacs-lisp -*-
;; This file is loaded by Spacemacs at startup.
;; It must be stored in your home directory.
;; use apsell as ispell backend
(setq-default ispell-program-name "aspell")
;; use American English as ispell default dictionary
(ispell-change-dictionary "american" t)
(defun dotspacemacs/layers ()
"Configuration Layers declaration.
You should not put any user code in this function besides modifying the variable
values."
(setq-default
;; Base distribution to use. This is a layer contained in the directory
;; `+distribution'. For now available distributions are `spacemacs-base'
;; or `spacemacs'. (default 'spacemacs)
dotspacemacs-distribution 'spacemacs
;; Lazy installation of layers (i.e. layers are installed only when a file
;; with a supported type is opened). Possible values are `all', `unused'
;; and `nil'. `unused' will lazy install only unused layers (i.e. layers
;; not listed in variable `dotspacemacs-configuration-layers'), `all' will
;; lazy install any layer that support lazy installation even the layers
;; listed in `dotspacemacs-configuration-layers'. `nil' disable the lazy
;; installation feature and you have to explicitly list a layer in the
;; variable `dotspacemacs-configuration-layers' to install it.
;; (default 'unused)
dotspacemacs-enable-lazy-installation 'unused
;; If non-nil then Spacemacs will ask for confirmation before installing
;; a layer lazily. (default t)
dotspacemacs-ask-for-lazy-installation t
;; If non-nil layers with lazy install support are lazy installed.
;; List of additional paths where to look for configuration layers.
;; Paths must have a trailing slash (i.e. `~/.mycontribs/')
dotspacemacs-configuration-layer-path '()
;; List of configuration layers to load.
dotspacemacs-configuration-layers
'(
;; ----------------------------------------------------------------
;; Example of useful layers you may want to use right away.
;; Uncomment some layer names and press <SPC f e R> (Vim style) or
;; <M-m f e R> (Emacs style) to install them.
;; ----------------------------------------------------------------
helm
python
;; auto-completion
;; better-defaults
emacs-lisp
;; git
;; markdown
org
;; (shell :variables
;; shell-default-height 30
;; shell-default-position 'bottom)
spell-checking
syntax-checking
;; version-control
)
;; List of additional packages that will be installed without being
;; wrapped in a layer. If you need some configuration for these
;; packages, then consider creating a layer. You can also put the
;; configuration in `dotspacemacs/user-config'.
dotspacemacs-additional-packages '()
;; A list of packages that cannot be updated.
dotspacemacs-frozen-packages '()
;; A list of packages that will not be installed and loaded.
dotspacemacs-excluded-packages '()
;; Defines the behaviour of Spacemacs when installing packages.
;; Possible values are `used-only', `used-but-keep-unused' and `all'.
;; `used-only' installs only explicitly used packages and uninstall any
;; unused packages as well as their unused dependencies.
;; `used-but-keep-unused' installs only the used packages but won't uninstall
;; them if they become unused. `all' installs *all* packages supported by
;; Spacemacs and never uninstall them. (default is `used-only')
dotspacemacs-install-packages 'used-only))
(defun dotspacemacs/init ()
"Initialization function.
This function is called at the very startup of Spacemacs initialization
before layers configuration.
You should not put any user code in there besides modifying the variable
values."
;; This setq-default sexp is an exhaustive list of all the supported
;; spacemacs settings.
(setq-default
;; If non nil ELPA repositories are contacted via HTTPS whenever it's
;; possible. Set it to nil if you have no way to use HTTPS in your
;; environment, otherwise it is strongly recommended to let it set to t.
;; This variable has no effect if Emacs is launched with the parameter
;; `--insecure' which forces the value of this variable to nil.
;; (default t)
dotspacemacs-elpa-https t
;; Maximum allowed time in seconds to contact an ELPA repository.
dotspacemacs-elpa-timeout 5
;; If non nil then spacemacs will check for updates at startup
;; when the current branch is not `develop'. Note that checking for
;; new versions works via git commands, thus it calls GitHub services
;; whenever you start Emacs. (default nil)
;; dotspacemacs-check-for-update nil
;; If non-nil, a form that evaluates to a package directory. For example, to
;; use different package directories for different Emacs versions, set this
;; to `emacs-version'.
dotspacemacs-elpa-subdirectory nil
;; One of `vim', `emacs' or `hybrid'.
;; `hybrid' is like `vim' except that `insert state' is replaced by the
;; `hybrid state' with `emacs' key bindings. The value can also be a list
;; with `:variables' keyword (similar to layers). Check the editing styles
;; section of the documentation for details on available variables.
;; (default 'vim)
dotspacemacs-editing-style 'vim
;; If non nil output loading progress in `*Messages*' buffer. (default nil)
dotspacemacs-verbose-loading nil
;; Specify the startup banner. Default value is `official', it displays
;; the official spacemacs logo. An integer value is the index of text
;; banner, `random' chooses a random text banner in `core/banners'
;; directory. A string value must be a path to an image format supported
;; by your Emacs build.
;; If the value is nil then no banner is displayed. (default 'official)
dotspacemacs-startup-banner 'official
;; List of items to show in startup buffer or an association list of
;; the form `(list-type . list-size)`. If nil then it is disabled.
;; Possible values for list-type are:
;; `recents' `bookmarks' `projects' `agenda' `todos'."
;; List sizes may be nil, in which case
;; `spacemacs-buffer-startup-lists-length' takes effect.
dotspacemacs-startup-lists '((recents . 5)
(projects . 7))
;; True if the home buffer should respond to resize events.
dotspacemacs-startup-buffer-responsive t
;; Default major mode of the scratch buffer (default `text-mode')
dotspacemacs-scratch-mode 'text-mode
;; List of themes, the first of the list is loaded when spacemacs starts.
;; Press <SPC> T n to cycle to the next theme in the list (works great
;; with 2 themes variants, one dark and one light)
dotspacemacs-themes '(manoj-dark
spacemacs-light)
;; If non nil the cursor color matches the state color in GUI Emacs.
dotspacemacs-colorize-cursor-according-to-state t
;; Default font, or prioritized list of fonts. `powerline-scale' allows to
;; quickly tweak the mode-line size to make separators look not too crappy.
dotspacemacs-default-font '("Hack Nerd Font"
:size 20
:weight normal
:width normal
:powerline-scale 1.1)
;; The leader key
dotspacemacs-leader-key "SPC"
;; The key used for Emacs commands (M-x) (after pressing on the leader key).
;; (default "SPC")
dotspacemacs-emacs-command-key "SPC"
;; The key used for Vim Ex commands (default ":")
dotspacemacs-ex-command-key ":"
;; The leader key accessible in `emacs state' and `insert state'
;; (default "M-m")
dotspacemacs-emacs-leader-key "M-m"
;; Major mode leader key is a shortcut key which is the equivalent of
;; pressing `<leader> m`. Set it to `nil` to disable it. (default ",")
dotspacemacs-major-mode-leader-key ","
;; Major mode leader key accessible in `emacs state' and `insert state'.
;; (default "C-M-m")
dotspacemacs-major-mode-emacs-leader-key "C-M-m"
;; These variables control whether separate commands are bound in the GUI to
;; the key pairs C-i, TAB and C-m, RET.
;; Setting it to a non-nil value, allows for separate commands under <C-i>
;; and TAB or <C-m> and RET.
;; In the terminal, these pairs are generally indistinguishable, so this only
;; works in the GUI. (default nil)
dotspacemacs-distinguish-gui-tab nil
;; If non nil `Y' is remapped to `y$' in Evil states. (default nil)
dotspacemacs-remap-Y-to-y$ nil
;; If non-nil, the shift mappings `<' and `>' retain visual state if used
;; there. (default t)
dotspacemacs-retain-visual-state-on-shift t
;; If non-nil, J and K move lines up and down when in visual mode.
;; (default nil)
dotspacemacs-visual-line-move-text nil
;; If non nil, inverse the meaning of `g' in `:substitute' Evil ex-command.
;; (default nil)
dotspacemacs-ex-substitute-global nil
;; Name of the default layout (default "Default")
dotspacemacs-default-layout-name "Default"
;; If non nil the default layout name is displayed in the mode-line.
;; (default nil)
dotspacemacs-display-default-layout nil
;; If non nil then the last auto saved layouts are resume automatically upon
;; start. (default nil)
dotspacemacs-auto-resume-layouts nil
;; Size (in MB) above which spacemacs will prompt to open the large file
;; literally to avoid performance issues. Opening a file literally means that
;; no major mode or minor modes are active. (default is 1)
dotspacemacs-large-file-size 1
;; Location where to auto-save files. Possible values are `original' to
;; auto-save the file in-place, `cache' to auto-save the file to another
;; file stored in the cache directory and `nil' to disable auto-saving.
;; (default 'cache)
dotspacemacs-auto-save-file-location 'cache
;; Maximum number of rollback slots to keep in the cache. (default 5)
dotspacemacs-max-rollback-slots 5
;; If non nil, `helm' will try to minimize the space it uses. (default nil)
dotspacemacs-helm-resize nil
;; if non nil, the helm header is hidden when there is only one source.
;; (default nil)
dotspacemacs-helm-no-header nil
;; define the position to display `helm', options are `bottom', `top',
;; `left', or `right'. (default 'bottom)
dotspacemacs-helm-position 'bottom
;; Controls fuzzy matching in helm. If set to `always', force fuzzy matching
;; in all non-asynchronous sources. If set to `source', preserve individual
;; source settings. Else, disable fuzzy matching in all sources.
;; (default 'always)
dotspacemacs-helm-use-fuzzy 'always
;; If non nil the paste micro-state is enabled. When enabled pressing `p`
;; several times cycle between the kill ring content. (default nil)
dotspacemacs-enable-paste-transient-state nil
;; Which-key delay in seconds. The which-key buffer is the popup listing
;; the commands bound to the current keystroke sequence. (default 0.4)
dotspacemacs-which-key-delay 0.4
;; Which-key frame position. Possible values are `right', `bottom' and
;; `right-then-bottom'. right-then-bottom tries to display the frame to the
;; right; if there is insufficient space it displays it at the bottom.
;; (default 'bottom)
dotspacemacs-which-key-position 'bottom
;; If non nil a progress bar is displayed when spacemacs is loading. This
;; may increase the boot time on some systems and emacs builds, set it to
;; nil to boost the loading time. (default t)
dotspacemacs-loading-progress-bar t
;; If non nil the frame is fullscreen when Emacs starts up. (default nil)
;; (Emacs 24.4+ only)
dotspacemacs-fullscreen-at-startup nil
;; If non nil `spacemacs/toggle-fullscreen' will not use native fullscreen.
;; Use to disable fullscreen animations in OSX. (default nil)
dotspacemacs-fullscreen-use-non-native nil
;; If non nil the frame is maximized when Emacs starts up.
;; Takes effect only if `dotspacemacs-fullscreen-at-startup' is nil.
;; (default nil) (Emacs 24.4+ only)
dotspacemacs-maximized-at-startup nil
;; A value from the range (0..100), in increasing opacity, which describes
;; the transparency level of a frame when it's active or selected.
;; Transparency can be toggled through `toggle-transparency'. (default 90)
dotspacemacs-active-transparency 90
;; A value from the range (0..100), in increasing opacity, which describes
;; the transparency level of a frame when it's inactive or deselected.
;; Transparency can be toggled through `toggle-transparency'. (default 90)
dotspacemacs-inactive-transparency 90
;; If non nil show the titles of transient states. (default t)
dotspacemacs-show-transient-state-title t
;; If non nil show the color guide hint for transient state keys. (default t)
dotspacemacs-show-transient-state-color-guide t
;; If non nil unicode symbols are displayed in the mode line. (default t)
dotspacemacs-mode-line-unicode-symbols t
;; If non nil smooth scrolling (native-scrolling) is enabled. Smooth
;; scrolling overrides the default behavior of Emacs which recenters point
;; when it reaches the top or bottom of the screen. (default t)
dotspacemacs-smooth-scrolling t
;; Control line numbers activation.
;; If set to `t' or `relative' line numbers are turned on in all `prog-mode' and
;; `text-mode' derivatives. If set to `relative', line numbers are relative.
;; This variable can also be set to a property list for finer control:
;; '(:relative nil
;; :disabled-for-modes dired-mode
;; doc-view-mode
;; markdown-mode
;; org-mode
;; pdf-view-mode
;; text-mode
;; :size-limit-kb 1000)
;; (default nil)
dotspacemacs-line-numbers nil
;; Code folding method. Possible values are `evil' and `origami'.
;; (default 'evil)
dotspacemacs-folding-method 'evil
;; If non-nil smartparens-strict-mode will be enabled in programming modes.
;; (default nil)
dotspacemacs-smartparens-strict-mode nil
;; If non-nil pressing the closing parenthesis `)' key in insert mode passes
;; over any automatically added closing parenthesis, bracket, quote, etc…
;; This can be temporary disabled by pressing `C-q' before `)'. (default nil)
dotspacemacs-smart-closing-parenthesis nil
;; Select a scope to highlight delimiters. Possible values are `any',
;; `current', `all' or `nil'. Default is `all' (highlight any scope and
;; emphasis the current one). (default 'all)
dotspacemacs-highlight-delimiters 'all
;; If non nil, advise quit functions to keep server open when quitting.
;; (default nil)
dotspacemacs-persistent-server nil
;; List of search tool executable names. Spacemacs uses the first installed
;; tool of the list. Supported tools are `ag', `pt', `ack' and `grep'.
;; (default '("ag" "pt" "ack" "grep"))
dotspacemacs-search-tools '("ag" "pt" "ack" "grep")
;; The default package repository used if no explicit repository has been
;; specified with an installed package.
;; Not used for now. (default nil)
dotspacemacs-default-package-repository nil
;; Delete whitespace while saving buffer. Possible values are `all'
;; to aggressively delete empty line and long sequences of whitespace,
;; `trailing' to delete only the whitespace at end of lines, `changed'to
;; delete only whitespace for changed lines or `nil' to disable cleanup.
;; (default nil)
dotspacemacs-whitespace-cleanup nil
))
(defun dotspacemacs/user-init ()
"Initialization function for user code.
It is called immediately after `dotspacemacs/init', before layer configuration
executes.
This function is mostly useful for variables that need to be set
before packages are loaded. If you are unsure, you should try in setting them in
`dotspacemacs/user-config' first."
(setq configuration-layer-elpa-archives
'(("melpa-cn" . "http://mirrors.tuna.tsinghua.edu.cn/elpa/melpa/")
("org-cn" . "http://mirrors.tuna.tsinghua.edu.cn/elpa/org/")
("gnu-cn" . "http://mirrors.tuna.tsinghua.edu.cn/elpa/gnu/")))
)
(defun dotspacemacs/user-config ()
"Configuration function for user code.
This function is called at the very end of Spacemacs initialization after
layers configuration.
This is the place where most of your configurations should be done. Unless it is
explicitly specified that a variable should be set before a package is loaded,
you should place your code here."
)
;; Do not write anything past this comment. This is where Emacs will
;; auto-generate custom variable definitions.
(custom-set-variables
;; custom-set-variables was added by Custom.
;; If you edit it by hand, you could mess it up, so be careful.
;; Your init file should contain only one such instance.
;; If there is more than one, they won't work right.
'(org-agenda-files (quote ("~/jianguo_sync/Nutstore/theNext.org")))
'(package-selected-packages
(quote
(yapfify pyvenv pytest pyenv-mode py-isort pip-requirements org-category-capture org-present org-pomodoro alert log4e gntp org-mime org-download live-py-mode lv hy-mode dash-functional htmlize helm-pydoc flycheck-pos-tip pos-tip anaconda-mode gnuplot gitignore-mode gitconfig-mode gitattributes-mode git-timemachine git-messenger git-link flyspell-correct-helm flyspell-correct flycheck magit magit-popup git-commit with-editor cython-mode auto-dictionary pythonic company-lsp lsp-mode ws-butler winum which-key volatile-highlights vi-tilde-fringe uuidgen use-package toc-org spaceline powerline restart-emacs request rainbow-delimiters popwin persp-mode pcre2el paradox spinner org-plus-contrib org-bullets open-junk-file neotree move-text macrostep lorem-ipsum linum-relative link-hint indent-guide hydra hungry-delete hl-todo highlight-parentheses highlight-numbers parent-mode highlight-indentation helm-themes helm-swoop helm-projectile helm-mode-manager helm-make projectile pkg-info epl helm-flx helm-descbinds helm-ag google-translate golden-ratio flx-ido flx fill-column-indicator fancy-battery eyebrowse expand-region exec-path-from-shell evil-visualstar evil-visual-mark-mode evil-unimpaired evil-tutor evil-surround evil-search-highlight-persist highlight evil-numbers evil-nerd-commenter evil-mc evil-matchit evil-lisp-state smartparens evil-indent-plus evil-iedit-state iedit evil-exchange evil-escape evil-ediff evil-args evil-anzu anzu evil goto-chg undo-tree eval-sexp-fu elisp-slime-nav dumb-jump f dash s diminish define-word column-enforce-mode clean-aindent-mode bind-map bind-key auto-highlight-symbol auto-compile packed aggressive-indent adaptive-wrap ace-window ace-link ace-jump-helm-line helm avy helm-core popup async))))
(custom-set-faces
;; custom-set-faces was added by Custom.
;; If you edit it by hand, you could mess it up, so be careful.
;; Your init file should contain only one such instance.
;; If there is more than one, they won't work right.
)
;; 自动根据子项目的完成更改父项目的状态
(defun org-summary-todo (n-done n-not-done)
"Switch entry to DONE when all subentries are done, to TODO otherwise."
(let (org-log-done org-log-states) ; turn off logging
(org-todo (if (= n-not-done 0) "DONE" "TODO"))))
(add-hook 'org-after-todo-statistics-hook 'org-summary-todo)
(defgroup org-gantt nil "Customization of org-gantt."
:group 'org)
(defcustom org-gantt-default-hours-per-day 8
"The default hours in a workday.
Use :hours-per-day to overwrite this value for individual gantt charts."
:type '(integer)
:group 'org-gantt)
(defcustom org-gantt-default-work-free-days '(0 6)
"The default days on which no work is done.
Stored in a list of day-of-week numbers,
starting with sunday = 0, ending with saturday = 6.
Use :work-free-days to overwrite this value for individual gantt charts."
:type '(repeat integer)
:group 'org-gantt)
(defcustom org-gantt-default-weekend-style "{black}"
"The default style for the weekend lines.
Use :weekend-style to overwrite this value for individual gantt charts."
:type '(string)
:group 'org-gantt)
(defcustom org-gantt-default-workday-style "{dashed}"
"The default style for the workday lines.
Use :workday-style to overwrite this value for individual gantt charts."
:type '(string)
:group 'org-gantt)
(defcustom org-gantt-default-title-calendar "year, month=name, day"
"The default style for the title calendar.
Use :title-calendar to overwrite this value for individual gantt charts."
:type '(string)
:group 'org-gantt)
(defcustom org-gantt-default-compressed-title-calendar "year, month"
"The default style for the title calendar, if the chart is compressed.
Use :compressed-title-calendar to overwrite this value for individual gantt charts."
:type '(string)
:group 'org-gantt)
(defcustom org-gantt-default-show-progress nil
"The default for showing a progress.
nil means progress is not shown.
always means progress is always shown (0, if no value exists).
if-exists means progress is only shown if a value exists."
:type '(symbol)
:options '(nil if-exists always)
:group 'org-gantt)
(defcustom org-gantt-default-progress-source 'cookie-clocksum
"The default source of the progress.
Determines how the progress is calculated.
clocksum means use clocksum values only.
cookie means use progress-cookies only
clocksum-cookie means prioritize clocksums,
but use progress cookie, if no clocksum exists.
cookie-clocksum means prioritize cookie,
but use clocksum value, if no progress cookie exists."
:type '(symbol)
:options '(clocksum cookie clocksum-cookie cookie-clocksum))
(defcustom org-gantt-default-incomplete-date-headlines 'inactive
"The default treatment for headlines that have either deadline or schedule
\(also computed\), but not both.
'keep will place the headline normally, with a length of 0.
'inactive will place the headline, but distinguish it via inactive-style.
'ignore will not place the headline onto the chart."
:type '(symbol)
:options '(keep inactive ignore)
:group 'org-gantt)
(defcustom org-gantt-default-no-date-headlines 'inactive
"The default treatment for headlines that have neither deadline nor schedule.
'keep will place the headline at the first day, with a length of 0.
'inactive will place the headline, but distinguish it via
inactive-bar-style and inactive-group-style.
'ignore will not place the headline onto the chart."
:type '(symbol)
:options '(keep inactive ignore)
:group 'org-gantt)
(defcustom org-gantt-default-inactive-bar-style "bar label font=\\color{black!50}"
"The default styles for bars that are considered inactive by incomplete-date-headlines
or no-date-headlines."
:type '(string)
:group 'org-gantt)
(defcustom org-gantt-default-inactive-group-style "group label font=\\color{black!50}"
"The default styles for groups that are considered inactive by incomplete-date-headlines
or no-date-headlines."
:type '(string)
:group 'org-gantt)
(defcustom org-gantt-default-tags-bar-style nil
"An alist that associates tags to styles for bars in the form (tag . style)."
:type '(alist :key-type string :value-type string)
:group 'org-gantt)
(defcustom org-gantt-default-tags-group-style nil
"An alist that associates tags to styles for groups in the form (tag . style)."
:type '(alist :key-type string :value-type string)
:group 'org-gantt)
(defcustom org-gantt-default-tag-style-effect 'subheadlines
"The effect of tag styles.
If value is 'current, a tag style is only applied to headlines
with the appropriate tag.
If value is 'subheadlines, it applies to the headline and
all its subheadlines."
:type '(symbol)
:options '(subheadlines 'current)
:group 'org-gantt)
(defcustom org-gantt-default-use-tags nil
"A list of tags for which the bars/groups should be printed.
All headlines without those tags will not be printed.
nil means print all."
:type '(repeat string)
:group 'org-gantt)
(defcustom org-gantt-default-ignore-tags nil
"A list of tags for which the bars/groups should not be printed.
All headlines with those tags will not be printed.
Can not be (sensibly) used in combination with org-gantt-default-use-tags.
nil means print all."
:type '(repeat string)
:group 'org-gantt)
(defcustom org-gantt-default-milestone-tags '("milestone")
"A list of tags, for which a headline is printed as a milestone."
:type '(repeat string)
:group 'org-gantt)
(defcustom org-gantt-default-linked-to-property-keys '(:LINKED-TO)
"A list of strings that are accepted as property keys for linked elements."
:type '(repeat string)
:group 'org-gantt)
(defcustom org-gantt-default-maxlevel nil
"The default maximum levels used for org-gantt charts.
nil means the complete tree is used."
:type '(choice integer (const nil))
:group 'org-gantt)
(defcustom org-gantt-output-debug-dates nil
"Decides whether to put out some extra information about the computed dates
as a latex comment after each gantt bar."
:type '(boolean)
:group 'org-gantt)
(defcustom org-gantt-default-hgrid nil
"The option :hgrid decides whether hgrid lines are shown.
This is the default setting for :hgrid."
:type '(boolean)
:group 'org-gantt)
(defconst org-gantt-start-prop :startdate
"What is used as the start property in the constructed property list.")
(defconst org-gantt-end-prop :enddate
"What is used as the end property in the constructed property list.")
(defconst org-gantt-effort-prop :effort
"What is used as the effort property in the constructed property list.")
(defconst org-gantt-clocksum-prop :clocksum
"What is used as the effort property in the constructed property list.")
(defconst org-gantt-progress-prop :progress
"What is used as the progress property in the constructed property list.")
(defconst org-gantt-stats-cookie-prop :stats-cookie
"What is used as the statistics cooke, i.e. [X%], [X/Y]")
(defconst org-gantt-tags-prop :tags
"What is used as the tags property in the constructed property list.")
(defconst org-gantt-parent-tags-prop :parent-tags
"What is used as the property for propagated parent tags.")
(defconst org-gantt-id-prop :id
"What is used as the the property for storing ids.")
(defconst org-gantt-blocker-prop :blocker
"What is used as the property for the blocker property.")
(defconst org-gantt-trigger-prop :trigger
"What is used as the property for the trigger property.")
(defconst org-gantt-linked-to-prop :linked-to
"What is used as the property for the linked-to elements")
(defvar org-gant-hours-per-day-gv nil
"Global variable for local hours-per-day.")
(defvar org-gantt-options nil
"Global variable that keeps a plist of the current options.
Is filled with local or default options.")
(defvar *org-gantt-changed-in-propagation* nil
"Global variable for checking if something was changed during propagation.")
(defvar *org-gantt-id-counter* 0
"Global variable for creating ids.")
(defvar *org-gantt-link-hash* nil
"Global variable for storing manually given links.
Is used to create the manual links between elements at the end.")
(defun org-gantt-hours-per-day ()
"Get the hours per day."
org-gantt-hours-per-day-gv)
(defun org-gantt-hours-per-day-time ()
"Get hours per day as a time value."
(seconds-to-time (* 3600 (org-gantt-hours-per-day))))
(defun org-gantt-chomp (str)
"Chomp leading and tailing whitespace from STR."
(replace-regexp-in-string (rx (or (: bos (* (any " \t\n")))
(: (* (any " \t\n")) eos)))
""
str))
(defun org-gantt-gethash (key table &optional dflt)
"Works just as gethash, but works if hashtable is nil.
Look up KEY in TABLE and return its associated value.
If KEY is not found, or TABLE is nil, return DFLT which defaults to nil."
(if table
(gethash key table dflt)
dflt))
(defun org-gantt-hashtable-equal (table1 table2)
"Return true, iff table1 and table2 are hash tables with the same contents."
(and (= (hash-table-count table1)
(hash-table-count table2))
(catch 'flag (maphash (lambda (x y)
(or (org-gantt-equal (gethash x table2) y)
(throw 'flag nil)))
table1)
(throw 'flag t))))
(defun org-gantt-equal (item1 item2)
"Returns true, iff item1 is equal to item2, including hash tables"
(if (and (hash-table-p item1) (hash-table-p item2))
(org-gantt-hashtable-equal item1 item2)
(equal item1 item2)))
(defun org-gantt-info-list-equal (il1 il2)
"Returns true iff IL1 is equal to IL2, including hash tables."
(or (and (not il1) (not il2))
(and (org-gantt-equal (car il1) (car il2))
(org-gantt-info-list-equal (cdr il1) (cdr il2)))))
(defun org-gantt-get-planning-time (element timestamp-type)
"Get the time belonging to a first-order headline of the given ELEMENT.
TIMESTAMP-TYPE is either :scheduled or :deadline.
If it is :deadline, hours-per-day is added to it."
(let* ((timestamp
(org-element-map
element '(planning headline)
(lambda (subelement) (org-element-property timestamp-type subelement))
nil t 'headline))
(time (org-gantt-timestamp-to-time timestamp))
(dt (decode-time time))
(hours (nth 2 dt))
(minutes (nth 1 dt)))
(if (and (equal timestamp-type :deadline)
(= 0 hours)
(= 0 minutes))
(time-add time (org-gantt-hours-per-day-time))
time)))
(defun org-gantt-get-subheadlines (element)
"Get all the headlines of ELEMENT."
(org-element-map element 'headline (lambda (subelement) subelement)
nil nil 'headline))
(defun org-gantt-time-less-p (t1 t2)
"Return non-nil, if T1 is before T2.
I.e. `time-less-p' working with nil.
Any time is less than nil."
(and t1
(or (not t2)
(time-less-p t1 t2))))
(defun org-gantt-time-larger-p (t1 t2)
"Return non-nil, if T1 is later than T2.
Works with nil. Any time is lager than nil."
(and t1
(or (not t2)
(time-less-p t2 t1))))
(defun org-gantt-subheadline-extreme (element comparator time-getter subheadline-getter)
"Return smallest/largest timestamp of the subheadlines of ELEMENT.
Smallest or largest depends on COMPARATOR.
TIME-GETTER is the recursive function that needs to be called if
the subheadlines have no timestamp.
SUBHEADLINE-GETTER is the function that is used to get subheadlines."
(and
element
(let ((subheadlines (funcall subheadline-getter element)))
(funcall
time-getter
(car
(sort
subheadlines
(lambda (hl1 hl2)
(funcall comparator
(funcall time-getter hl1)
(funcall time-getter hl2)))))))))
(defun org-gantt-get-start-time (element)
"Get the start time of ELEMENT.
This is either the :scheduled time, or the first start time of
ELEMENT's subelements."
(or
(org-gantt-get-planning-time element ':scheduled)
(org-gantt-subheadline-extreme
(cdr element)
#'org-gantt-time-less-p
#'org-gantt-get-start-time
#'org-gantt-get-subheadlines)))
(defun org-gantt-get-end-time (element)
"Get the end time of ELEMENT.
This is either the :deadline time, or the last end time of
ELEMENT's subelements."
(or
(org-gantt-get-planning-time element ':deadline)
(org-gantt-subheadline-extreme
(cdr element)
#'org-gantt-time-larger-p
#'org-gantt-get-end-time
#'org-gantt-get-subheadlines)))
(defun org-gantt-subheadlines-effort (element effort-getter element-org-gantt-effort-prop)
"Return the sum of the efforts of the subheadlines of ELEMENT.
EFFORT-GETTER is the recursive function that needs to be called if
the subheadlines have no effort.
ELEMENT-ORG-GANTT-EFFORT-PROP The property that stores the effort in the headline element."
(and
element
(let ((subheadlines (org-gantt-get-subheadlines element))
(time-sum (seconds-to-time 0)))
(dolist (sh subheadlines (if (= 0 (apply '+ time-sum)) nil time-sum))
(let ((subtime (funcall effort-getter sh element-org-gantt-effort-prop)))
(when subtime
(setq time-sum (time-add time-sum subtime))))))))
(defun org-gantt-get-effort (element element-org-gantt-effort-prop &optional use-subheadlines-effort)
"Get the effort of the current ELEMENT.
If use-subheadlines-effort is non-nil and element has no effort,
use sum of the efforts of the subelements.
ELEMENT-ORG-GANTT-EFFORT-PROP is the property that stores the effort
in the headline element.
If USE-SUBHEADLINES-EFFORT is non-nil and element does not have a direct effort,
the combined effort of subheadlines is used."
(let ((effort-time (org-gantt-effort-to-time (org-element-property element-org-gantt-effort-prop element))))
(or effort-time
(and use-subheadlines-effort
(org-gantt-subheadlines-effort (cdr element) #'org-gantt-get-effort element-org-gantt-effort-prop)))))
(defun org-gantt-statistics-value (title)
"Return the statistics value, if title contains it, else nil"
(org-element-map (org-element-contents title) 'statistics-cookie
(lambda (element) (org-element-property :value element))
nil t t))
(defun org-gantt-get-flattened-properties (element property-key-list)
"Return the properties in ELEMENT flattened into one list.
Return properties as defined by any key in PROPERTY-KEY-LIST."
; (dbgmessage "PROP-KEY-LIST %s" property-key-list)
; (dbgmessage "ELEMENT %s" (pp element))
(let ((property-list nil))
(dolist (key property-key-list property-list)
(when (org-element-property key element)
(setq property-list
(append (split-string (org-element-property key element) "," t)
property-list))))))
(defun org-gantt-create-id ()
"Create a unique id."
(setq *org-gantt-id-counter*
(+ 1 *org-gantt-id-counter*))
(concat "uniqueid"
(number-to-string *org-gantt-id-counter*)))
(defun org-gantt-create-gantt-info (element)
"Create a gantt-info for ELEMENT.
A gantt-info is a plist containing :name org-gantt-start-prop org-gantt-end-prop org-gantt-effort-prop :subelements"
; (dbgmessage "TITLEtype: %s" (type-of (cdr (org-element-property :title element))))
; (dbgmessage "TITLE: %s" (car (org-element-contents (org-element-property :title element))))
(let ((gantt-info-hash (make-hash-table)))
(puthash
:name (org-element-property :raw-value element)
gantt-info-hash)
(puthash :ordered (org-element-property :ORDERED element) gantt-info-hash)
(puthash org-gantt-start-prop (org-gantt-get-start-time element) gantt-info-hash)
(puthash org-gantt-end-prop (org-gantt-get-end-time element) gantt-info-hash)
(puthash org-gantt-effort-prop (or (org-gantt-get-effort
element :EFFORT)
(and (org-gantt-is-in-tags
(org-element-property :tags element)
(plist-get org-gantt-options :milestone-tags))
(seconds-to-time 0)))
gantt-info-hash)
(puthash org-gantt-stats-cookie-prop (org-gantt-statistics-value
(org-element-property :title element))
gantt-info-hash)
(puthash org-gantt-clocksum-prop (org-gantt-effort-to-time (org-element-property :CLOCKSUM element) 24) gantt-info-hash) ;clocksum is computed automatically with 24 hours per day, therefore we use 24.
(puthash org-gantt-tags-prop (org-element-property :tags element) gantt-info-hash)
(puthash org-gantt-id-prop (or (org-element-property :ID element)
(org-gantt-create-id))
gantt-info-hash)
(when (org-gantt-get-flattened-properties
element (plist-get org-gantt-options
:linked-to-property-keys))
(dbgmessage "FLATTENED: %s" (org-gantt-get-flattened-properties
element (plist-get org-gantt-options
:linked-to-property-keys))))
(puthash org-gantt-linked-to-prop (org-gantt-get-flattened-properties
element (plist-get org-gantt-options
:linked-to-property-keys))
gantt-info-hash)
(puthash org-gantt-trigger-prop (org-element-property :TRIGGER element) gantt-info-hash)
(puthash org-gantt-blocker-prop (org-element-property :BLOCKER element) gantt-info-hash)
; (org-gantt-get-effort element :CLOCKSUM)
(puthash :subelements (org-gantt-crawl-headlines (cdr element)) gantt-info-hash)
gantt-info-hash))
(defun org-gantt-crawl-headlines (data)
"Crawl the parsed DATA and return a gantt-info-list from the headlines."
(let ((gantt-info-list
(org-element-map data 'headline #'org-gantt-create-gantt-info nil nil 'headline)))
gantt-info-list))
(defun org-gantt-get-extreme-date-il (info-list time-getter time-comparer)
"Get the first or last date in INFO-LIST.
TIME-GETTER is used to get the time in an info object.
TIME-COMPARER is used to compare times, i.e. determine first or last.
Returns the first element of the list `sort'ed according to TIME-COMPARER."
(let ((reslist nil))
(dolist (info info-list)
(setq
reslist
(cons (funcall time-getter info)
(cons
(org-gantt-get-extreme-date-il
(gethash :subelements info) time-getter time-comparer)
reslist))))
(car (sort reslist time-comparer))))
(defun org-gantt-timestamp-to-time (timestamp &optional use-end)
"Convert a TIMESTAMP to an Emacs time.
If optional USE-END is non-nil use the ...-end values of the timestamp."
(and timestamp
(if use-end
(encode-time 0
(or (org-element-property :minute-end timestamp) 0)
(or (org-element-property :hour-end timestamp) 0)
(org-element-property :day-end timestamp)
(org-element-property :month-end timestamp)
(org-element-property :year-end timestamp))
(encode-time 0
(or (org-element-property :minute-start timestamp) 0)
(or (org-element-property :hour-start timestamp) 0)
(org-element-property :day-start timestamp)
(org-element-property :month-start timestamp)
(org-element-property :year-start timestamp)))))
(defun org-gantt-substring-if (string from to)
"Return substring if STRING, FROM and TO are non-nil and from < to, otherwise nil."
(and string from to (< from to) (substring string from to)))
(defun org-gantt-string-to-number (string)
"Return a numberthat is `string-to-number' or 0 if STRING is nil."
(if string (string-to-number string) 0))
(defun org-gantt-strings-to-time
(seconds-string minutes-string &optional hours-string
days-string weeks-string months-string years-string hours-per-day)
"Convert the given strings to time, taking into account HOURS-PER-DAY.
SECONDS-STRING MINUTES-STRING HOURS-STRING
DAYS-STRING WEEKS-STRING MONTHS-STRING and YEARS-STRING are strings
that are converted to numbers. Then the time is calculated from the values."
(let* ((ex-hours (+ (org-gantt-string-to-number seconds-string)
(* 60 (org-gantt-string-to-number minutes-string))
(* 3600 (org-gantt-string-to-number hours-string))))
(calc-days (/ ex-hours (org-gantt-hours-per-day)))
(rest-hours (% ex-hours (org-gantt-hours-per-day)))
(work-free-days (plist-get org-gantt-options :work-free-days))
(time
(seconds-to-time
(+ (org-gantt-string-to-number seconds-string)
(* 60 (org-gantt-string-to-number minutes-string))
(* 3600 (org-gantt-string-to-number hours-string))
(* 3600 (or hours-per-day (org-gantt-hours-per-day)) (org-gantt-string-to-number days-string))
(* 3600 (or hours-per-day (org-gantt-hours-per-day)) (- 7 (length work-free-days)))
(* 3600 (or hours-per-day (org-gantt-hours-per-day)) 30 (org-gantt-string-to-number months-string))
(* 3600 (or hours-per-day (org-gantt-hours-per-day)) 30 12 (org-gantt-string-to-number years-string))))))
(if (= 0 (apply '+ time))
nil
time)))
(defun org-gantt-effort-to-time (effort &optional hours-per-day)
"Parse EFFORT timestring and return it as Emacs time.
The returned time represents a time difference.
Optional HOURS-PER-DAY makes it possible to convert hour estimates into workdays."
(and effort
(let* ((years-string (org-gantt-substring-if effort 0 (string-match "y" effort)))
(msp (if years-string (match-end 0) 0))
(months-string (org-gantt-substring-if effort msp (string-match "m" effort)))
(wsp (if months-string (match-end 0) msp))
(weeks-string (org-gantt-substring-if effort wsp (string-match "w" effort)))
(dsp (if weeks-string (match-end 0) wsp))
(days-string (org-gantt-substring-if effort dsp (string-match "d" effort)))
(hsp (if days-string (match-end 0) dsp))
(hours-string (org-gantt-substring-if effort hsp (string-match ":" effort)))
(minsp (if hours-string (match-end 0) hsp))
(minutes-string (org-gantt-substring-if effort minsp (length effort))))
(org-gantt-strings-to-time "0"
minutes-string hours-string
days-string weeks-string
months-string years-string
hours-per-day))))
(defun org-gantt-is-workday (time)
"Return non-nil, iff TIME is a workday. Currently does not consider holidays."
(let ((dow (string-to-number (format-time-string "%w" time)))
(work-free-days (plist-get org-gantt-options :work-free-days)))
(not (member dow work-free-days))))
(defun org-gantt-change-workdays (time ndays change-function)
"Add or subtract NDAYS workdays to the given TIME.
Add or subtract depends on change-function.
E.g. if time is on Friday, ndays is one, the result will be monday.
FIXME: Does not use holidays."
(cl-assert (>= ndays 0) "trying to add negative days to timestamp.")
(let ((oneday (days-to-time 1))
(curtime time))
(while (/= 0 ndays)
(setq curtime (funcall change-function curtime oneday))
(when (org-gantt-is-workday curtime)
(setq ndays (- ndays 1))))
curtime))
(defun org-gantt-day-end (time)
"Get the end of the given workday TIME."
(let ((dt (decode-time time)))
(encode-time 0 0 (org-gantt-hours-per-day)
(nth 3 dt) (nth 4 dt) (nth 5 dt))))
(defun org-gantt-day-start (time)
"Get the start of the given workday TIME."
(let ((dt (decode-time time)))
(encode-time 0 0 0 (nth 3 dt) (nth 4 dt) (nth 5 dt))))
(defun org-gantt-add-worktime (time change-time)
"Add CHANGE-TIME to TIME, taking into account holidays and hours-per-day."
(let* ((dt (decode-time time))
(day-end (encode-time 0 0 (org-gantt-hours-per-day)
(nth 3 dt) (nth 4 dt) (nth 5 dt)))
(rest-time (time-subtract day-end time))
(one-day (days-to-time 1)))
(if (time-less-p change-time rest-time)
(time-add time change-time)
(let*
((next-day-d (decode-time (org-gantt-change-workdays time 1 #'time-add)))
(next-day (encode-time 0 0 0 (nth 3 next-day-d)
(nth 4 next-day-d) (nth 5 next-day-d)))
(rest-change (time-subtract change-time rest-time))
(dc (decode-time rest-change))
(rest-min (+ (nth 1 dc) (* 60 (nth 2 dc)))))
(while (> rest-min (* 60 (org-gantt-hours-per-day)))
(setq next-day (org-gantt-change-workdays next-day 1 #'time-add))
(setq rest-change (time-subtract rest-change (seconds-to-time (* 3600 (org-gantt-hours-per-day)))))
(setq dc (decode-time rest-change))
(setq rest-min (+ (nth 1 dc) (* 60 (nth 2 dc)))))
(while (time-less-p one-day rest-change)
(setq next-day (org-gantt-change-workdays next-day 1 #'time-add))
(setq rest-change (time-subtract rest-change one-day)))
(time-add next-day rest-change)))))
(defun org-gantt-time-difference (t1 t2)
"Calculate the difference between T1 and T2.
No matter which is larger, the resulting difference is always positive."
(if (time-less-p t1 t2)
(time-subtract t2 t1)
(time-subtract t1 t2)))
(defun org-gantt-change-worktime (time change-time time-changer day-start-getter day-end-getter)
"Add CHANGE-TIME to TIME, taking into account holidays and hours-per-day.
TIME-CHANGER determines wheter time is added or subtracted.
DAY-START-GETTER must return the day start, if TIME-CHANGER adds time,
otherwise the end.
DAY-END-GETTER must return the day end, if TIME-CHANGER adds time,
otherwise the start"
(let* ((day-end (funcall day-end-getter time))
(rest-time (org-gantt-time-difference day-end time))
(one-day (days-to-time 1)))
; (dbgmessage "Change Time: %s" (format-time-string "%Y-%m-%d:%T" change-time))
(if (time-less-p change-time rest-time)
(funcall time-changer time change-time)
(let*
((next-day (funcall day-start-getter (org-gantt-change-workdays time 1 time-changer)))
(rest-change (time-subtract change-time rest-time))
(rest-sec (round (time-to-seconds rest-change))))
(while (> rest-sec (* 3600 (org-gantt-hours-per-day)))
(setq next-day (org-gantt-change-workdays next-day 1 time-changer))
(setq rest-change (time-subtract rest-change (seconds-to-time (* 3600 (org-gantt-hours-per-day)))))
(setq rest-sec (round (time-to-seconds rest-change))))
(while (time-less-p one-day rest-change)
(setq next-day (org-gantt-change-workdays next-day 1 time-changer))
(setq rest-change (time-subtract rest-change one-day)))
(funcall time-changer next-day rest-change)))))
(defun org-gantt-get-next-time (endtime)
"Get the time where the next bar should start.
ENDTIME is the time where the previous bar ends."
(let* ((dt (decode-time endtime))
(hours (nth 3 dt))
(minutes (nth 2 dt)))
(if (and (= (org-gantt-hours-per-day) hours)
(= 0 minutes))
(org-gantt-change-worktime
endtime (encode-time (* 3600 (- 24 (org-gantt-hours-per-day))) 0 0 0 0 0)
#'time-add
#'org-gantt-day-start #'org-gantt-day-end)
endtime)))
(defun org-gantt-get-prev-time (starttime)
"Get the time where the previous bar should end.
STARTTIME is the time where the next bar starts."
(let* ((dt (decode-time starttime))
(hours (nth 3 dt))
(minutes (nth 2 dt)))
(if (and (= (org-gantt-hours-per-day) hours)
(= 0 minutes))
(org-gantt-change-worktime
starttime (seconds-to-time (* 3600 (- 24 (org-gantt-hours-per-day))))
#'time-subtract
#'org-gantt-day-end #'org-gantt-day-start)
starttime)))
(defun org-gantt-propagate-order-timestamps (headline-list &optional is-ordered parent-start parent-end)
"Propagate the times of headlines in HEADLINE-LIST that are ordered.
Recursively apply to subheadlines.
IS-ORDERED whether th(car headline-list) e current subheadlins are ordered.