├── useful-tools ├── borg │ └── config.el ├── snippets │ ├── plantuml-mode │ │ ├── c4_person │ │ ├── c4_system │ │ ├── c4_dynamic_set_index │ │ ├── c4_hide_stereotype │ │ ├── c4_layout_top_down │ │ ├── c4_layout_as_sketch │ │ ├── c4_systemdb │ │ ├── c4_boundary │ │ ├── c4_dynamic_increment │ │ ├── c4_layout_left_right │ │ ├── c4_layout_with_legend │ │ ├── c4_person_ext │ │ ├── c4_system_ext │ │ ├── c4_systemqueue │ │ ├── c4_layout_left │ │ ├── c4_component │ │ ├── c4_container │ │ ├── c4_layout_right │ │ ├── c4_relationship │ │ ├── c4_systemdb_ext │ │ ├── c4_systemqueue_ext │ │ ├── c4_componentdb │ │ ├── c4_containerdb │ │ ├── c4_person_descr │ │ ├── c4_system_descr │ │ ├── c4_component_ext │ │ ├── c4_componentqueue │ │ ├── c4_container_ext │ │ ├── c4_containerqueue │ │ ├── c4_deployment_node │ │ ├── c4_system_boundary │ │ ├── c4_boundary_type │ │ ├── c4_relationship_bi │ │ ├── c4_container_boundary │ │ ├── c4_systemdb_descr │ │ ├── c4_componentdb_ext │ │ ├── c4_containerdb_ext │ │ ├── c4_enterprise_boundary │ │ ├── c4_componentqueue_ext │ │ ├── c4_containerqueue_ext │ │ ├── c4_person_ext_descr │ │ ├── c4_system_ext_descr │ │ ├── c4_systemqueue_descr │ │ ├── c4_relationship_index │ │ ├── c4_component_descr │ │ ├── c4_container_descr │ │ ├── c4_deployment_node_type │ │ ├── c4_relationship_techn │ │ ├── c4_systemdb_ext_descr │ │ ├── c4_systemqueue_ext_descr │ │ ├── c4_componentdb_descr │ │ ├── c4_containerdb_descr │ │ ├── c4_include_context │ │ ├── c4_include_dynamic │ │ ├── c4_component_ext_descr │ │ ├── c4_componentqueue_descr │ │ ├── c4_container_ext_descr │ │ ├── c4_containerqueue_descr │ │ ├── c4_relationship_bi_techn │ │ ├── c4_include_component │ │ ├── c4_include_container │ │ ├── c4_include_deployment │ │ ├── c4_componentdb_ext_descr │ │ ├── c4_containerdb_ext_descr │ │ ├── c4_componentqueue_ext_descr │ │ ├── c4_containerqueue_ext_descr │ │ └── c4_relationship_index_techn │ ├── org-mode │ │ ├── org_mermaid │ │ ├── org_d2 │ │ ├── org_plantuml │ │ └── org_dot │ └── fundamental-mode │ │ └── asciibox ├── elfeed.org ├── banner.txt ├── update_submodule.sh └── old-elisps │ └── org-roam-config.org ├── .gitignore ├── Makefile ├── init-minimal.el ├── .gitmodules ├── README.org └── init.org /useful-tools/borg/config.el: -------------------------------------------------------------------------------- 1 | (when (native-comp-available-p) 2 | (setq borg-compile-function #'native-compile)) 3 | -------------------------------------------------------------------------------- /useful-tools/snippets/plantuml-mode/c4_person: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: C4_Person 3 | # key: Person 4 | # -- 5 | Person(${1:alias}, "${2:label}") 6 | -------------------------------------------------------------------------------- /useful-tools/snippets/plantuml-mode/c4_system: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: C4_System 3 | # key: System 4 | # -- 5 | System(${1:alias}, "${2:label}") 6 | -------------------------------------------------------------------------------- /useful-tools/snippets/plantuml-mode/c4_dynamic_set_index: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: C4_Dynamic_Set_Index 3 | # key: Set index 4 | # -- 5 | setIndex(${1:value}) 6 | -------------------------------------------------------------------------------- /useful-tools/snippets/plantuml-mode/c4_hide_stereotype: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: C4_Hide_Stereotype 3 | # key: Hide stereotype 4 | # -- 5 | HIDE_STEREOTYPE() 6 | -------------------------------------------------------------------------------- /useful-tools/snippets/plantuml-mode/c4_layout_top_down: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: C4_Layout_Top_Down 3 | # key: Layout top down 4 | # -- 5 | LAYOUT_TOP_DOWN() 6 | -------------------------------------------------------------------------------- /useful-tools/snippets/plantuml-mode/c4_layout_as_sketch: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: C4_Layout_As_Sketch 3 | # key: Layout as sketch 4 | # -- 5 | LAYOUT_AS_SKETCH() 6 | -------------------------------------------------------------------------------- /useful-tools/snippets/plantuml-mode/c4_systemdb: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: C4_SystemDb 3 | # key: Database System 4 | # -- 5 | SystemDb(${1:alias}, "${2:label}") 6 | -------------------------------------------------------------------------------- /useful-tools/snippets/plantuml-mode/c4_boundary: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: C4_Boundary 3 | # key: Boundary 4 | # -- 5 | Boundary(${1:alias}, "${2:label}"){ 6 | $0 7 | } 8 | -------------------------------------------------------------------------------- /useful-tools/snippets/plantuml-mode/c4_dynamic_increment: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: C4_Dynamic_Increment 3 | # key: Increment index 4 | # -- 5 | increment(${1:count}) 6 | -------------------------------------------------------------------------------- /useful-tools/snippets/plantuml-mode/c4_layout_left_right: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: C4_Layout_Left_Right 3 | # key: Layout left to right 4 | # -- 5 | LAYOUT_LEFT_RIGHT() 6 | -------------------------------------------------------------------------------- /useful-tools/snippets/plantuml-mode/c4_layout_with_legend: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: C4_Layout_With_Legend 3 | # key: Layout with legend 4 | # -- 5 | LAYOUT_WITH_LEGEND() 6 | -------------------------------------------------------------------------------- /useful-tools/snippets/plantuml-mode/c4_person_ext: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: C4_Person_Ext 3 | # key: External Person 4 | # -- 5 | Person_Ext(${1:alias}, "${2:label}") 6 | -------------------------------------------------------------------------------- /useful-tools/snippets/plantuml-mode/c4_system_ext: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: C4_System_Ext 3 | # key: External System 4 | # -- 5 | System_Ext(${1:alias}, "${2:label}") 6 | -------------------------------------------------------------------------------- /useful-tools/snippets/plantuml-mode/c4_systemqueue: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: C4_SystemQueue 3 | # key: Queue System 4 | # -- 5 | SystemQueue(${1:alias}, "${2:label}") 6 | -------------------------------------------------------------------------------- /useful-tools/snippets/plantuml-mode/c4_layout_left: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: C4_Layout_Left 3 | # key: Layout to Left side 4 | # -- 5 | Lay_L(${1:from_alias}, ${2:to_alias}) 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /* 2 | !.gitignore 3 | !.gitmodules 4 | !Makefile 5 | !init.org 6 | !README.org 7 | !useful-tools/ 8 | !lib/ 9 | !modules/ 10 | init-config.el 11 | !init-minimal.el 12 | -------------------------------------------------------------------------------- /useful-tools/snippets/plantuml-mode/c4_component: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: C4_Component 3 | # key: Component 4 | # -- 5 | Component(${1:alias}, "${2:label}", "${3:technology}") 6 | -------------------------------------------------------------------------------- /useful-tools/snippets/plantuml-mode/c4_container: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: C4_Container 3 | # key: Container 4 | # -- 5 | Container(${1:alias}, "${2:label}", "${3:technology}") 6 | -------------------------------------------------------------------------------- /useful-tools/snippets/plantuml-mode/c4_layout_right: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: C4_Layout_Right 3 | # key: Layout to Right side 4 | # -- 5 | Lay_R(${1:from_alias}, ${2:to_alias}) 6 | -------------------------------------------------------------------------------- /useful-tools/snippets/plantuml-mode/c4_relationship: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: C4_Relationship 3 | # key: Relationship 4 | # -- 5 | Rel(${1:from_alias}, ${2:to_alias}, "${3:label}") 6 | -------------------------------------------------------------------------------- /useful-tools/snippets/plantuml-mode/c4_systemdb_ext: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: C4_SystemDb_Ext 3 | # key: External Database System 4 | # -- 5 | SystemDb_Ext(${1:alias}, "${2:label}") 6 | -------------------------------------------------------------------------------- /useful-tools/snippets/plantuml-mode/c4_systemqueue_ext: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: C4_SystemQueue_Ext 3 | # key: External Queue System 4 | # -- 5 | SystemQueue_Ext(${1:alias}, "${2:label}") 6 | -------------------------------------------------------------------------------- /useful-tools/snippets/plantuml-mode/c4_componentdb: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: C4_ComponentDb 3 | # key: Database Component 4 | # -- 5 | ComponentDb(${1:alias}, "${2:label}", "${3:technology}") 6 | -------------------------------------------------------------------------------- /useful-tools/snippets/plantuml-mode/c4_containerdb: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: C4_ContainerDb 3 | # key: Database Container 4 | # -- 5 | ContainerDb(${1:alias}, "${2:label}", "${3:technology}") 6 | -------------------------------------------------------------------------------- /useful-tools/snippets/plantuml-mode/c4_person_descr: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: C4_Person_Descr 3 | # key: Person with Description 4 | # -- 5 | Person(${1:alias}, "${2:label}", "${3:description}") 6 | -------------------------------------------------------------------------------- /useful-tools/snippets/plantuml-mode/c4_system_descr: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: C4_System_Descr 3 | # key: System with Description 4 | # -- 5 | System(${1:alias}, "${2:label}", "${3:description}") 6 | -------------------------------------------------------------------------------- /useful-tools/snippets/plantuml-mode/c4_component_ext: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: C4_Component_Ext 3 | # key: External Component 4 | # -- 5 | Component_Ext(${1:alias}, "${2:label}", "${3:technology}") 6 | -------------------------------------------------------------------------------- /useful-tools/snippets/plantuml-mode/c4_componentqueue: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: C4_ComponentQueue 3 | # key: Queue Component 4 | # -- 5 | ComponentQueue(${1:alias}, "${2:label}", "${3:technology}") 6 | -------------------------------------------------------------------------------- /useful-tools/snippets/plantuml-mode/c4_container_ext: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: C4_Container_Ext 3 | # key: External Container 4 | # -- 5 | Container_Ext(${1:alias}, "${2:label}", "${3:technology}") 6 | -------------------------------------------------------------------------------- /useful-tools/snippets/plantuml-mode/c4_containerqueue: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: C4_ContainerQueue 3 | # key: Queue Container 4 | # -- 5 | ContainerQueue(${1:alias}, "${2:label}", "${3:technology}") 6 | -------------------------------------------------------------------------------- /useful-tools/snippets/plantuml-mode/c4_deployment_node: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: C4_Deployment_Node 3 | # key: Deployment Node 4 | # -- 5 | Deployment_Node(${1:alias}, "${2:label}"){ 6 | $0 7 | } 8 | -------------------------------------------------------------------------------- /useful-tools/snippets/plantuml-mode/c4_system_boundary: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: C4_System_Boundary 3 | # key: System Boundary 4 | # -- 5 | System_Boundary(${1:alias}, "${2:label}"){ 6 | $0 7 | } 8 | -------------------------------------------------------------------------------- /useful-tools/snippets/org-mode/org_mermaid: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: org_mermaid 3 | # key: org_mermaid 4 | # -- 5 | #+BEGIN_SRC mermaid :file /tmp/`(format-time-string "%Y%m%d%H%M%S")`.png 6 | #+END_SRC 7 | -------------------------------------------------------------------------------- /useful-tools/snippets/plantuml-mode/c4_boundary_type: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: C4_Boundary_Type 3 | # key: Boundary with type 4 | # -- 5 | Boundary(${1:alias}, "${2:label}", "${3:type}"){ 6 | $0 7 | } 8 | -------------------------------------------------------------------------------- /useful-tools/snippets/plantuml-mode/c4_relationship_bi: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: C4_Relationship_Bi 3 | # key: Bidirectional Relationship 4 | # -- 5 | BiRel(${1:from_alias}, ${2:to_alias}, "${3:label}") 6 | -------------------------------------------------------------------------------- /useful-tools/snippets/plantuml-mode/c4_container_boundary: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: C4_Container_Boundary 3 | # key: Container Boundary 4 | # -- 5 | Container_Boundary(${1:alias}, "${2:label}"){ 6 | $0 7 | } 8 | -------------------------------------------------------------------------------- /useful-tools/snippets/plantuml-mode/c4_systemdb_descr: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: C4_SystemDb_Descr 3 | # key: Database System with Description 4 | # -- 5 | SystemDb(${1:alias}, "${2:label}", "${3:description}") 6 | -------------------------------------------------------------------------------- /useful-tools/snippets/plantuml-mode/c4_componentdb_ext: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: C4_ComponentDb_Ext 3 | # key: External Database Component 4 | # -- 5 | ComponentDb_Ext(${1:alias}, "${2:label}", "${3:technology}") 6 | -------------------------------------------------------------------------------- /useful-tools/snippets/plantuml-mode/c4_containerdb_ext: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: C4_ContainerDb_Ext 3 | # key: External Database Container 4 | # -- 5 | ContainerDb_Ext(${1:alias}, "${2:label}", "${3:technology}") 6 | -------------------------------------------------------------------------------- /useful-tools/snippets/plantuml-mode/c4_enterprise_boundary: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: C4_Enterprise_Boundary 3 | # key: Enterprise Boundary 4 | # -- 5 | Enterprise_Boundary(${1:alias}, "${2:label}"){ 6 | $0 7 | } 8 | -------------------------------------------------------------------------------- /useful-tools/snippets/plantuml-mode/c4_componentqueue_ext: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: C4_ComponentQueue_Ext 3 | # key: External Queue Component 4 | # -- 5 | ComponentQueue_Ext(${1:alias}, "${2:label}", "${3:technology}") 6 | -------------------------------------------------------------------------------- /useful-tools/snippets/plantuml-mode/c4_containerqueue_ext: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: C4_ContainerQueue_Ext 3 | # key: External Queue Container 4 | # -- 5 | ContainerQueue_Ext(${1:alias}, "${2:label}", "${3:technology}") 6 | -------------------------------------------------------------------------------- /useful-tools/snippets/plantuml-mode/c4_person_ext_descr: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: C4_Person_Ext_Descr 3 | # key: External Person with Description 4 | # -- 5 | Person_Ext(${1:alias}, "${2:label}", "${3:description}") 6 | -------------------------------------------------------------------------------- /useful-tools/snippets/plantuml-mode/c4_system_ext_descr: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: C4_System_Ext_Descr 3 | # key: External System with Description 4 | # -- 5 | System_Ext(${1:alias}, "${2:label}", "${3:description}") 6 | -------------------------------------------------------------------------------- /useful-tools/snippets/plantuml-mode/c4_systemqueue_descr: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: C4_SystemQueue_Descr 3 | # key: Queue System with Description 4 | # -- 5 | SystemQueue(${1:alias}, "${2:label}", "${3:description}") 6 | -------------------------------------------------------------------------------- /useful-tools/snippets/org-mode/org_d2: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: org_d2 3 | # key: org_d2 4 | # -- 5 | #+begin_src d2 :file /tmp/`(format-time-string "%Y%m%d%H%M%S")`.svg :flags -l elk -t 101 -s 6 | $1 7 | #+end_src 8 | $0 9 | -------------------------------------------------------------------------------- /useful-tools/snippets/plantuml-mode/c4_relationship_index: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: C4_Relationship_Index 3 | # key: Relationship with Index 4 | # -- 5 | RelIndex(${1:index}, ${2:from_alias}, ${3:to_alias}, "${4:label}") 6 | -------------------------------------------------------------------------------- /useful-tools/snippets/plantuml-mode/c4_component_descr: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: C4_Component_Descr 3 | # key: Component with Description 4 | # -- 5 | Component(${1:alias}, "${2:label}", "${3:technology}", "${4:description}") 6 | -------------------------------------------------------------------------------- /useful-tools/snippets/plantuml-mode/c4_container_descr: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: C4_Container_Descr 3 | # key: Container with Description 4 | # -- 5 | Container(${1:alias}, "${2:label}", "${3:technology}", "${4:description}") 6 | -------------------------------------------------------------------------------- /useful-tools/snippets/plantuml-mode/c4_deployment_node_type: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: C4_Deployment_Node_Type 3 | # key: Deployment Node with type 4 | # -- 5 | Deployment_Node(${1:alias}, "${2:label}", "${3:type}"){ 6 | $0 7 | } 8 | -------------------------------------------------------------------------------- /useful-tools/snippets/plantuml-mode/c4_relationship_techn: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: C4_Relationship_Techn 3 | # key: Relationship with Technology 4 | # -- 5 | Rel(${1:from_alias}, ${2:to_alias}, "${3:label}", "${4:technology}") 6 | -------------------------------------------------------------------------------- /useful-tools/snippets/plantuml-mode/c4_systemdb_ext_descr: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: C4_SystemDb_Ext_Descr 3 | # key: External Database System with Description 4 | # -- 5 | SystemDb_Ext(${1:alias}, "${2:label}", "${3:description}") 6 | -------------------------------------------------------------------------------- /useful-tools/snippets/plantuml-mode/c4_systemqueue_ext_descr: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: C4_SystemQueue_Ext_Descr 3 | # key: External Queue System with Description 4 | # -- 5 | SystemQueue_Ext(${1:alias}, "${2:label}", "${3:description}") 6 | -------------------------------------------------------------------------------- /useful-tools/snippets/plantuml-mode/c4_componentdb_descr: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: C4_ComponentDb_Descr 3 | # key: Database Component with Description 4 | # -- 5 | ComponentDb(${1:alias}, "${2:label}", "${3:technology}", "${4:description}") 6 | -------------------------------------------------------------------------------- /useful-tools/snippets/plantuml-mode/c4_containerdb_descr: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: C4_ContainerDb_Descr 3 | # key: Database Container with Description 4 | # -- 5 | ContainerDb(${1:alias}, "${2:label}", "${3:technology}", "${4:description}") 6 | -------------------------------------------------------------------------------- /useful-tools/snippets/plantuml-mode/c4_include_context: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: C4_Include_Context 3 | # key: Include C4 Context Diagram 4 | # -- 5 | !include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Context.puml 6 | -------------------------------------------------------------------------------- /useful-tools/snippets/plantuml-mode/c4_include_dynamic: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: C4_Include_Dynamic 3 | # key: Include C4 Dynamic Diagram 4 | # -- 5 | !include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Dynamic.puml 6 | -------------------------------------------------------------------------------- /useful-tools/snippets/org-mode/org_plantuml: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: org_plantuml 3 | # key: org_uml 4 | # -- 5 | #+begin_src plantuml :file /tmp/`(format-time-string "%Y%m%d%H%M%S")`.jpg :cmdline -charset UTF-8 6 | title ${1} 7 | #+end_src 8 | $0 9 | -------------------------------------------------------------------------------- /useful-tools/snippets/plantuml-mode/c4_component_ext_descr: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: C4_Component_Ext_Descr 3 | # key: External Component with Description 4 | # -- 5 | Component_Ext(${1:alias}, "${2:label}", "${3:technology}", "${4:description}") 6 | -------------------------------------------------------------------------------- /useful-tools/snippets/plantuml-mode/c4_componentqueue_descr: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: C4_ComponentQueue_Descr 3 | # key: Queue Component with Description 4 | # -- 5 | ComponentQueue(${1:alias}, "${2:label}", "${3:technology}", "${4:description}") 6 | -------------------------------------------------------------------------------- /useful-tools/snippets/plantuml-mode/c4_container_ext_descr: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: C4_Container_Ext_Descr 3 | # key: External Container with Description 4 | # -- 5 | Container_Ext(${1:alias}, "${2:label}", "${3:technology}", "${4:description}") 6 | -------------------------------------------------------------------------------- /useful-tools/snippets/plantuml-mode/c4_containerqueue_descr: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: C4_ContainerQueue_Descr 3 | # key: Queue Container with Description 4 | # -- 5 | ContainerQueue(${1:alias}, "${2:label}", "${3:technology}", "${4:description}") 6 | -------------------------------------------------------------------------------- /useful-tools/snippets/plantuml-mode/c4_relationship_bi_techn: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: C4_Relationship_Bi_Techn 3 | # key: Bidirectional Relationship with Technology 4 | # -- 5 | BiRel(${1:from_alias}, ${2:to_alias}, "${3:label}", "${4:technology}") 6 | -------------------------------------------------------------------------------- /useful-tools/snippets/plantuml-mode/c4_include_component: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: C4_Include_Component 3 | # key: Include C4 Component Diagram 4 | # -- 5 | !include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Component.puml 6 | -------------------------------------------------------------------------------- /useful-tools/snippets/plantuml-mode/c4_include_container: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: C4_Include_Container 3 | # key: Include C4 Container Diagram 4 | # -- 5 | !include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Container.puml 6 | -------------------------------------------------------------------------------- /useful-tools/snippets/plantuml-mode/c4_include_deployment: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: C4_Include_Deployment 3 | # key: Include C4 Deployment Diagram 4 | # -- 5 | !include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Deployment.puml 6 | -------------------------------------------------------------------------------- /useful-tools/snippets/plantuml-mode/c4_componentdb_ext_descr: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: C4_ComponentDb_Ext_Descr 3 | # key: External Database Component with Description 4 | # -- 5 | ComponentDb_Ext(${1:alias}, "${2:label}", "${3:technology}", "${4:description}") 6 | -------------------------------------------------------------------------------- /useful-tools/snippets/plantuml-mode/c4_containerdb_ext_descr: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: C4_ContainerDb_Ext_Descr 3 | # key: External Database Container with Description 4 | # -- 5 | ContainerDb_Ext(${1:alias}, "${2:label}", "${3:technology}", "${4:description}") 6 | -------------------------------------------------------------------------------- /useful-tools/snippets/plantuml-mode/c4_componentqueue_ext_descr: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: C4_ComponentQueue_Ext_Descr 3 | # key: External Queue Component with Description 4 | # -- 5 | ComponentQueue_Ext(${1:alias}, "${2:label}", "${3:technology}", "${4:description}") 6 | -------------------------------------------------------------------------------- /useful-tools/snippets/plantuml-mode/c4_containerqueue_ext_descr: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: C4_ContainerQueue_Ext_Descr 3 | # key: External Queue Container with Description 4 | # -- 5 | ContainerQueue_Ext(${1:alias}, "${2:label}", "${3:technology}", "${4:description}") 6 | -------------------------------------------------------------------------------- /useful-tools/snippets/plantuml-mode/c4_relationship_index_techn: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: C4_Relationship_Index_Techn 3 | # key: Relationship with Technology and Index 4 | # -- 5 | RelIndex(${1:index}, ${2:from_alias}, ${3:to_alias}, "${4:label}", "${5:technology}") 6 | -------------------------------------------------------------------------------- /useful-tools/snippets/fundamental-mode/asciibox: -------------------------------------------------------------------------------- 1 | # -*- mode: fundamental -*- 2 | # name: asciibox 3 | # key: asciibox 4 | # -- 5 | 6 | ${1:$(concat comment-start " ┌─" (make-string (string-width yas-text) ?─) "─┐")} 7 | `comment-start` │ ${1:Title} │ 8 | ${1:$(concat comment-start " └─" (make-string (string-width yas-text) ?─) "─┘")} 9 | $0 10 | -------------------------------------------------------------------------------- /useful-tools/snippets/org-mode/org_dot: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: org_dot 3 | # key: org_dot 4 | # -- 5 | 6 | #+begin_src dot :file /tmp/`(format-time-string "%Y%m%d%H%M%S")`.png 7 | digraph { 8 | rankdir=LR 9 | node [ 10 | shape=record 11 | style=filled 12 | fillcolor="#E3EFFE" 13 | color="#7EA8F6" 14 | fontsize=12 15 | ]; 16 | edge [ 17 | color="#B3C3F3" 18 | arrowsize=0.8 19 | penwidth=2 20 | fontsize=11 21 | ]; 22 | subgraph cluster_a { 23 | } 24 | $1 25 | } 26 | #+end_src 27 | $0 28 | -------------------------------------------------------------------------------- /useful-tools/elfeed.org: -------------------------------------------------------------------------------- 1 | * feeds :elfeed: 2 | ** emacs :emacs: 3 | *** https://sachachua.com/blog/feed/ 4 | *** https://karthinks.com/index.xml 5 | *** https://protesilaos.com/codelog.xml 6 | *** https://sachachua.com/blog/feed/ 7 | *** https://manateelazycat.github.io/feed.xml :life: 8 | ** Guix :guix: 9 | *** https://guix.gnu.org/feeds/blog.atom 10 | ** org mode 11 | *** https://ogbe.net/blog.xml 12 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | DRONES_DIR = $(shell git config "borg.drones-directory" || echo "lib") 2 | 3 | -include $(DRONES_DIR)/borg/borg.mk 4 | 5 | bootstrap-borg: 6 | @git submodule--helper clone --name borg --path $(DRONES_DIR)/borg \ 7 | --url https://github.com/emacscollective/borg.git 8 | @cd $(DRONES_DIR)/borg; git symbolic-ref HEAD refs/heads/main 9 | @cd $(DRONES_DIR)/borg; git reset --hard HEAD 10 | init-org: init-build 11 | @rm init.elc 12 | init-clean: init-tangle 13 | # 更新到 remote 最新 commit 14 | update: 15 | ./useful-tools/update_submodule.sh 16 | # 初始化下载,更新到 .gitmodules 中指定的 commit 17 | init: 18 | @git submodule update --init --jobs 32 19 | @git submodule foreach git reset --hard 20 | # 修改 .gitmodules 后 21 | sync: 22 | git submodule sync 23 | native-all: $(foreach package,$(notdir $(wildcard lib/*)), native/$(package)) 24 | build-all: $(foreach package,$(notdir $(wildcard lib/*)), build/$(package)) 25 | -------------------------------------------------------------------------------- /useful-tools/banner.txt: -------------------------------------------------------------------------------- 1 | 2 | _____ _____ ____ _______ _______ ____________ _____ 3 | |\ \ \ \ ____\_ \__ / /| |\ \ / \ _____\ \ 4 | \\ \ | | / / \ / / | | \ \ |\___/\ \\___/| / / \ | 5 | \\ \ | | / /\ || / |___| \ | \|____\ \___|/ | | /___/| 6 | \| \ | | | | | || | | | | | | | ____\ \ | || 7 | | \| | | | | || \ \ / / | __ / / __ / /\ \|___|/ 8 | / /\ \ | | / /|| |\\/ \//| | / \/ /_/ || |/ \ \ 9 | /_____/ /______/||\ \_____/ ||\_____\|\_____/|/_____/||____________/||\____\ /____/| 10 | | | | | || \_____\ | / | | | | | | | || | /| | || | | 11 | |______|/|_____|/ \ | |___|/ \|_____|\|___|/|_____|/ |___________|/ \|___||____|/ 12 | \|____| 13 | -------------------------------------------------------------------------------- /useful-tools/update_submodule.sh: -------------------------------------------------------------------------------- 1 | log_dir=/tmp/git_update_logs 2 | rm -rf $log_dir 3 | mkdir -p $log_dir 4 | 5 | function pull() { 6 | submodule_path="$1" 7 | log_file="$log_dir/$(basename "$submodule_path").log" 8 | ( 9 | cd "$submodule_path" 10 | PN=$(basename $(pwd)) 11 | label="package: $PN" 12 | box_pad=2 # spaces on both sides 13 | box_inner_len=$((${#label} + box_pad * 2)) 14 | top_box="┌$(printf '─%.0s' $(seq 1 $box_inner_len))┐" 15 | mid_box="│$(printf ' %.0s' $(seq 1 $box_pad))${label}$(printf ' %.0s' $(seq 1 $box_pad))│" 16 | bottom_box="└$(printf '─%.0s' $(seq 1 $box_inner_len))┘" 17 | echo -e "\033[1;36m$top_box\033[0m" >>"$log_file" 18 | echo -e "\033[1;36m$mid_box\033[0m" >>"$log_file" 19 | echo -e "\033[1;36m$bottom_box\033[0m" >>"$log_file" 20 | last_commit=$(git rev-parse HEAD) 21 | # checkout then reset, output appended 22 | git checkout main >/dev/null 2>&1 || git checkout master >/dev/null 2>&1 23 | # git reset --hard >>"$log_file" 2>&1 24 | pull_output=$(git -c color.ui=always pull --rebase 2>&1) 25 | new_commit=$(git rev-parse HEAD) 26 | if [[ "$pull_output" != "Already up to date." ]]; then 27 | echo -e "$pull_output" >>"$log_file" 28 | fi 29 | # Only show log if HEAD moved 30 | # if [[ "$last_commit" != "$new_commit" ]]; then 31 | git log $last_commit...$new_commit --no-merges --color --graph --date=format:'%Y-%m-%d %H:%M:%S' --pretty=format:'%C(red)%h%Creset -%C(green)(%cd) %C(yellow)%d%C(blue) %Creset%s %C(bold blue)<%an>%Creset' --abbrev-commit >>"$log_file" 32 | # fi 33 | echo $'\n' >>"$log_file" 34 | ) 35 | } 36 | 37 | export -f pull 38 | 39 | submodule_paths=$(find lib -mindepth 1 -maxdepth 1 -type d) 40 | 41 | for path in $submodule_paths; do 42 | pull "$path" & 43 | done 44 | 45 | wait 46 | 47 | cat $log_dir/*.log 48 | -------------------------------------------------------------------------------- /init-minimal.el: -------------------------------------------------------------------------------- 1 | ;; -*- lexical-binding: t; -*- 2 | (setq package-enable-at-startup nil) 3 | 4 | ;; Inhibit resizing frame 5 | (setq frame-inhibit-implied-resize t) 6 | 7 | ;; no title bar 8 | ;; (add-to-list 'default-frame-alist '(undecorated . t)) 9 | ;; Faster to disable these here (before they've been initialized) 10 | (push '(alpha-background . 85) default-frame-alist) 11 | (push '(menu-bar-lines . 0) default-frame-alist) 12 | (push '(tool-bar-lines . 0) default-frame-alist) 13 | (push '(vertical-scroll-bars) default-frame-alist) 14 | ;; (push '(undecorated . t) default-frame-alist) 15 | (setq initial-major-mode 'fundamental-mode ;; 默认用最简单的模式 16 | package--init-file-ensured t 17 | inhibit-startup-message t ; 关闭启动 Emacs 时的欢迎界面 18 | ) 19 | 20 | (fido-vertical-mode) 21 | (setq use-short-answers t) 22 | (setq confirm-kill-emacs 'y-or-n-p) 23 | (setq package-enable-at-startup nil) 24 | (set-default-coding-systems 'utf-8) 25 | (setq make-backup-files nil) 26 | (setq auto-save-default nil) 27 | 28 | (defun new-eshell(name) 29 | "create a new eshell with a given name" 30 | (interactive "sInput a name:") 31 | (let ((eshell-buffer-name name)) 32 | (eshell))) 33 | (load-theme 'modus-vivendi t) 34 | (global-set-key [remap list-buffers] #'ibuffer) 35 | 36 | (add-to-list 'load-path (expand-file-name "lib/meow" user-emacs-directory)) 37 | (require 'meow) 38 | (setq meow-use-keypad-when-execute-kbd nil 39 | meow-expand-exclude-mode-list nil 40 | meow-use-clipboard t 41 | ;; meow-cursor-type-normal 'box 42 | ;; meow-cursor-type-insert '(bar . 1) 43 | meow-replace-state-name-list '((normal . "N") 44 | (motion . "M") 45 | (keypad . "K") 46 | (insert . "I") 47 | (beacon . "B")) 48 | meow-use-enhanced-selection-effect t 49 | meow-cheatsheet-layout meow-cheatsheet-layout-qwerty 50 | meow-keypad-start-keys '((?c . ?c) 51 | (?x . ?x)) 52 | meow-char-thing-table '((?\( . round) 53 | (?\) . round) 54 | (?\[ . square) 55 | (?\] . square) 56 | (?\{ . curly) 57 | (?\} . curly) 58 | (?\" . string) 59 | (?w . symbol) 60 | ;; (?w . window) 61 | (?b . buffer) 62 | (?p . paragraph) 63 | (?l . line) 64 | (?d . defun) 65 | (?s . sentence)) 66 | ) 67 | ;; motion keys 68 | (meow-motion-define-key '("j" . meow-next) 69 | '("J" . meow-next-expand) 70 | '("k" . meow-prev) 71 | '("K" . meow-prev-expand) 72 | '("h" . meow-left) 73 | '("H" . meow-left-expand) 74 | '("l" . meow-right) 75 | '("L" . meow-right-expand) 76 | '("v i" . meow-inner-of-thing) 77 | '("v a" . meow-bounds-of-thing) 78 | '("y" . meow-save) 79 | '("" . ignore) 80 | '("." . repeat) 81 | '("!" . kmacro-start-macro-or-insert-counter) 82 | '("@" . meow-end-or-call-kmacro) 83 | ) 84 | 85 | ;; normal keys 86 | (setq wrap-keymap 87 | (let ((map (make-keymap))) 88 | (suppress-keymap map) 89 | (dolist (k '("(" "[" "{" "<" "\"" "*")) 90 | (define-key map k #'insert-pair)) 91 | map 92 | )) 93 | 94 | (meow-normal-define-key '("0" . meow-expand-0) 95 | '("9" . meow-expand-9) 96 | '("8" . meow-expand-8) 97 | '("7" . meow-expand-7) 98 | '("6" . meow-expand-6) 99 | '("5" . meow-expand-5) 100 | '("4" . meow-expand-4) 101 | '("3" . meow-expand-3) 102 | '("2" . meow-expand-2) 103 | '("1" . meow-expand-1) 104 | 105 | '("a" . meow-vim-append) 106 | ;; '("A" . meow-append-vim) 107 | '("b" . meow-back-word) 108 | '("B" . meow-back-symbol) 109 | '("c c" . meow-change) 110 | '("d" . meow-kill) 111 | '("e" . meow-next-word) 112 | '("E" . meow-next-symbol) 113 | '("f" . meow-find) 114 | '("g" . g-extra-commands) 115 | '("G" . meow-grab) 116 | '("h" . meow-left) 117 | '("H" . meow-left-expand) 118 | '("i" . meow-insert) 119 | ;; '("I" . meow-insert-vim) 120 | '("j" . meow-next) 121 | '("J" . meow-next-expand) 122 | '("k" . meow-prev) 123 | '("K" . meow-prev-expand) 124 | '("l" . meow-right) 125 | '("L" . meow-right-expand) 126 | '("m" . consult-register-store) 127 | '("M" . meow-block) 128 | '("n" . meow-search) 129 | '("N" . meow-pop-selection);; 130 | 131 | '("o" . meow-open-below) 132 | '("O" . meow-open-above) 133 | '("p" . meow-yank) 134 | '("P" . meow-yank-pop);; 135 | '("q" . meow-quit) 136 | '("Q" . consult-goto-line) 137 | '("r" . meow-replace) 138 | '("R" . meow-swap-grab) 139 | '("s" . meow-line) 140 | '("S" . meow-kmacro-lines) ;; 141 | '("t" . meow-till) 142 | '("u" . meow-undo) 143 | '("U" . vundo) 144 | '("v v" . meow-visit) ;; 145 | '("V" . meow-kmacro-matches) ;; 146 | '("w" . meow-mark-word) 147 | '("W" . meow-mark-symbol) 148 | 149 | '("x" . meow-delete) 150 | '("X" . meow-backward-delete) 151 | '("y" . meow-save) 152 | ;; '("Y" . meow-sync-save) 153 | '("z a" . hs-toggle-hiding) 154 | '("z c" . hs-hide-block) 155 | '("z o" . hs-show-block) 156 | '("z m" . hs-hide-all) 157 | '("z r" . hs-show-all) 158 | '("z z" . recenter-top-bottom) 159 | 160 | '("v i" . meow-inner-of-thing) 161 | '("v a" . meow-bounds-of-thing) 162 | '("v =" . insert-equation) 163 | 164 | '("-" . negative-argument) 165 | '("=" . indent-region) 166 | '("(" . backward-sentence) 167 | '(")" . forward-sentence) 168 | '("{" . backward-paragraph) 169 | '("}" . forward-paragraph) 170 | '("]" . nowis-graphviz-symbol-with-label) 171 | ;; '("]" . (lambda() 172 | ;; (interactive) 173 | ;; (meow-bounds-of-thing ?\"))) 174 | (cons "\\" wrap-keymap) 175 | '(";" . meow-expand-1) 176 | ;; '(":" . async-shell-command) 177 | '("'" . consult-register-load) 178 | '("\"" . consult-register) 179 | '("," . meow-reverse) 180 | '("." . repeat) 181 | 182 | '("" . ignore) 183 | '("!" . kmacro-start-macro-or-insert-counter) 184 | '("@" . meow-end-or-call-kmacro) 185 | '("#" . embark-toggle-highlight) 186 | '("^" . meow-join) 187 | '("*" . embark-next-symbol) 188 | '("/" . isearch-forward)) 189 | (defun meow-vim-append () 190 | "Like vim, move to the end of selection, switch to INSERT state." 191 | (interactive) 192 | (if meow--temp-normal 193 | (progn 194 | (message "Quit temporary normal mode") 195 | (meow--switch-state 'motion)) 196 | (if (not (region-active-p)) 197 | (progn 198 | (when (and meow-use-cursor-position-hack 199 | (< (point) (point-max))) 200 | (forward-char 1)) 201 | (forward-char 1) 202 | ) 203 | (meow--direction-forward) 204 | (meow--cancel-selection)) 205 | (meow--switch-state 'insert))) 206 | (meow-global-mode 1) 207 | 208 | (defun toggle-between-meow-normal-motion() 209 | (interactive) 210 | (if meow-motion-mode (meow-normal-mode) (meow-motion-mode))) 211 | (global-set-key (kbd "M-\\") #'toggle-between-meow-normal-motion) 212 | 213 | 214 | ;; which-key 215 | (setq which-key-idle-delay 0.1) 216 | (which-key-mode) 217 | (electric-pair-mode) 218 | 219 | ;; isearch 220 | (setq isearch-lazy-count t) 221 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "ace-window"] 2 | path = lib/ace-window 3 | url = https://github.com/abo-abo/ace-window.git 4 | [submodule "avy"] 5 | path = lib/avy 6 | url = https://github.com/abo-abo/avy.git 7 | [submodule "beancount"] 8 | path = lib/beancount 9 | url = https://github.com/beancount/beancount-mode.git 10 | [submodule "borg"] 11 | path = lib/borg 12 | url = https://github.com/emacscollective/borg.git 13 | [submodule "breadcrumb"] 14 | path = lib/breadcrumb 15 | url = https://github.com/joaotavora/breadcrumb.git 16 | [submodule "cape"] 17 | path = lib/cape 18 | url = https://github.com/minad/cape.git 19 | [submodule "cdlatex"] 20 | path = lib/cdlatex 21 | url = https://github.com/cdominik/cdlatex.git 22 | [submodule "citar"] 23 | path = lib/citar 24 | url = https://github.com/emacs-citar/citar.git 25 | no-byte-compile = citar-citeproc.el 26 | [submodule "citar-denote"] 27 | path = lib/citar-denote 28 | url = https://github.com/pprevos/citar-denote.git 29 | no-byte-compile = minimum-config.el 30 | [submodule "citre"] 31 | path = lib/citre 32 | url = https://github.com/universal-ctags/citre.git 33 | [submodule "clipetty"] 34 | path = lib/clipetty 35 | url = https://github.com/spudlyo/clipetty.git 36 | [submodule "cmake-mode"] 37 | path = lib/cmake-mode 38 | url = https://github.com/emacsmirror/cmake-mode.git 39 | [submodule "cond-let"] 40 | path = lib/cond-let 41 | url = https://github.com/tarsius/cond-let.git 42 | [submodule "consult"] 43 | path = lib/consult 44 | url = https://github.com/minad/consult.git 45 | [submodule "consult-dir"] 46 | path = lib/consult-dir 47 | url = https://github.com/karthink/consult-dir.git 48 | [submodule "corfu"] 49 | path = lib/corfu 50 | url = https://github.com/minad/corfu.git 51 | load-path = . 52 | load-path = extensions 53 | [submodule "csv-mode"] 54 | path = lib/csv-mode 55 | url = https://github.com/emacsmirror/csv-mode.git 56 | [submodule "dape"] 57 | path = lib/dape 58 | url = https://github.com/svaante/dape.git 59 | [submodule "darkroom"] 60 | path = lib/darkroom 61 | url = https://github.com/joaotavora/darkroom.git 62 | [submodule "dash"] 63 | path = lib/dash 64 | url = https://github.com/magnars/dash.el.git 65 | [submodule "dashboard"] 66 | path = lib/dashboard 67 | url = https://github.com/emacs-dashboard/emacs-dashboard.git 68 | [submodule "denote"] 69 | path = lib/denote 70 | url = https://github.com/protesilaos/denote.git 71 | [submodule "denote-explore"] 72 | path = lib/denote-explore 73 | url = https://github.com/pprevos/denote-explore.git 74 | [submodule "denote-journal"] 75 | path = lib/denote-journal 76 | url = https://github.com/protesilaos/denote-journal.git 77 | [submodule "diff-hl"] 78 | path = lib/diff-hl 79 | url = https://github.com/dgutov/diff-hl.git 80 | [submodule "dired-hacks"] 81 | path = lib/dired-hacks 82 | url = https://github.com/Fuco1/dired-hacks.git 83 | [submodule "dired-sidebar"] 84 | path = lib/dired-sidebar 85 | url = https://github.com/jojojames/dired-sidebar.git 86 | [submodule "dracula"] 87 | path = lib/dracula 88 | url = https://github.com/dracula/emacs.git 89 | [submodule "ebib"] 90 | path = lib/ebib 91 | url = https://github.com/joostkremers/ebib.git 92 | [submodule "eca"] 93 | path = lib/eca 94 | url = https://github.com/editor-code-assistant/eca-emacs.git 95 | [submodule "el-themes"] 96 | path = lib/el-themes 97 | url = https://github.com/protesilaos/ef-themes.git 98 | [submodule "elisp-demos"] 99 | path = lib/elisp-demos 100 | url = https://github.com/xuchunyang/elisp-demos.git 101 | [submodule "elisp-refs"] 102 | path = lib/elisp-refs 103 | url = https://github.com/Wilfred/elisp-refs.git 104 | [submodule "embark"] 105 | path = lib/embark 106 | url = https://github.com/oantolin/embark.git 107 | [submodule "engrave-faces"] 108 | path = lib/engrave-faces 109 | url = https://github.com/tecosaur/engrave-faces.git 110 | [submodule "esup"] 111 | path = lib/esup 112 | url = https://github.com/jschaf/esup.git 113 | [submodule "esxml"] 114 | path = lib/esxml 115 | url = https://github.com/tali713/esxml.git 116 | [submodule "f"] 117 | path = lib/f 118 | url = https://github.com/rejeep/f.el.git 119 | [submodule "format-all"] 120 | path = lib/format-all 121 | url = https://github.com/lassik/emacs-format-all-the-code.git 122 | [submodule "geiser"] 123 | path = lib/geiser 124 | url = https://github.com/emacsmirror/geiser.git 125 | [submodule "geiser-guile"] 126 | path = lib/geiser-guile 127 | url = https://github.com/emacsmirror/geiser-guile.git 128 | [submodule "gptel"] 129 | path = lib/gptel 130 | url = https://github.com/karthink/gptel.git 131 | [submodule "gptel-agent"] 132 | path = lib/gptel-agent 133 | url = https://github.com/karthink/gptel-agent.git 134 | [submodule "gptel-aibo"] 135 | path = lib/gptel-aibo 136 | url = https://github.com/dolmens/gptel-aibo.git 137 | [submodule "gptel-local-org-prompts"] 138 | path = lib/gptel-local-org-prompts 139 | url = https://github.com/nowislewis/gptel-local-org-prompts.git 140 | [submodule "gptel-quick"] 141 | path = lib/gptel-quick 142 | url = https://github.com/karthink/gptel-quick.git 143 | [submodule "graphviz-dot-mode"] 144 | path = lib/graphviz-dot-mode 145 | url = https://github.com/ppareit/graphviz-dot-mode.git 146 | no-byte-compile = company-graphviz-dot.el 147 | [submodule "helpful"] 148 | path = lib/helpful 149 | url = https://github.com/Wilfred/helpful.git 150 | [submodule "hide-mode-line"] 151 | path = lib/hide-mode-line 152 | url = https://github.com/hlissner/emacs-hide-mode-line.git 153 | [submodule "hl-todo"] 154 | path = lib/hl-todo 155 | url = https://github.com/tarsius/hl-todo.git 156 | [submodule "imenu-list"] 157 | path = lib/imenu-list 158 | url = https://github.com/nowislewis/imenu-list.git 159 | [submodule "indent-bars"] 160 | path = lib/indent-bars 161 | url = https://github.com/jdtsmith/indent-bars.git 162 | [submodule "inheritenv"] 163 | path = lib/inheritenv 164 | url = https://github.com/purcell/inheritenv.git 165 | [submodule "jinx"] 166 | path = lib/jinx 167 | url = https://github.com/minad/jinx.git 168 | [submodule "kv"] 169 | path = lib/kv 170 | url = https://github.com/nicferrier/emacs-kv.git 171 | [submodule "language-id"] 172 | path = lib/language-id 173 | url = https://github.com/lassik/emacs-language-id.git 174 | [submodule "lisp-fsrs"] 175 | path = lib/lisp-fsrs 176 | url = https://github.com/open-spaced-repetition/lisp-fsrs.git 177 | build-step = borg-makeinfo 178 | [submodule "llama"] 179 | path = lib/llama 180 | url = https://github.com/tarsius/llama.git 181 | [submodule "lua-mode"] 182 | path = lib/lua-mode 183 | url = https://github.com/immerrr/lua-mode.git 184 | [submodule "magit"] 185 | path = lib/magit 186 | url = https://github.com/magit/magit 187 | [submodule "marginalia"] 188 | path = lib/marginalia 189 | url = https://github.com/minad/marginalia.git 190 | [submodule "markdown-mode"] 191 | path = lib/markdown-mode 192 | url = https://github.com/jrblevin/markdown-mode.git 193 | [submodule "meow"] 194 | path = lib/meow 195 | url = https://github.com/meow-edit/meow.git 196 | [submodule "minesweeper"] 197 | path = lib/minesweeper 198 | url = https://github.com/calancha/Minesweeper.git 199 | [submodule "mini-echo"] 200 | path = lib/mini-echo 201 | url = https://github.com/liuyinz/mini-echo.el.git 202 | [submodule "mpv"] 203 | path = lib/mpv 204 | url = https://github.com/kljohann/mpv.el.git 205 | [submodule "nerd-icons"] 206 | path = lib/nerd-icons 207 | url = https://github.com/rainstormstudio/nerd-icons.el.git 208 | [submodule "nerd-icons-completion"] 209 | path = lib/nerd-icons-completion 210 | url = https://github.com/rainstormstudio/nerd-icons-completion.git 211 | [submodule "nerd-icons-corfu"] 212 | path = lib/nerd-icons-corfu 213 | url = https://github.com/LuigiPiucco/nerd-icons-corfu.git 214 | [submodule "nerd-icons-dired"] 215 | path = lib/nerd-icons-dired 216 | url = https://github.com/rainstormstudio/nerd-icons-dired.git 217 | [submodule "no-littering"] 218 | path = lib/no-littering 219 | url = https://github.com/emacscollective/no-littering.git 220 | [submodule "nov"] 221 | path = lib/nov 222 | url = https://depp.brause.cc/nov.el.git 223 | [submodule "nowis-gptel-tools"] 224 | path = lib/nowis-gptel-tools 225 | url = https://github.com/nowislewis/nowis-gptel-tools.git 226 | [submodule "orderless"] 227 | path = lib/orderless 228 | url = https://github.com/oantolin/orderless.git 229 | [submodule "org-appear"] 230 | path = lib/org-appear 231 | url = https://github.com/awth13/org-appear.git 232 | [submodule "org-elp"] 233 | path = lib/org-elp 234 | url = https://github.com/guanyilun/org-elp.git 235 | [submodule "org-graphviz-mindmap"] 236 | path = lib/org-graphviz-mindmap 237 | url = https://github.com/nowislewis/org-graphviz-mindmap.git 238 | [submodule "org-inc"] 239 | path = lib/org-inc 240 | url = https://github.com/bohonghuang/org-inc.git 241 | build-step = borg-makeinfo 242 | [submodule "org-ladder"] 243 | path = lib/org-ladder 244 | url = https://github.com/nowislewis/org-ladder.git 245 | [submodule "org-media-note"] 246 | path = lib/org-media-note 247 | url = https://github.com/yuchen-lea/org-media-note.git 248 | [submodule "org-noter"] 249 | path = lib/org-noter 250 | url = https://github.com/org-noter/org-noter.git 251 | load-path = . 252 | load-path = modules 253 | [submodule "org-present"] 254 | path = lib/org-present 255 | url = https://github.com/rlister/org-present.git 256 | [submodule "org-sliced-images"] 257 | path = lib/org-sliced-images 258 | url = https://github.com/jcfk/org-sliced-images.git 259 | [submodule "org-srs"] 260 | path = lib/org-srs 261 | url = https://github.com/bohonghuang/org-srs.git 262 | [submodule "org-visual-outline"] 263 | path = lib/org-visual-outline 264 | url = https://github.com/legalnonsense/org-visual-outline.git 265 | [submodule "ox-hugo"] 266 | path = lib/ox-hugo 267 | url = https://github.com/kaushalmodi/ox-hugo.git 268 | [submodule "parsebib"] 269 | path = lib/parsebib 270 | url = https://github.com/joostkremers/parsebib.git 271 | [submodule "pinyinlib"] 272 | path = lib/pinyinlib 273 | url = https://github.com/nowislewis/pinyinlib.el.git 274 | [submodule "popper"] 275 | path = lib/popper 276 | url = https://github.com/karthink/popper.git 277 | [submodule "posframe"] 278 | path = lib/posframe 279 | url = https://github.com/tumashu/posframe.git 280 | [submodule "project-rootfile"] 281 | path = lib/project-rootfile 282 | url = https://github.com/buzztaiki/project-rootfile.el.git 283 | [submodule "pulsar"] 284 | path = lib/pulsar 285 | url = https://github.com/protesilaos/pulsar.git 286 | [submodule "rainbow-delimiters"] 287 | path = lib/rainbow-delimiters 288 | url = https://github.com/Fanael/rainbow-delimiters.git 289 | [submodule "rg"] 290 | path = lib/rg 291 | url = https://github.com/dajva/rg.el.git 292 | [submodule "rime"] 293 | path = lib/rime 294 | url = https://github.com/DogLooksGood/emacs-rime.git 295 | [submodule "s"] 296 | path = lib/s 297 | url = https://github.com/magnars/s.el.git 298 | [submodule "setup"] 299 | path = lib/setup 300 | url = https://github.com/emacsmirror/setup.git 301 | [submodule "tabspaces"] 302 | path = lib/tabspaces 303 | url = https://github.com/mclear-tools/tabspaces.git 304 | [submodule "toc-org"] 305 | path = lib/toc-org 306 | url = https://github.com/snosov1/toc-org.git 307 | [submodule "tomelr"] 308 | path = lib/tomelr 309 | url = https://github.com/kaushalmodi/tomelr.git 310 | [submodule "treesit-auto"] 311 | path = lib/treesit-auto 312 | url = https://github.com/renzmann/treesit-auto.git 313 | [submodule "uniline"] 314 | path = lib/uniline 315 | url = https://github.com/tbanel/uniline.git 316 | [submodule "vertico"] 317 | path = lib/vertico 318 | url = https://github.com/minad/vertico.git 319 | load-path = . 320 | load-path = extensions 321 | [submodule "vterm"] 322 | path = lib/vterm 323 | url = https://github.com/akermu/emacs-libvterm.git 324 | [submodule "vundo"] 325 | path = lib/vundo 326 | url = https://github.com/casouri/vundo.git 327 | [submodule "wgrep"] 328 | path = lib/wgrep 329 | url = https://github.com/mhayashi1120/Emacs-wgrep.git 330 | no-byte-compile = wgrep-subtest.el 331 | no-byte-compile = wgrep-ag.el 332 | [submodule "whisper"] 333 | path = lib/whisper 334 | url = https://github.com/natrys/whisper.el.git 335 | [submodule "with-editor"] 336 | path = lib/with-editor 337 | url = https://github.com/magit/with-editor.git 338 | [submodule "ws-butler"] 339 | path = lib/ws-butler 340 | url = https://github.com/lewang/ws-butler.git 341 | [submodule "yaml"] 342 | path = lib/yaml 343 | url = https://github.com/zkry/yaml.el.git 344 | [submodule "yasnippet"] 345 | path = lib/yasnippet 346 | url = https://github.com/joaotavora/yasnippet.git 347 | [submodule "ztree"] 348 | path = lib/ztree 349 | url = https://codeberg.org/fourier/ztree.git 350 | -------------------------------------------------------------------------------- /useful-tools/old-elisps/org-roam-config.org: -------------------------------------------------------------------------------- 1 | * org-roam 2 | ** org-roam 3 | #+begin_src elisp :tangle no 4 | (setup emacsql-sqlite-builtin) 5 | (setup org-roam 6 | (:option org-roam-database-connector 'sqlite-builtin 7 | org-roam-mode-sections '(org-roam-backlinks-section 8 | org-roam-reflinks-section 9 | ;; org-roam-unlinked-references-section 10 | ) 11 | org-roam-directory (concat nowisemacs-doc-root-dir "/orgmode/roam/") 12 | org-roam-dailies-directory (concat nowisemacs-doc-root-dir "/orgmode/roam/dailies") 13 | 14 | org-roam-db-gc-threshold most-positive-fixnum 15 | ;; org-roam-node-display-template "${doom-hierarchy:*} ${tags:37}" 16 | org-roam-node-display-template (concat "${namespace:15} ${doom-hierarchy:80} " 17 | (propertize "${tags:*}" 'face 'org-tag)) 18 | 19 | org-roam-capture-templates '(("m" "main" plain "%?" 20 | :target 21 | (file+head "main/%<%Y-%m-%d>-${slug}.org" 22 | "#+title: ${title}\n* Action notes\n* Idea notes\n* Sealed notes") 23 | :unnarrowed t) 24 | ("r" "reference" plain "%?" 25 | :target 26 | (file+head "reference/%<%Y-%m-%d>-${slug}.org" 27 | "#+title: ${title}\n* Action notes\n* Idea notes\n* Sealed notes") 28 | :unnarrowed t) 29 | ("a" "article" plain "%?" 30 | ;; :target 31 | :if-new 32 | (file+head "articles/%<%Y-%m-%d>-${slug}.org" 33 | "#+title: ${title}\n* Action notes\n* Idea notes\n* Sealed notes") 34 | :unnarrowed t)) 35 | ) 36 | (:when-loaded 37 | (org-roam-db-autosync-mode) 38 | 39 | ;; Codes blow are used to general a hierachy for title nodes that under a file 40 | (cl-defmethod org-roam-node-doom-filetitle ((node org-roam-node)) 41 | "Return the value of \"#+title:\" (if any) from file that NODE resides in. 42 | If there's no file-level title in the file, return empty string." 43 | (or (if (= (org-roam-node-level node) 0) 44 | (org-roam-node-title node) 45 | (org-roam-get-keyword "TITLE" (org-roam-node-file node))) 46 | "")) 47 | (cl-defmethod org-roam-node-doom-hierarchy ((node org-roam-node)) 48 | "Return hierarchy for NODE, constructed of its file title, OLP and direct title. 49 | If some elements are missing, they will be stripped out." 50 | (let ((title (org-roam-node-title node)) 51 | (olp (org-roam-node-olp node)) 52 | (level (org-roam-node-level node)) 53 | (filetitle (org-roam-node-doom-filetitle node)) 54 | (separator (propertize " > " 'face 'shadow))) 55 | (cl-case level 56 | ;; node is a top-level file 57 | (0 filetitle) 58 | ;; node is a level 1 heading 59 | (1 (concat (propertize filetitle 'face '(shadow italic)) 60 | separator title)) 61 | ;; node is a heading with an arbitrary outline path 62 | (t (concat (propertize filetitle 'face '(shadow italic)) 63 | separator (propertize (string-join olp " > ") 'face '(shadow italic)) 64 | separator title))))) 65 | 66 | 67 | (cl-defmethod org-roam-node-namespace ((node org-roam-node)) 68 | "Return the TYPE of NODE." 69 | (condition-case nil 70 | (file-name-nondirectory 71 | (directory-file-name 72 | (file-name-directory 73 | (file-relative-name (org-roam-node-file node) org-roam-directory)))) 74 | (error ""))) 75 | (add-to-list 'display-buffer-alist 76 | '("\\*org-roam\\*" 77 | (display-buffer-in-direction) 78 | (direction . right) 79 | (window-width . 0.33) 80 | (window-height . fit-window-to-buffer))) 81 | (org-roam-buffer-toggle) 82 | ;; (magit-section-show-level-2-all) 83 | 84 | ;; Every Zettel is a Draft until Declared Otherwise 85 | (add-hook 'org-roam-capture-new-node-hook (lambda() 86 | (org-roam-tag-add '("draft")))) 87 | )) 88 | #+end_src 89 | 90 | ** org-roam-ui 91 | #+begin_src elisp :tangle no 92 | (setup websocket) 93 | (setup simple-httpd) 94 | (setup org-roam-ui 95 | (:option org-roam-ui-browser-function #'eaf-open-browser-other-window)) 96 | #+end_src 97 | ** consult-org-roam 98 | #+begin_src elisp :tangle no 99 | (setup consult-org-roam 100 | (:hook-into org-roam-mode)) 101 | #+end_src 102 | ** org-roam-agenda 103 | The main purpose for this section is to add every node that has a "TODO" into org-agenda, so I can see all the "TODO"s 104 | among all the files in org-roam in a single agenda-view. The code was borrowed from vulpea and now in a repo "org-roam-agenda". You can see in [[https://github.com/nowislewis/org-roam-agenda.git][org-roam-agenda]] 105 | #+begin_src elisp :tangle no 106 | ;; -*- lexical-binding: t; -*- 107 | 108 | (defun vulpea-buffer-p () 109 | "Return non-nil if the currently visited buffer is a note." 110 | (and buffer-file-name 111 | (string-prefix-p 112 | (expand-file-name (file-name-as-directory org-roam-directory)) 113 | (file-name-directory buffer-file-name)))) 114 | 115 | (defun vulpea-project-files () 116 | "Return a list of note files containing 'project' tag." ; 117 | (seq-uniq 118 | (seq-map 119 | #'car 120 | (org-roam-db-query 121 | [:select [nodes:file] 122 | :from tags 123 | :left-join nodes 124 | :on (= tags:node-id nodes:id) 125 | :where (like tag (quote "%\"project\"%"))])))) 126 | 127 | (defun vulpea-agenda-files-update (&rest _) 128 | "Update the value of `org-agenda-files'." 129 | (setq org-agenda-files (vulpea-project-files))) 130 | 131 | (add-hook 'find-file-hook #'vulpea-project-update-tag) 132 | (add-hook 'before-save-hook #'vulpea-project-update-tag) 133 | 134 | (advice-add 'org-agenda :before #'vulpea-agenda-files-update) 135 | (advice-add 'org-todo-list :before #'vulpea-agenda-files-update) 136 | 137 | ;; functions borrowed from `vulpea' library 138 | ;; https://github.com/d12frosted/vulpea/blob/6a735c34f1f64e1f70da77989e9ce8da7864e5ff/vulpea-buffer.el 139 | (defun vulpea-buffer-tags-get () 140 | "Return filetags value in current buffer." 141 | (vulpea-buffer-prop-get-list "filetags" "[ :]")) 142 | 143 | (defun vulpea-buffer-tags-set (&rest tags) 144 | "Set TAGS in current buffer. 145 | 146 | If filetags value is already set, replace it." 147 | (if tags 148 | (vulpea-buffer-prop-set 149 | "filetags" (concat ":" (string-join tags ":") ":")) 150 | (vulpea-buffer-prop-remove "filetags"))) 151 | 152 | (defun vulpea-buffer-tags-add (tag) 153 | "Add a TAG to filetags in current buffer." 154 | (let* ((tags (vulpea-buffer-tags-get)) 155 | (tags (append tags (list tag)))) 156 | (apply #'vulpea-buffer-tags-set tags))) 157 | 158 | (defun vulpea-buffer-tags-remove (tag) 159 | "Remove a TAG from filetags in current buffer." 160 | (let* ((tags (vulpea-buffer-tags-get)) 161 | (tags (delete tag tags))) 162 | (apply #'vulpea-buffer-tags-set tags))) 163 | 164 | (defun vulpea-buffer-prop-set (name value) 165 | "Set a file property called NAME to VALUE in buffer file. 166 | If the property is already set, replace its value." 167 | (setq name (downcase name)) 168 | (org-with-point-at 1 169 | (let ((case-fold-search t)) 170 | (if (re-search-forward (concat "^#\\+" name ":\\(.*\\)") 171 | (point-max) t) 172 | (replace-match (concat "#+" name ": " value) 'fixedcase) 173 | (while (and (not (eobp)) 174 | (looking-at "^[#:]")) 175 | (if (save-excursion (end-of-line) (eobp)) 176 | (progn 177 | (end-of-line) 178 | (insert "\n")) 179 | (forward-line) 180 | (beginning-of-line))) 181 | (insert "#+" name ": " value "\n"))))) 182 | 183 | (defun vulpea-buffer-prop-set-list (name values &optional separators) 184 | "Set a file property called NAME to VALUES in current buffer. 185 | VALUES are quoted and combined into single string using 186 | `combine-and-quote-strings'. 187 | If SEPARATORS is non-nil, it should be a regular expression 188 | matching text that separates, but is not part of, the substrings. 189 | If nil it defaults to `split-string-default-separators', normally 190 | \"[ \f\t\n\r\v]+\", and OMIT-NULLS is forced to t. 191 | If the property is already set, replace its value." 192 | (vulpea-buffer-prop-set 193 | name (combine-and-quote-strings values separators))) 194 | 195 | (defun vulpea-buffer-prop-get (name) 196 | "Get a buffer property called NAME as a string." 197 | (org-with-point-at 1 198 | (when (re-search-forward (concat "^#\\+" name ": \\(.*\\)") 199 | (point-max) t) 200 | (buffer-substring-no-properties 201 | (match-beginning 1) 202 | (match-end 1))))) 203 | 204 | (defun vulpea-buffer-prop-get-list (name &optional separators) 205 | "Get a buffer property NAME as a list using SEPARATORS. 206 | If SEPARATORS is non-nil, it should be a regular expression 207 | matching text that separates, but is not part of, the substrings. 208 | If nil it defaults to `split-string-default-separators', normally 209 | \"[ \f\t\n\r\v]+\", and OMIT-NULLS is forced to t." 210 | (let ((value (vulpea-buffer-prop-get name))) 211 | (when (and value (not (string-empty-p value))) 212 | (split-string-and-unquote value separators)))) 213 | 214 | (defun vulpea-buffer-prop-remove (name) 215 | "Remove a buffer property called NAME." 216 | (org-with-point-at 1 217 | (when (re-search-forward (concat "\\(^#\\+" name ":.*\n?\\)") 218 | (point-max) t) 219 | (replace-match "")))) 220 | 221 | (defun vulpea-project-p () 222 | "Return non-nil if current buffer has any todo entry. 223 | 224 | TODO entries marked as done are ignored, meaning the this 225 | function returns nil if current buffer contains only completed 226 | tasks." 227 | (seq-find ; (3) 228 | (lambda (type) 229 | (eq type 'todo)) 230 | (org-element-map ; (2) 231 | (org-element-parse-buffer 'headline) ; (1) 232 | 'headline 233 | (lambda (h) 234 | (org-element-property :todo-type h))))) 235 | 236 | (defun vulpea-project-update-tag () 237 | "Update PROJECT tag in the current buffer." 238 | (when (and (not (active-minibuffer-window)) 239 | (vulpea-buffer-p)) 240 | (save-excursion 241 | (goto-char (point-min)) 242 | (let* ((tags (vulpea-buffer-tags-get)) 243 | (original-tags tags)) 244 | (if (vulpea-project-p) 245 | (setq tags (cons "project" tags)) 246 | (setq tags (remove "project" tags))) 247 | 248 | ;; cleanup duplicates 249 | (setq tags (seq-uniq tags)) 250 | 251 | ;; update tags if changed 252 | (when (or (seq-difference tags original-tags) 253 | (seq-difference original-tags tags)) 254 | (apply #'vulpea-buffer-tags-set tags)))))) 255 | #+end_src 256 | ** citar-org-roam 257 | #+begin_src elisp :tangle no 258 | (setup citar-org-roam 259 | (:option citar-org-roam-subdir "reference" 260 | citar-org-roam-note-title-template "${title}") 261 | (:hook-into org-roam-mode) 262 | (:when-loaded 263 | (defun citar-org-roam--create-capture-note (citekey entry) 264 | "Open or create org-roam node for CITEKEY and ENTRY." 265 | ;; adapted from https://jethrokuan.github.io/org-roam-guide/#orgc48eb0d 266 | (let ((title (citar-format--entry 267 | citar-org-roam-note-title-template entry))) 268 | (org-roam-capture- 269 | :templates 270 | '(("r" "reference" plain "%?" :if-new 271 | (file+head "reference/${title}.org" 272 | ":PROPERTIES:\n:ROAM_REFS: [cite:@${citekey}]\n:END:\n#+title: ${title}\n* Action notes\n* Idea notes\n* Sealed notes") 273 | :unnarrowed t)) 274 | :info (list :citekey citekey) 275 | :node (org-roam-node-create :title title) 276 | :props '(:finalize find-file)))) 277 | )) 278 | #+end_src 279 | ** denote-convert-from-org-roam 280 | #+begin_src elisp :tangle no 281 | (defun org-roam-convert-to-denote (files dir) 282 | "Convert org-roam notes to denote format and insert them into 283 | `denote-directory'. Works in Dired." 284 | (interactive 285 | (list (dired-get-marked-files t current-prefix-arg nil nil t) 286 | (read-directory-name "Denote directory: " (denote-directory)))) 287 | (unless (file-exists-p dir) (error "Directory does not exist: %s" dir)) 288 | 289 | (dolist (file files) 290 | (let* ((filename (file-name-base file)) 291 | (org-roam-filename-regex 292 | (rx 293 | ;; date: YYYY-MM-DD 294 | (group (= 4 digit) "-" (= 2 digit) "-" (= 2 digit)) 295 | "-" 296 | ;; title 297 | (group (* any)))) 298 | (match? (string-match org-roam-filename-regex filename))) 299 | (unless match? 300 | (warn "Filename doesn't match org-roam-filename-regex: %s" filename)) 301 | (let* ((date (match-string 1 filename)) 302 | 303 | (format-time-string "%H%M%S") 304 | ;; (time (match-string 2 filename)) 305 | (title (or ;; Try to get title with spaces. 306 | (denote-retrieve--value-title file) 307 | (replace-regexp-in-string "_" " " (match-string 2 filename)))) 308 | (decoded-time (date-to-time (concat date "T" (format-time-string "%H%M%S")))) 309 | (id (format-time-string denote--id-format decoded-time)) 310 | ;; Code from `org-roam-tag-add'. 311 | (keywords (with-temp-buffer (insert-file-contents file nil 0 1024) 312 | (split-string (or (cadr (assoc "filetags" 313 | (org-collect-keywords '("filetags")))) 314 | "") 315 | ":" 'omit-nulls))) 316 | (keywords (denote--sluggify-keywords 317 | (if (cdr keywords) keywords (car keywords)))) 318 | (new-name (denote--format-file 319 | (denote-directory) 320 | id 321 | keywords 322 | (denote--sluggify title) 323 | (denote--file-extension)))) 324 | ;; Ask for confirmation when overwriting, but don't throw an error if 325 | ;; the user declines. 326 | (ignore-errors (copy-file file new-name 1)) 327 | 328 | (with-current-buffer (find-file-noselect new-name t) 329 | (when-let* (((denote--only-note-p file)) 330 | (filetype (denote-dired--filetype-heuristics file)) 331 | (date (denote--date (date-to-time id))) 332 | (new-front-matter (denote--file-meta-header title date keywords id filetype))) 333 | (goto-char (point-min)) 334 | (insert new-front-matter))) 335 | 336 | (message "Converted %s -> %s" file new-name)))) 337 | (denote-dired-update-dired-buffers)) 338 | 339 | #+end_src 340 | -------------------------------------------------------------------------------- /README.org: -------------------------------------------------------------------------------- 1 | #+begin_src elisp 2 | 3 | _____ _____ ____ _______ _______ ____________ _____ 4 | |\ \ \ \ ____\_ \__ / /| |\ \ / \ _____\ \ 5 | \\ \ | | / / \ / / | | \ \ |\___/\ \\___/| / / \ | 6 | \\ \ | | / /\ || / |___| \ | \|____\ \___|/ | | /___/| 7 | \| \ | | | | | || | | | | | | | ____\ \ | || 8 | | \| | | | | || \ \ / / | __ / / __ / /\ \|___|/ 9 | / /\ \ | | / /|| |\\/ \//| | / \/ /_/ || |/ \ \ 10 | /_____/ /______/||\ \_____/ ||\_____\|\_____/|/_____/||____________/||\____\ /____/| 11 | | | | | || \_____\ | / | | | | | | | || | /| | || | | 12 | |______|/|_____|/ \ | |___|/ \|_____|\|___|/|_____|/ |___________|/ \|___||____|/ 13 | \|____| 14 | #+end_src 15 | * Contents :toc: 16 | - [[#introduction-to-nowisemacs][Introduction to nowisemacs]] 17 | - [[#features][Features]] 18 | - [[#how-to-use][How to use]] 19 | - [[#how-to-customize][How to customize]] 20 | - [[#useful-keybindings][Useful Keybindings]] 21 | - [[#leader-keybinds][leader keybinds]] 22 | - [[#vim-users-should-care][vim users should care]] 23 | - [[#ideas-behind-nowisemacs][Ideas behind nowisemacs]] 24 | - [[#tl--nr][TL ; NR]] 25 | - [[#description-in-detail][Description in detail]] 26 | - [[#things-you-must-know-before-going-deeper][Things you must know before going deeper]] 27 | - [[#radical][Radical]] 28 | - [[#sacrifice-for-simplicity][Sacrifice for simplicity]] 29 | - [[#beginners-are-encouraged-to-access-package-website][Beginners are encouraged to access package website]] 30 | - [[#optinal-reading][Optinal reading]] 31 | - [[#why-setup-instead-of-simpler-manual-configuration-or-full-blown-use-package][Why setup instead of simpler manual configuration or full-blown use-package?]] 32 | - [[#how-to-become-a-proficient-user-in-emacs][How to become a proficient user in emacs]] 33 | - [[#related-great-solutions][Related great solutions]] 34 | 35 | * Introduction to nowisemacs 36 | Nowisemacs is a configuration framework for GNU Emacs that tends to be used in everyday scenarios with a wealth of 37 | features but on an easy-to-maintain 38 | basis. 39 | 40 | It's designed by following principles: 41 | + *Close to metal*. As a core idea of nowisemacs, there should be less between users and vanilla emacs. 42 | + *Easy to use and modify*. 43 | Generally, the 44 | higher degree of abstraction, the stronger the applicability of programs. But the abstraction will increase the 45 | distance between users and native codes and make it more difficult for users to maintain codes. Nowiemacs trys to solve this problems in two ways: 46 | 1. Nowisemacs uses a tiling scheme to avoid high level code abstraction, and uses an org-structure to combine all 47 | components to avoid the code confusion caused by the tile scheme. Thus, nowisemacs separate the code structure and 48 | functional structure. Users are supposed to focus only on the functional structure when using it, and focus only on code structure 49 | when modifying code. 50 | 2. Nowisemacs provides many simple macros to simplify the daily configuration of users. With the help of =setup=, users 51 | can quickly handle the configuration cycle of a new or existing package. At the same time, users are encouraged to get the real native code 52 | everywhere by using =emacs-lisp-macroexpand=. 53 | ** Features 54 | + Affected by lazycat-emacs, there is a clear process chain in nowisemacs. 55 | + Easy to expand new features, easy to understand the framework. 56 | + Writing on the fly with a full configured org-mode, includes beautiful interfaces, a deep integration with denote and denote-citar to manage references with notes. 57 | Use a GTD methods to manage personal trials based on org-agenda. 58 | + Many useful English auxiliary writing tools and so on. 59 | + Universal programming solution including completion, jump, search under different path or files. With the help of *Language Server Protocol* powered by Microsoft and the great ctags 60 | front-end *citre*, users can easily use and expand almost all programming languages under emacs. 61 | + Rime integration, orderless completion everywhere. 62 | ** How to use 63 | ---------------------------------------------------------------------------------------------------------------------------- 64 | |*All configs can be seen [[file:init.org][here]], it is highly recommended that you read this document first.*| 65 | --------------------------------------------------------------------------------------------------------------------------- 66 | 67 | Nowisemacs uses a single org file to manage all configurations. To reduce the startup time of emacs, users need to 68 | generate =.el= configuration files before the first startup 69 | 70 | *** Installation 71 | **** Dependences 72 | 1. Install =ripgrep= and =fd=. 73 | **** Nowisemacs 74 | 1. =mv ~/.emacs.d ~/.emacs.d.back= ;; Backup your original configuration 75 | 2. =git clone https://github.com/nowislewis/nowisemacs ~/.emacs.d= ;; Download nowisemacs 76 | 3. =cd ~/.emacs.d= 77 | 4. =make bootstrap-borg & make bootstrap= ;; download and build packages 78 | 5. (optional) =make native= ;; if you build emacs with native-comp, use this command to build all packages ahead-of-time. 79 | 6. =emacs= ;; Launch emacs, the download, installation and configuration of packages will be done automatically. 80 | 7. M-x 81 | 7. If you upgrade packages or install new packages, just run =make= in the =.emacs.d= dir. 82 | *** Add packages 83 | 1. Inside emacs, run =M-x borg-assimilate=, and then input your package name and git url sequentially. 84 | 2. Run =M-x borg-active=, choose the package you just installed. 85 | *** Remove packages 86 | 1. Inside emacs, run =M-x borg-remove=, choose the package you want to remove. 87 | *** Update packages 88 | 1. =make update= ;; get all packages update latest 89 | 2. =git add .=, then =make build= ;; build packages 90 | 3. (optional) =make native= ;; if you build emacs with native-comp, use this command to build all packages ahead-of-time. 91 | *** display icons correctly 92 | [nerd-icons](https://github.com/rainstormstudio/nerd-icons.el) are necessary. Run `M-x nerd-icons-install-fonts` to 93 | install the resource fonts. On Windows, the fonts should be installed manually. `nerd-icons` supports bot GUI and TUI. 94 | ** How to customize 95 | *** Change configurations 96 | Nowisemacs use =setup.el= to config all the configuration but you can also use built-in methods, =setup= is just a simple wrapper of these methods. You can get a clear understand in anywhere by typing =M-x emacs-lisp-macroexpand=, and the =setup= code will be expanded to normal built-in methods. 97 | 98 | Every time you make some changes on =~/.emacs.d/init.org= (eg, write down = | Move point to the end of the buffer | 139 | | M-< | Move point to the beginning of the buffer | 140 | | M-v | Scroll text of selected window down ARG lines; or near full screen if no ARG | 141 | | C-v | Scroll text of selected window upward ARG lines; or near full screen if no ARG | 142 | | C-w | Kill ("cut") text between point and mark | 143 | | e | meow-next-word, select to the end of the next Nth word | 144 | | b | meow-back-word, select to the beginning the previous Nth word | 145 | | f | meow-find, find the next N char read from minibuffer | 146 | | c c | meow-change, kill current selection and switch to INSERT state | 147 | | n | moew-search, search and select with the car of the current regexp-search-ring | 148 | | v a | text-object based operation (arounding objects) | 149 | | v i | text-object based operation (inside objects) | 150 | | m + any letter | save the current location into registers with name "letter" | 151 | | ' + any letter | load the location registers of name "letter" | 152 | | g d | jump to definition | 153 | | g D | jump to reference | 154 | | g a | code actions | 155 | 156 | Press =Space ?= to get a view of keybings under normal status. 157 | * Ideas behind nowisemacs 158 | ** TL ; NR 159 | Concise + High maintainability 160 | ** Description in detail 161 | *** Understand Emacs from the perspective of system architecture 162 | 1. Emacs can be regarded as a virtual machine of the lisp language. And the core function of a virtual machine is to 163 | manage memory. 164 | 2. The built-in variables and functions defined by Emacs are set together with the user-defined functions, and they are 165 | all equivalent as First-class citizen. 166 | 3. Therefore, most of the user's operation on Emacs correspond to a function, and users can modify all external or 167 | built-in variables and functions. In other words, users should regard themselves as internal schedulers of the 168 | system, not external users. 169 | *** Packages and related configurations should be simple 170 | Simplicity doesn't mean that the number of packages used is few, or the interface is ugly, but that the following 171 | concepts should be met as far as possible: 172 | 1. Try to use built-in functions to reduce redundancy. The rational use of these APIs can greatly reduce the external 173 | maintenance burden. 174 | 2. Packages should be designed simple and flexible, which will reduce dependencies. 175 | 3. Packages with less code or active updates will have higher priority. 176 | 4. Try to use the default configuration or select packages with enough default configuration to avoid the update burden 177 | caused by numerous hacks. 178 | *** Balance 179 | I like rich functionality, which allows me to have suitable solutions for various scenarios. Usually adding a functionality 180 | will increase the complexity of configurations. Nowisemacs looks for a balance between functionality and complexity by 181 | "concise" choices. 182 | * Things you must know before going deeper 183 | ** Radical 184 | 1. Nowisemacs always uses the latest emacs version and compile it locally, so there may be some incompatible when you use an older version. 185 | 2. Fast iteration, no option of "all" packages. If there is a package with a cleaner code implementation than the one 186 | used now, or fewer dependencies, or better functionality, only *one* will be left. 187 | ** Sacrifice for simplicity 188 | The code will be kept iteratively updated and thus less stable, because any duplicated or useless code will be 189 | updated or optimized immediately, with little consideration for compatibility. 190 | ** Beginners are encouraged to access package website 191 | Many functions provided by packages are invoked manually as APIs with =M-x= with few key bindings. Users are encouraged to 192 | access the website of packages to get a comprehensive understanding. 193 | * Optinal reading 194 | ** Why setup instead of simpler manual configuration or full-blown use-package? 195 | As mentioned above, nowisemacs hoped to reduce the abstraction level of configuration as much as possible while meeting 196 | practical requirements, so as they facilitate the understanding of configuration maintenance code. 197 | 198 | After heavy use for a period of time, I gave up use-package and leaf. They have a high degree of abstraction and thus 199 | complex mechanisms, which is not conducive to understanding and debugging. 200 | 201 | At the suggestion of Lazycat, a great Emacs contributor, I have used the native way to configure Emacs for a while. I 202 | really like this idea, it is clear and easy to drill down. No black box here. 203 | 204 | But if you use the native way, you will find that there is a lot of duplicated codes, which make the work tedious and 205 | increase the maintenance work. =setup= comes into view. First, =setup= is almost indistinguishable from the native 206 | way at the level of abstraction. =setup= is actually a bunch of simple macros to generate code. And the code generated 207 | after macro-expand is almost the same as native methods. So =setup= is also clear and easy to drill down as native way. 208 | 209 | The function of =setup= is to turn these repeated codes into simple calls, which are equivalent to defining one place, but 210 | can be used everywhere. 211 | 212 | What's more, =setup= can easily change the code context such as keymap context or hook context. It's easy to get complex 213 | configuration clear. 214 | ** How to become a proficient user in emacs 215 | I would like to first give my own experience through these difficulties for beginners: 216 | 217 | 1. I have been using doom emacs for a long time, which is a great configuration framework for vim users. During that, I 218 | was mainly familiar with various cool or practical functions of emacs, which greatly aroused interest and made it 219 | clear what an excellent emacs should be and what does it look like. 220 | 2. Then I found I need some personal features for my daily work, but it's hard to achieve an end because it's always 221 | easy to get stuck in a lot of code traps. I don't know how to sort out my own process. 222 | 3. After some time I found a very native configuration, lazycat-emacs, and learned how to configure all the code in the lowest-level way, including manually managing packages, manually controlling the loading order, etc. 223 | 4. After understanding what I need to set after startup. Things I needed to figure out became clear again: 224 | + First, to implement whatever features I need. 225 | + Second, to control the abstraction level of the configuration so as not to increase maintenance pressure. 226 | 227 | The configuration of nowisemacs is not there all at once. There is an article "Understanding emacs from the perspective of operating system architecture" that gave me a good inspiration, let me try to use emacs from the perspective of an emacs itself rather than an emacs user. As an emacs, how can I meet user needs? 228 | 229 | + First, when users give me requirements, I need to know how to combine existing functions to achieve this requirement; 230 | + Second, I can find or implement these functions. 231 | 232 | With this idea in mind, nowisemacs tries to separate functional structure and code structure to solve this problem. 233 | * Related great solutions 234 | + [[https://github.com/hlissner/doom-emacs][doom emacs]] 235 | + [[https://github.com/manateelazycat/lazycat-emacs][lazycat-emacs]] 236 | + [[https://github.com/seagle0128/.emacs.d][centaur emacs]] 237 | -------------------------------------------------------------------------------- /init.org: -------------------------------------------------------------------------------- 1 | #+TITLE: Emacs Configuration 2 | #+PROPERTY: header-args:elisp :tangle ~/.emacs.d/init.el 3 | I failed in love with denote, so previous *org-roam* configs were refiled into [[file:useful-tools/old-elisps/org-roam-config.org][org-roam configs]] 4 | * Content :toc: 5 | - [[#startup-configs][Startup configs]] 6 | - [[#ui-speed-up][UI speed up]] 7 | - [[#basic-modes][basic modes]] 8 | - [[#load-path][load-path]] 9 | - [[#drop-out][drop out]] 10 | - [[#set-vars][set vars]] 11 | - [[#package-management][Package Management]] 12 | - [[#setup][setup]] 13 | - [[#other-macros][other macros]] 14 | - [[#keyboard-bindings][Keyboard Bindings]] 15 | - [[#meow][meow]] 16 | - [[#transient-and-related-leader-map][transient and related leader-map]] 17 | - [[#meow-leader-keybindings][meow leader keybindings]] 18 | - [[#which-key][which-key]] 19 | - [[#electric][electric]] 20 | - [[#package-library][Package Library]] 21 | - [[#dash][dash]] 22 | - [[#s][s]] 23 | - [[#f][f]] 24 | - [[#ui][UI]] 25 | - [[#font][font]] 26 | - [[#variable-pitch][variable-pitch]] 27 | - [[#theme][Theme]] 28 | - [[#line-number][line number]] 29 | - [[#nerd-icons][nerd-icons]] 30 | - [[#nerd-icons-completion][nerd-icons-completion]] 31 | - [[#rainbow-delimiters][rainbow-delimiters]] 32 | - [[#diff-hl][diff-hl]] 33 | - [[#fringe-mode][fringe-mode]] 34 | - [[#emacs-dashboard][emacs-dashboard]] 35 | - [[#mini-echo][mini-echo]] 36 | - [[#hl-todo][hl-todo]] 37 | - [[#highlight-line][highlight line]] 38 | - [[#show-paren-mode][show-paren-mode]] 39 | - [[#general-configuration][General Configuration]] 40 | - [[#simple][simple]] 41 | - [[#general-builtin-modes][general builtin modes]] 42 | - [[#repeat-mode][repeat-mode]] 43 | - [[#backup][backup]] 44 | - [[#no-littering][no-littering]] 45 | - [[#recentf][recentf]] 46 | - [[#自动换行][自动换行]] 47 | - [[#long-line][long-line]] 48 | - [[#tramp][TRAMP]] 49 | - [[#automatically-clean-whitespace][Automatically clean whitespace]] 50 | - [[#vundo-for-undo-history][vundo for undo history]] 51 | - [[#search][Search]] 52 | - [[#isearch][isearch]] 53 | - [[#consult-commands][Consult Commands]] 54 | - [[#rgel][rg.el]] 55 | - [[#补全][补全]] 56 | - [[#completions-with-vertico][Completions with Vertico]] 57 | - [[#orderless-and-pinyinlib][Orderless and pinyinlib]] 58 | - [[#marginalia][Marginalia]] 59 | - [[#embark][embark]] 60 | - [[#yasnippet][yasnippet]] 61 | - [[#window-management][Window Management]] 62 | - [[#window][window]] 63 | - [[#winner-mode][winner-mode]] 64 | - [[#popper][popper]] 65 | - [[#move][Move]] 66 | - [[#ibuffer][ibuffer]] 67 | - [[#ibuffer-1][ibuffer]] 68 | - [[#input][Input]] 69 | - [[#posframe][posframe]] 70 | - [[#rime][rime]] 71 | - [[#file-and-browsing][File and Browsing]] 72 | - [[#file-browsing][file browsing]] 73 | - [[#structure-browsing][structure browsing]] 74 | - [[#tab-line-and-tab-bar][tab-line and tab-bar]] 75 | - [[#tabspaces][tabspaces]] 76 | - [[#project][project]] 77 | - [[#project-rootfile][project-rootfile]] 78 | - [[#auto-insert][auto-insert]] 79 | - [[#midnight][midnight]] 80 | - [[#shell][shell]] 81 | - [[#eshell][eshell]] 82 | - [[#eat][eat]] 83 | - [[#vterm][vterm]] 84 | - [[#git][git]] 85 | - [[#magit][magit]] 86 | - [[#ediff][ediff]] 87 | - [[#program][Program]] 88 | - [[#language][Language]] 89 | - [[#useful-programing-tools][Useful programing tools]] 90 | - [[#org-mode][Org Mode]] 91 | - [[#org-mode-1][org-mode]] 92 | - [[#org-src][org-src]] 93 | - [[#org-sidebar][org-sidebar]] 94 | - [[#org-zotero-parser][org-zotero-parser]] 95 | - [[#org-oxlatexwordmarkdown][org-ox,latex,word,markdown]] 96 | - [[#org-clock][org-clock]] 97 | - [[#org-timer][org-timer]] 98 | - [[#appt][appt]] 99 | - [[#ui-1][ui]] 100 | - [[#ox-hugo][ox-hugo]] 101 | - [[#org-present][org-present]] 102 | - [[#bibtex-related][bibtex related]] 103 | - [[#toc-org][toc-org]] 104 | - [[#denote-and-related][denote and related]] 105 | - [[#find-orgmode-dir-files][find orgmode dir files]] 106 | - [[#agendagtd][agenda/gtd]] 107 | - [[#org-srs][org-srs]] 108 | - [[#org-inc][org-inc]] 109 | - [[#insert-from-clipboard][insert from clipboard]] 110 | - [[#org-media-note][org-media-note]] 111 | - [[#org-sliced-images][org-sliced-images]] 112 | - [[#org-noter][org-noter]] 113 | - [[#org-graphviz-mindmap][org-graphviz-mindmap]] 114 | - [[#org-ladder][org-ladder]] 115 | - [[#阅读][阅读]] 116 | - [[#pdf-tools][pdf-tools]] 117 | - [[#pdf-view-pagemark][pdf-view-pagemark]] 118 | - [[#newsticker][newsticker]] 119 | - [[#nov][nov]] 120 | - [[#darkroom][darkroom]] 121 | - [[#markdown-mode][markdown-mode]] 122 | - [[#tools][tools]] 123 | - [[#ai-related][ai related]] 124 | - [[#webjump][webjump]] 125 | - [[#backup-scripts][backup scripts]] 126 | - [[#server][server]] 127 | - [[#macos-ocr][macos-ocr]] 128 | - [[#esup][esup]] 129 | - [[#uniline][uniline]] 130 | - [[#excalidraw][excalidraw]] 131 | - [[#manage-web-bookmarks][manage-web-bookmarks]] 132 | - [[#games][games]] 133 | - [[#minesweeper][minesweeper]] 134 | - [[#system-specific-config][system-specific-config]] 135 | - [[#windows-wslg][windows-wslg]] 136 | - [[#android][android]] 137 | 138 | * Startup configs 139 | ** UI speed up 140 | #+NAME: ui-speed-up 141 | #+begin_src elisp :tangle ~/.emacs.d/early-init.el 142 | ;; -*- lexical-binding: t; -*- 143 | ;; set gc according to EmacsConf 2023 144 | ;; (setq gc-cons-threshold 8000000 145 | ;; gc-cons-percentage 0.2) 146 | ;; Package initialize occurs automatically, before `user-init-file' is 147 | ;; loaded, but after `early-init-file'. We handle package 148 | ;; initialization, so we must prevent Emacs from doing it early! 149 | (setq package-enable-at-startup nil) 150 | 151 | ;; Inhibit resizing frame 152 | (setq frame-inhibit-implied-resize t) 153 | ;; disable warning 154 | (setq byte-compile-warnings nil) 155 | ;; no title bar 156 | ;; (add-to-list 'default-frame-alist '(undecorated . t)) 157 | ;; Faster to disable these here (before they've been initialized) 158 | ;; (push '(alpha-background . 80) default-frame-alist) 159 | (push '(menu-bar-lines . 0) default-frame-alist) 160 | (push '(tool-bar-lines . 0) default-frame-alist) 161 | (push '(vertical-scroll-bars) default-frame-alist) 162 | ;; (push '(undecorated . t) default-frame-alist) 163 | (setq initial-major-mode 'fundamental-mode ;; 默认用最简单的模式 164 | package--init-file-ensured t 165 | inhibit-startup-message t ; 关闭启动 Emacs 时的欢迎界面 166 | ) 167 | ;; speed font 168 | ;; (add-to-list 'default-frame-alist '(font . "Maple Mono SC NF")) 169 | 170 | ;; add support for android port of emacs 171 | (if (eq system-type 'android) 172 | (progn 173 | (setenv "PATH" (format "%s:%s" "/data/data/com.termux/files/usr/bin" 174 | (getenv "PATH"))) 175 | (push "/data/data/com.termux/files/usr/bin" exec-path))) 176 | 177 | #+end_src 178 | ** basic modes 179 | #+NAME: basic-modes 180 | #+begin_src elisp 181 | ;; -*- lexical-binding: t; -*- 182 | ;; basic modes 183 | (setq use-short-answers t) 184 | (setq confirm-kill-emacs 'y-or-n-p) 185 | (setq ring-bell-function 'ignore) ;关闭烦人的出错时的提示声 186 | (set-default-coding-systems 'utf-8) 187 | (setq-default indent-tabs-mode nil) 188 | 189 | (setq next-screen-context-lines 0) ;; scroll up/down lines 190 | (setq-default tab-width 4) 191 | ;; 平滑地进行半屏滚动,避免滚动后recenter操作 192 | (setq scroll-step 0 193 | scroll-conservatively 10000) 194 | (setq redisplay-skip-fontification-on-input t) 195 | (setq completions-detailed t) ;;useful in emacs 28 196 | (setq use-dialog-box nil) ;never pop dialog 197 | (setq mouse-yank-at-point t) ;粘贴于光标处,而不是鼠标指针处 198 | #+end_src 199 | ** load-path 200 | #+NAME: load-path 201 | #+begin_src elisp 202 | (add-to-list 'load-path (expand-file-name "lib/borg" user-emacs-directory)) 203 | (require 'borg) 204 | (setq borg-rewrite-urls-alist 205 | '(("git@github.com:" . "https://github.com/") 206 | ("git@gitlab.com:" . "https://gitlab.com/"))) 207 | (borg-initialize) 208 | #+end_src 209 | ** drop out 210 | The following content is not enabled yet, because I want to minimize unnecessary settings as much as possible 211 | #+begin_src elisp :tangle no 212 | ;; Restore emacs session. 213 | (setq initial-buffer-choice t) 214 | (run-with-timer 1 nil #'(lambda () (bury-buffer))) 215 | ;; 增加IO性能 216 | (setq process-adaptive-read-buffering nil) 217 | (setq read-process-output-max (* 1024 1024)) 218 | 219 | (global-subword-mode 1) ;Word移动支持 FooBar 的格式 220 | (setq initial-scratch-message "") ;关闭启动空白buffer, 这个buffer会干扰session恢复 221 | (setq-default comment-style 'indent) ;设定自动缩进的注释风格 222 | (setq default-major-mode 'text-mode) ;设置默认地主模式为TEXT模式 223 | (setq split-width-threshold nil) ;分屏的时候使用上下分屏 224 | (setq inhibit-compacting-font-caches t) ;使用字体缓存,避免卡顿 225 | (setq confirm-kill-processes nil) ;退出自动杀掉进程 226 | (setq async-bytecomp-allowed-packages nil) ;避免magit报错 227 | (setq profiler-report-cpu-line-format ;让 profiler-report 第一列宽一点 228 | '((100 left) 229 | (24 right ((19 right) 230 | (5 right))))) 231 | (setq profiler-report-memory-line-format 232 | '((100 left) 233 | (19 right ((14 right profiler-format-number) 234 | (5 right))))) 235 | 236 | ;; (add-hook 'find-file-hook 'highlight-parentheses-mode t) ;增强的括号高亮 237 | (setq ad-redefinition-action 'accept) ;不要烦人的 redefine warning 238 | #+end_src 239 | ** set vars 240 | I use the following file paths to manage all the files in Nowisemacs: 241 | #+begin_example 242 | emacs 243 | ├── 01-orgmode 244 | │   ├── org-remark 245 | │   └── xnotes 246 | ├── 02-binary-git/binary-files 247 | │   ├── 01-pictures 248 | │   ├── 02-searchable 249 | │   ├── 03-stardicts 250 | │   ├── 04-org-imagine 251 | │   └── 10-report-backup 252 | ├── 03-bibliography 253 | ├── 04-beancount 254 | ├── 05-excalidraw 255 | ├── 06-anki 256 | ├── 07-pyim 257 | │   └── dcache 258 | ├── 08-keys 259 | └── 09-scripts 260 | #+end_example 261 | 1. All files and folders except =02-binary-git/binary-files= are managed under git control, and =binary-file= is managed under =rsync= or =restic=. 262 | 2. =01-orgmode= stores .org files, where =org-remark= is used to store remark notes, =xnote= is the default directory of =Denote= . 263 | 3. =02-binary-git/binary-files=, as its name, storing binary-fils. For example, =02-searchable= is used store the PDF of the literature 264 | and daily MS Office files, the meaning of searchable means that all files under this folder maybe searched or 265 | modified latter, and they should have nice naming specifications for convenience search. 266 | 267 | #+begin_src elisp 268 | (defvar nowis-config-file (expand-file-name "init.org" user-emacs-directory)) 269 | (defvar nowis-config-useful-tools (expand-file-name "useful-tools/" user-emacs-directory)) 270 | (defvar nowis-doc-emacs-dir (file-truename "~/Documents/emacs/")) 271 | (defvar nowis-gtd-dir (concat nowis-doc-emacs-dir "01-orgmode/xnotes/gtd")) 272 | (defvar nowis-bib-dir (concat nowis-doc-emacs-dir "03-bibliography/")) 273 | (defvar nowis-bib-pdf-dir (concat nowis-doc-emacs-dir "02-binary-git/binary-files/02-searchable/01-papers-markable/")) 274 | #+end_src 275 | * Package Management 276 | ** setup 277 | #+NAME: setup 278 | #+begin_src elisp 279 | (require 'setup) 280 | (setup-define :defer 281 | (lambda (features) 282 | `(run-with-idle-timer 2 nil 283 | (lambda () 284 | ,features))) 285 | :documentation "Delay loading the feature until a certain amount of idle time has passed." 286 | :repeatable t) 287 | (setup-define :load-after 288 | (lambda (features &rest body) 289 | (let ((body `(progn 290 | (require ',(setup-get 'feature)) 291 | ,@body))) 292 | (dolist (feature (if (listp features) 293 | (nreverse features) 294 | (list features))) 295 | (setq body `(with-eval-after-load ',feature ,body))) 296 | body)) 297 | :documentation "Load the current feature after FEATURES." 298 | :indent 1) 299 | (setup-define :autoload 300 | (lambda (func) 301 | (let ((fn (if (memq (car-safe func) '(quote function)) 302 | (cadr func) 303 | func))) 304 | `(unless (fboundp (quote ,fn)) 305 | (autoload (function ,fn) ,(symbol-name (setup-get 'feature)) nil t)))) 306 | :documentation "Autoload COMMAND if not already bound." 307 | :repeatable t 308 | :signature '(FUNC ...)) 309 | #+end_src 310 | ** other macros 311 | #+begin_src elisp 312 | (defmacro with-idle-delay (secs &rest body) 313 | "Emacs 启动并空闲 SECS 秒后执行 BODY,仅执行一次。" 314 | `(run-with-idle-timer 315 | ,secs nil 316 | (lambda () ,@body))) 317 | #+end_src 318 | * Keyboard Bindings 319 | I used to be a vim(evil) user, but now I use meow to manage all my keys. 320 | ** meow 321 | Maybe I should add a new state. 322 | #+name: meow 323 | #+begin_src elisp 324 | (setup meow 325 | (require 'meow) 326 | (setq meow-use-keypad-when-execute-kbd nil 327 | meow-expand-exclude-mode-list nil 328 | meow-use-clipboard t 329 | ;; meow-cursor-type-normal 'box 330 | ;; meow-cursor-type-insert '(bar . 1) 331 | meow-replace-state-name-list '((normal . "N") 332 | (motion . "M") 333 | (keypad . "K") 334 | (insert . "I") 335 | (beacon . "B")) 336 | meow-use-enhanced-selection-effect t 337 | meow-cheatsheet-layout meow-cheatsheet-layout-qwerty 338 | meow-keypad-start-keys '((?c . ?c) 339 | (?x . ?x)) 340 | meow-char-thing-table '((?\( . round) 341 | (?\) . round) 342 | (?\[ . square) 343 | (?\] . square) 344 | (?\{ . curly) 345 | (?\} . curly) 346 | (?\" . string) 347 | (?w . symbol) 348 | ;; (?w . window) 349 | (?b . buffer) 350 | (?p . paragraph) 351 | (?l . line) 352 | (?d . defun) 353 | (?s . sentence)) 354 | ) 355 | ;; motion keys 356 | (meow-motion-define-key '("j" . meow-next) 357 | '("J" . meow-next-expand) 358 | '("k" . meow-prev) 359 | '("K" . meow-prev-expand) 360 | '("h" . meow-left) 361 | '("H" . meow-left-expand) 362 | '("l" . meow-right) 363 | '("L" . meow-right-expand) 364 | '("v i" . meow-inner-of-thing) 365 | '("v a" . meow-bounds-of-thing) 366 | '("y" . meow-save) 367 | '("" . ignore) 368 | '("." . repeat) 369 | '("!" . kmacro-start-macro-or-insert-counter) 370 | '("@" . meow-end-or-call-kmacro) 371 | ) 372 | 373 | ;; normal keys 374 | (setq wrap-keymap 375 | (let ((map (make-keymap))) 376 | (suppress-keymap map) 377 | (dolist (k '("(" "[" "{" "<" "\"" "*")) 378 | (define-key map k #'insert-pair)) 379 | map 380 | )) 381 | 382 | (meow-normal-define-key '("0" . meow-expand-0) 383 | '("9" . meow-expand-9) 384 | '("8" . meow-expand-8) 385 | '("7" . meow-expand-7) 386 | '("6" . meow-expand-6) 387 | '("5" . meow-expand-5) 388 | '("4" . meow-expand-4) 389 | '("3" . meow-expand-3) 390 | '("2" . meow-expand-2) 391 | '("1" . meow-expand-1) 392 | 393 | '("a" . meow-vim-append) 394 | ;; '("A" . meow-append-vim) 395 | '("b" . meow-back-word) 396 | '("B" . meow-back-symbol) 397 | '("c c" . meow-change) 398 | '("d" . meow-kill) 399 | '("e" . meow-next-word) 400 | '("E" . meow-next-symbol) 401 | '("f" . meow-find) 402 | '("g" . g-extra-commands) 403 | '("G" . meow-grab) 404 | '("h" . meow-left) 405 | '("H" . meow-left-expand) 406 | '("i" . meow-insert) 407 | ;; '("I" . meow-insert-vim) 408 | '("j" . meow-next) 409 | '("J" . meow-next-expand) 410 | '("k" . meow-prev) 411 | '("K" . meow-prev-expand) 412 | '("l" . meow-right) 413 | '("L" . meow-right-expand) 414 | '("m" . consult-register-store) 415 | '("M" . meow-block) 416 | '("n" . meow-search) 417 | '("N" . meow-pop-selection);; 418 | 419 | '("o" . meow-open-below) 420 | '("O" . meow-open-above) 421 | '("p" . meow-yank) 422 | '("P" . meow-yank-pop);; 423 | '("q" . meow-quit) 424 | '("Q" . consult-goto-line) 425 | '("r" . meow-replace) 426 | '("R" . meow-swap-grab) 427 | '("s" . meow-line) 428 | '("S" . meow-kmacro-lines) ;; 429 | '("t" . meow-till) 430 | '("u" . meow-undo) 431 | '("U" . vundo) 432 | '("v v" . meow-visit) ;; 433 | '("V" . meow-kmacro-matches) ;; 434 | '("w" . meow-mark-word) 435 | '("W" . meow-mark-symbol) 436 | 437 | '("x" . meow-delete) 438 | '("X" . meow-backward-delete) 439 | '("y" . meow-save) 440 | ;; '("Y" . meow-sync-save) 441 | '("z a" . hs-toggle-hiding) 442 | '("z c" . hs-hide-block) 443 | '("z o" . hs-show-block) 444 | '("z m" . hs-hide-all) 445 | '("z r" . hs-show-all) 446 | '("z z" . recenter-top-bottom) 447 | 448 | '("v i" . meow-inner-of-thing) 449 | '("v a" . meow-bounds-of-thing) 450 | '("v =" . insert-equation) 451 | 452 | '("-" . negative-argument) 453 | '("=" . indent-region) 454 | '("(" . backward-sentence) 455 | '(")" . forward-sentence) 456 | '("{" . backward-paragraph) 457 | '("}" . forward-paragraph) 458 | '("]" . nowis-graphviz-symbol-with-label) 459 | ;; '("]" . (lambda() 460 | ;; (interactive) 461 | ;; (meow-bounds-of-thing ?\"))) 462 | (cons "\\" wrap-keymap) 463 | '(";" . meow-expand-1) 464 | ;; '(":" . async-shell-command) 465 | '("'" . consult-register-load) 466 | '("\"" . consult-register) 467 | '("," . meow-reverse) 468 | '("." . repeat) 469 | 470 | '("" . ignore) 471 | '("!" . kmacro-start-macro-or-insert-counter) 472 | '("@" . meow-end-or-call-kmacro) 473 | '("#" . embark-toggle-highlight) 474 | '("^" . meow-join) 475 | '("*" . embark-next-symbol) 476 | '("/" . isearch-forward)) 477 | (defun meow-vim-append () 478 | "Like vim, move to the end of selection, switch to INSERT state." 479 | (interactive) 480 | (if meow--temp-normal 481 | (progn 482 | (message "Quit temporary normal mode") 483 | (meow--switch-state 'motion)) 484 | (if (not (region-active-p)) 485 | (progn 486 | (when (and meow-use-cursor-position-hack 487 | (< (point) (point-max))) 488 | (forward-char 1)) 489 | (forward-char 1) 490 | ) 491 | (meow--direction-forward) 492 | (meow--cancel-selection)) 493 | (meow--switch-state 'insert))) 494 | (meow-global-mode 1) 495 | 496 | (defun toggle-between-meow-normal-motion() 497 | (interactive) 498 | (if meow-motion-mode (meow-normal-mode) (meow-motion-mode))) 499 | (global-set-key (kbd "M-\\") #'toggle-between-meow-normal-motion) 500 | ) 501 | #+end_src 502 | 503 | ** transient and related leader-map 504 | *** transient 505 | #+name: transient 506 | #+begin_src elisp 507 | (setup transient 508 | (require 'transient) 509 | (:with-map transient-base-map 510 | (:bind "" transient-quit-one))) 511 | #+end_src 512 | *** g in normal mode 513 | #+begin_src elisp 514 | (transient-define-prefix g-extra-commands() 515 | "Define notes leader-key maps" 516 | [["Code find" 517 | ("d" "find-definitions" (lambda () (interactive) (call-interactively (key-binding (kbd "M-."))))) 518 | ("D" "find-references" xref-find-references) 519 | ("i" "find-impl" eglot-find-implementation) 520 | ("s" "find-symbols" xref-find-apropos) 521 | ("o" "find-def-other-window" xref-find-definitions-other-window) 522 | ] 523 | ["Code action" 524 | ("a" "code-actions" eglot-code-actions) 525 | ("r" "rename" eglot-rename) 526 | ("f" "format-all-region" format-all-region) 527 | ("F" "format-all-buffer" format-all-buffer)] 528 | ["diagnostic" 529 | ("n" "jump-to-next-diagnostic" flymake-goto-next-error) 530 | ("N" "jump-to-prev-diagnostic" flymake-goto-prev-error) 531 | ("l" "list-diagnostics" consult-flymake) 532 | ] 533 | ["Navigate" 534 | ("m" "consult-mark" consult-mark) 535 | ] 536 | ["citre" 537 | ("c d" "citre-jump" citre-jump) 538 | ("c D" "citre-jump-to-reference" citre-jump-to-reference) 539 | ("c p" "citre-peek" citre-peek) 540 | ("c P" "citre-peek-reference" citre-peek-reference) 541 | ("c r" "citre-peek-restore" citre-peek-restore) 542 | ("c a" "citre-ace-peek" citre-ace-peek) 543 | ("c u" "update-tags-file" citre-update-this-tags-file) 544 | ("c s" "peek-save-session" citre-peek-save-session) 545 | ("c l" "peek-load-session" citre-peek-load-session) 546 | ] 547 | ]) 548 | #+end_src 549 | *** find-file 550 | #+begin_src elisp 551 | (transient-define-prefix file-leader-map() 552 | "Define leader-key map for file-related functions" 553 | [["config" 554 | ("p" "personal emacs config" (lambda() 555 | (interactive) 556 | (find-file nowis-config-file))) 557 | ("e" "emacs documents" (lambda() 558 | (interactive) 559 | (find-file nowis-doc-emacs-dir))) 560 | ("d" "dot files" (lambda() 561 | (interactive) 562 | (find-file "~/dotfiles"))) 563 | ] 564 | ["history" 565 | ("r" "recent file" consult-recent-file)]]) 566 | #+end_src 567 | *** lewis 568 | #+begin_src elisp 569 | (transient-define-prefix lewis-leader-map() 570 | "Define leader-key map for special functions" 571 | [ 572 | ["Imenu" 573 | ("l" "Imenu list smart toggle" imenu-list-smart-toggle) 574 | ("o" "org mode sidebar" nowis-org-toggle-sidebar) 575 | ;; ("L" "Boxy imenu" boxy-imenu) 576 | ] 577 | ["gptel" 578 | ("a" "aibo" gptel-aibo) 579 | ("i" "gptel-aibo-summon/insert" gptel-aibo-summon) 580 | ("r" "gptel-rewrite" gptel-rewrite) 581 | ("f" "gptel-file-add" gptel-add-file) 582 | ("q" "gptel-quick" gptel-quick) 583 | ] 584 | ]) 585 | #+end_src 586 | *** buffer 587 | #+begin_src elisp 588 | (transient-define-prefix buffer-leader-map() 589 | "Define leader-key map for buffer functions" 590 | [["Buffer" 591 | ("b" "consult-buffer" consult-buffer) ;; work with C-x b 592 | ("k" "kill-current-buffer" kill-current-buffer) 593 | ("l" "meow-last-buffer" meow-last-buffer) 594 | ("n" "next-buffer" next-buffer) 595 | ("p" "previous-buffer" previous-buffer) 596 | ("r" "revert-buffer" revert-buffer) 597 | ("c" "clean-buffer" clean-buffer-list) 598 | ("s" "scratch-buffer" scratch-buffer) 599 | ] 600 | ["Bookmark" 601 | ("j" "bookmark-jump" bookmark-jump) 602 | ("m" "bookmark-set" bookmark-set) 603 | ("M" "bookmark-delete" bookmark-delete)] 604 | ] 605 | ) 606 | #+end_src 607 | *** notes 608 | #+begin_src elisp 609 | (transient-define-prefix notes-leader-map() 610 | "Define leader-key map for notes functions" 611 | [["Roam" 612 | ("r f" "denote-open-or-create" denote-open-or-create) 613 | ("r j" "denote-journal" denote-journal-new-or-existing-entry) 614 | ("r s" "find-all-searchable" project-find-searchable-dir-files) 615 | ("r c" "calendar" calendar) 616 | ("r w" "week-target" my/denote-journal-this-week-major-tasks) 617 | ("r g" "project-find-gtd-dir-files" project-find-gtd-dir-files) 618 | ("r e" "find excalidraw" (lambda () 619 | (interactive) 620 | (let ((denote-directory org-excalidraw-default-directory)) 621 | (call-interactively #'denote-open-or-create) 622 | ))) 623 | ] 624 | ["bibtex" 625 | ("e" "ebib" ebib) 626 | ("b" "citar-open" citar-open) 627 | ] 628 | ["review cards" 629 | ("s" "org-srs" org-srs-transient-map) 630 | ] 631 | ["graph" 632 | ("g" "org-graphviz-mindmap" org-graphviz-mindmap-create) 633 | ] 634 | ["ladder" 635 | ("l c" "display current" org-ladder-display-current-status) 636 | ("l d" "show detailed" org-ladder-show-detailed-status) 637 | ("l f" "force update" org-ladder-force-refresh) 638 | ("l h" "history" org-ladder-show-history-review) 639 | ] 640 | ] 641 | ) 642 | #+end_src 643 | *** search 644 | #+begin_src elisp 645 | (transient-define-prefix search-leader-map() 646 | "Define leader-key map for search functions" 647 | [ 648 | ;; ["blink-search" 649 | ;; ("b" "blink-search" blink-search)] 650 | ["grep" 651 | ("d" "consult-rg-in-dir" lewis/ripgrep-search-other-dir) 652 | ("D" "consult-rg" consult-ripgrep) 653 | ("g" "rg" rg) 654 | ("n" "grep-notes" lewis/ripgrep-search-notes) 655 | ] 656 | ["find" 657 | ("f" "consult-fd-in-dir" lewis/find-file-other-dir) 658 | ("F" "consult-fd" consult-fd) 659 | ] 660 | ["built-in enhance" 661 | ("h" "history" consult-history) 662 | ("i" "imenu" consult-imenu) 663 | ("l" "keep-lines" consult-keep-lines) 664 | ("s" "line" consult-line)] 665 | ["web search" 666 | ("w" "webjump" webjump) 667 | ("a" "add bookmark" my/add-bookmark) 668 | ("b" "browse bookmark" my/consult-org-bookmarks) 669 | ] 670 | ]) 671 | #+end_src 672 | *** apps 673 | #+begin_src elisp 674 | (transient-define-prefix apps-leader-map() 675 | "Define leader-key map for apps functions" 676 | [["agenda" 677 | ("a" "org-agenda" org-agenda) 678 | ("c" "capture" org-capture) 679 | ("A" "archive" nowis-org-archive-subtree) 680 | ] 681 | 682 | ["shell" 683 | ;; ("i" "toggle-insert-cd" eat-toggle-insert-dir) 684 | ] 685 | ["others" 686 | ;; ("t" "org-pomodoro" org-pomodoro) 687 | ;; ("l" "app-launcher-run-app" app-launcher-run-app) 688 | ;; ("e" "elfeed" my-elfeed) 689 | ("r" "restart emacs" restart-emacs) 690 | ("w" "whisper" whisper-run) 691 | ] 692 | ]) 693 | #+end_src 694 | *** ui 695 | #+begin_src elisp 696 | (transient-define-prefix toggle-leader-map() 697 | "Define leader-key map for ui functions" 698 | [("v" "toggle-variable-pitch" variable-pitch-mode) 699 | ("d" "toggle-darkroom" darkroom-mode) 700 | ]) 701 | #+end_src 702 | *** tui-support 703 | #+begin_src elisp 704 | (unless (display-graphic-p) 705 | (xterm-mouse-mode 1) 706 | ) 707 | #+end_src 708 | **** clipetty 709 | #+begin_src elisp 710 | (setup clipetty 711 | (unless (display-graphic-p) 712 | (require 'clipetty) 713 | (global-clipetty-mode) 714 | ) 715 | ) 716 | #+end_src 717 | ** meow leader keybindings 718 | #+name: meow-leader-keys 719 | #+begin_src elisp 720 | ;; default 721 | (meow-leader-define-key 722 | ;; Use SPC (0-9) for digit arguments. 723 | '("1" . meow-digit-argument) 724 | '("2" . meow-digit-argument) 725 | '("3" . meow-digit-argument) 726 | '("4" . meow-digit-argument) 727 | '("5" . meow-digit-argument) 728 | '("6" . meow-digit-argument) 729 | '("7" . meow-digit-argument) 730 | '("8" . meow-digit-argument) 731 | '("9" . meow-digit-argument) 732 | '("0" . meow-digit-argument) 733 | '("/" . meow-keypad-describe-key) 734 | '("?" . meow-cheatsheet) 735 | 736 | ;; buffer 737 | ;; (meow-leader-define-key 738 | '("b" . buffer-leader-map) 739 | ;; lewisliu 740 | '("e" . lewis-leader-map) 741 | ;; search 742 | '("s" . search-leader-map) 743 | ;; apps 744 | '("a" . apps-leader-map) 745 | ;; file 746 | '("f" . file-leader-map) 747 | ;; notes 748 | '("n" . notes-leader-map) 749 | ;;w workspace 750 | '("TAB" . tabspaces-leader-map) 751 | ;; ;; org gtd 752 | ;; '("d" . org-gtd-leader-map) 753 | ;; ui 754 | '("t" . toggle-leader-map) 755 | ;; '("d" . dictionary-leader-map) 756 | 757 | ;; remark 758 | '("r m" . org-remark-mark) 759 | '("r l" . org-remark-mark-line) ; new in v1.3 760 | '("r o" . org-remark-open) 761 | '("r ]" . org-remark-view-next) 762 | '("r [" . org-remark-view-prev) 763 | '("r r" . org-remark-remove) 764 | '("r d" . org-remark-delete) 765 | ) 766 | #+end_src 767 | ** which-key 768 | #+name: which-key 769 | #+begin_src elisp 770 | (setup which-key 771 | (setq which-key-idle-delay 0.1) 772 | (which-key-mode) 773 | ) 774 | #+end_src 775 | ** electric 776 | #+begin_src elisp 777 | (setup elec-pair 778 | (electric-pair-mode)) 779 | #+end_src 780 | * Package Library 781 | ** dash 782 | #+begin_src elisp 783 | (setup dash) 784 | #+end_src 785 | ** s 786 | #+begin_src elisp 787 | (setup s) 788 | #+end_src 789 | ** f 790 | #+begin_src elisp 791 | (setup f) 792 | #+end_src 793 | * UI 794 | ** font 795 | #+name: font 796 | #+begin_src elisp 797 | (defun font-installed-p (font-name) 798 | "Check if font with FONT-NAME is available." 799 | (find-font (font-spec :name font-name))) 800 | 801 | ;; font size 802 | (if (eq system-type 'darwin) 803 | (defvar lewis-font-size 140) 804 | (defvar lewis-font-size 150)) 805 | 806 | ;; fixed font 807 | (setq lewis-fixed-font (cl-loop for font in '( 808 | "JetBrains Maple Mono" 809 | "Maple Mono NF CN" 810 | "Maple Mono SC NF" 811 | "Unifont" 812 | ;; "InconsolataGo QiHei NF" 813 | ;; "yaheiInconsolata" 814 | "JetBrainsMono Nerd Font" 815 | "JetBrains Mono" 816 | "Sarasa Mono SC Nerd" 817 | "Monaco" 818 | "Consolas" 819 | ) 820 | when (font-installed-p font) 821 | return font)) 822 | ;; variable font 823 | (setq lewis-variable-font (cl-loop for font in '( 824 | "IBM Plex Sans SC" 825 | "Noto Sans CJK SC" 826 | "Times" 827 | "Helvetica" 828 | "LXGW WenKai" 829 | "Maple UI" 830 | ;; "Source Han Sans SC VF" 831 | "Arial" 832 | "Times New Roman") 833 | when (font-installed-p font) 834 | return font)) 835 | 836 | ;; chinese font 837 | (setq lewis-chinese-font (cl-loop for font in '( 838 | "Maple Mono SC NF" 839 | "Unifont" 840 | "Sarasa Mono SC Nerd" 841 | "Microsoft Yahei") 842 | when (font-installed-p font) 843 | return font)) 844 | 845 | ;; symbol font 846 | (setq lewis-symbol-font (cl-loop for font in '("Symbols Nerd Font Mono" 847 | "Symbola" 848 | "Symbol" 849 | ) 850 | when (font-installed-p font) 851 | return font)) 852 | 853 | ;; mayby I should remove all this font-seting and use only default font 854 | (defun nowis-setup-fonts() 855 | "Setup fonts." 856 | (when (display-graphic-p) 857 | ;; Set default font 858 | (if lewis-fixed-font 859 | (progn 860 | (set-face-attribute 'default nil :family lewis-fixed-font :height lewis-font-size) 861 | ;; (set-face-attribute 'fixed-pitch nil :family lewis-fixed-font :height 1.0) 862 | )) 863 | 864 | ;; variable-pitch 865 | (if lewis-variable-font 866 | (set-face-attribute 'variable-pitch nil :family lewis-variable-font :height 1.0)) 867 | 868 | ;; Specify font for all unicode characters 869 | (if lewis-symbol-font 870 | (set-fontset-font t 'unicode lewis-symbol-font nil 'prepend)) 871 | 872 | ;; Specify font for Chinese characters 873 | ;; (if lewis-chinese-font 874 | ;; (set-fontset-font t '(#x4e00 . #x9fff) lewis-chinese-font)) 875 | ) 876 | ) 877 | 878 | (nowis-setup-fonts) 879 | #+end_src 880 | ** variable-pitch 881 | #+begin_src elisp 882 | (defun dynamic-change-line-spacing( &optional ARG) 883 | (if line-spacing (setq-local line-spacing nil) (setq-local line-spacing 0.5))) 884 | (advice-add 'variable-pitch-mode :after #'dynamic-change-line-spacing) 885 | #+end_src 886 | ** Theme 887 | *** modus-themes 888 | #+begin_src elisp 889 | (setup modus-themes 890 | (load-theme 'modus-vivendi t) 891 | ;; (setq modus-themes-common-palette-overrides 892 | ;; '((fg-heading-1 blue) 893 | ;; (fg-heading-2 fg-main) 894 | ;; (fg-heading-3 fg-main) 895 | ;; (fg-heading-4 fg-main) 896 | ;; (fg-heading-5 fg-main) 897 | ;; (fg-heading-6 fg-main) 898 | ;; (fg-heading-7 fg-main) 899 | ;; )) 900 | ) 901 | #+end_src 902 | *** ef-themes 903 | #+begin_src elisp 904 | (setup ef-themes) 905 | ;; (load-theme 'ef-trio-dark t) 906 | #+end_src 907 | ** line number 908 | #+begin_src elisp 909 | (setq line-number-display-limit large-file-warning-threshold) 910 | ;; only enable line number in some modes, borrowed from lazycat-emacs 911 | (dolist (hook (list 912 | 'prog-mode-hook 913 | ;;'org-mode-hook 914 | )) 915 | (add-hook hook (lambda () (display-line-numbers-mode)))) 916 | #+end_src 917 | ** nerd-icons 918 | #+begin_src elisp 919 | (setup nerd-icons) 920 | #+end_src 921 | ** nerd-icons-completion 922 | #+begin_src elisp 923 | (setup nerd-icons-completion 924 | (:hook-into vertico-mode marginalia-mode)) 925 | #+end_src 926 | ** rainbow-delimiters 927 | rainbow-delimiters is a "rainbow parentheses"-like mode which highlights delimiters such as parentheses, brackets or braces according to their depth. 928 | #+begin_src elisp 929 | (setup rainbow-delimiters 930 | (:hook-into prog-mode)) 931 | #+end_src 932 | ** diff-hl 933 | diff-hl-mode highlights uncommitted changes on the left side of the window (area also known as the "gutter"), allows you to jump between and revert them selectively. 934 | #+begin_src elisp 935 | (setup diff-hl 936 | (:hook-into prog-mode) 937 | (:when-loaded 938 | (diff-hl-margin-mode))) 939 | #+end_src 940 | ** fringe-mode 941 | #+begin_src elisp 942 | (setup fringe 943 | (if (featurep 'fringe) 944 | (fringe-mode 4) 945 | )) 946 | #+end_src 947 | ** emacs-dashboard 948 | #+begin_src elisp 949 | (setup dashboard 950 | (setq dashboard-items '((recents . 5) 951 | (bookmarks . 5) 952 | ) 953 | dashboard-icon-type 'nerd-icons 954 | dashboard-set-heading-icons t 955 | dashboard-set-file-icons t 956 | dashboard-center-content t 957 | dashboard-startup-banner (concat nowis-config-useful-tools "banner.txt") 958 | dashboard-set-init-info t) 959 | (dashboard-setup-startup-hook) 960 | ) 961 | #+end_src 962 | *** my-simple-start 963 | #+begin_src elisp 964 | (add-hook 'emacs-startup-hook 965 | (lambda () 966 | (message "Emacs loaded in %s" (emacs-init-time)))) 967 | #+end_src 968 | ** mini-echo 969 | #+begin_src elisp 970 | (setup hide-mode-line) 971 | (setup mini-echo 972 | ;; set default segments of long/short style 973 | (setq mini-echo-persistent-rule 974 | '(:long 975 | ("major-mode" "vcs" "time" "flymake" "process" 976 | "narrow" "profiler" "repeat" "buffer-size" "buffer-position" "buffer-percent" "shrink-path" "meow" "macro" "org-clock" "org-timer") 977 | ;; remove "selection-info" 978 | :short 979 | ("major-mode" "vcs" "time" "buffer-size" "buffer-position" "shrink-path" "meow" "macro" "org-clock" "org-timer"))) 980 | (setq mini-echo-separator " ") 981 | (setq mini-echo-window-divider-args '(t 2 2)) 982 | (setq mini-echo-update-interval 0.04) 983 | (unless (display-graphic-p) 984 | (setq mini-echo-right-padding 1) 985 | ) 986 | (mini-echo-mode -1) 987 | (:when-loaded 988 | (mini-echo-define-segment "org-clock" 989 | "Return org-clock." 990 | :fetch 991 | (when (and (fboundp 'org-clocking-p) 992 | (org-clocking-p) 993 | (not 994 | (and (boundp 'org-timer-mode-line-string) 995 | org-timer-start-time))) 996 | (let* ((time-string (org-clock-get-clock-string)) 997 | (time-face 'mini-echo-magenta)) 998 | (mini-echo-segment--print time-string time-face)))) 999 | 1000 | (mini-echo-define-segment "org-timer" 1001 | "Return org-clock." 1002 | :fetch 1003 | (when (and (boundp 'org-timer-mode-line-string) 1004 | org-timer-start-time) 1005 | (mini-echo-segment--print (concat "⏱" org-timer-mode-line-string) 'diff-added))) 1006 | (mini-echo-define-segment "time" 1007 | "Show the current time." 1008 | :fetch 1009 | (mini-echo-segment--print (format-time-string "%H:%M Day%u") 'mini-echo-green)) 1010 | (mini-echo-define-segment "buffer-percent" 1011 | "Return the current line as a percentage of total lines in buffer." 1012 | :fetch 1013 | (when-let* ((total-lines (line-number-at-pos (point-max))) 1014 | (current-line (line-number-at-pos (point))) 1015 | ((> total-lines 0))) 1016 | (format "%d%%" (/ (* current-line 100) total-lines)))) 1017 | (mini-echo-mode) 1018 | )) 1019 | #+end_src 1020 | ** hl-todo 1021 | #+begin_src elisp 1022 | (setup hl-todo 1023 | (global-hl-todo-mode)) 1024 | #+end_src 1025 | ** highlight line 1026 | *** hl-line 1027 | #+begin_src elisp 1028 | (setup hl-line 1029 | (keymap-global-set "C-l" #'nowis-recenter) 1030 | ;; Only highliht current buffer in current window 1031 | (setq hl-line-sticky-flag nil 1032 | global-hl-line-sticky-flag nil) 1033 | (global-hl-line-mode) 1034 | (:when-loaded 1035 | ;; update only 0.05 timer 1036 | (defvar my/global-hl-line-timer nil) 1037 | 1038 | (defun my/global-hl-line-highlight-debounce () 1039 | (when my/global-hl-line-timer 1040 | (cancel-timer my/global-hl-line-timer)) 1041 | (setq my/global-hl-line-timer 1042 | (run-with-idle-timer 0.05 nil #'global-hl-line-highlight))) 1043 | (remove-hook 'post-command-hook #'global-hl-line-highlight) 1044 | (add-hook 'post-command-hook #'my/global-hl-line-highlight-debounce) 1045 | 1046 | )) 1047 | (defun nowis-recenter () 1048 | (interactive) 1049 | (call-interactively 'recenter) 1050 | (pulsar-pulse-line)) 1051 | (defvar my-hl-line-timer nil) 1052 | #+end_src 1053 | *** pulsar 1054 | #+begin_src elisp 1055 | (setup pulsar 1056 | (pulsar-global-mode 1) 1057 | (setq pulsar-delay 0.015 1058 | pulsar-iterations 10) 1059 | (:when-loaded 1060 | (add-hook 'pulsar-pulse-functions 'ace-window))) 1061 | #+end_src 1062 | ** show-paren-mode 1063 | #+begin_src elisp 1064 | (setup paren 1065 | (setq show-paren-context-when-offscreen 'child-frame)) 1066 | #+end_src 1067 | * General Configuration 1068 | ** simple 1069 | #+begin_src elisp 1070 | (setup simple 1071 | ;; show line/column/filesize in modeline 1072 | (setq line-number-mode t 1073 | column-number-mode t 1074 | size-indication-mode t 1075 | kill-do-not-save-duplicates t 1076 | shell-command-prompt-show-cwd t 1077 | what-cursor-show-names t) 1078 | ;; (add-hook 'org-mode-hook 'turn-on-auto-fill) 1079 | 1080 | ;; (global-visual-line-mode) 1081 | (dolist (hook (list 1082 | 'prog-mode-hook 1083 | 'org-mode-hook 1084 | 'vterm-mode-hook 1085 | )) 1086 | (add-hook hook (lambda () (visual-line-mode)))) 1087 | ) 1088 | #+end_src 1089 | ** general builtin modes 1090 | #+begin_src elisp 1091 | (setup save-place 1092 | (save-place-mode) 1093 | ) 1094 | 1095 | (setup autorevert 1096 | (setq global-auto-revert-non-file-buffers t) 1097 | (global-auto-revert-mode t)); 当另一程序修改了文件时,让 Emacs 及时刷新 Buffer 1098 | 1099 | (setup frame 1100 | (blink-cursor-mode -1) ;指针不闪动 1101 | ) 1102 | 1103 | ;; (setup pixel-scroll 1104 | ;; (when (>= emacs-major-version 29) 1105 | ;; (pixel-scroll-precision-mode t))) 1106 | #+end_src 1107 | ** repeat-mode 1108 | #+begin_src elisp 1109 | (setup repeat 1110 | (repeat-mode)) 1111 | #+end_src 1112 | ** backup 1113 | *** auto-save 1114 | #+begin_src elisp 1115 | (setup auto-save 1116 | (setq auto-save-default nil 1117 | create-lockfiles nil 1118 | make-backup-files nil 1119 | auto-save-visited-interval 1) 1120 | (auto-save-visited-mode) 1121 | ) 1122 | #+end_src 1123 | *** savehist 1124 | #+begin_src elisp 1125 | (setup savehist 1126 | (setq history-length 100 1127 | history-delete-duplicates t 1128 | savehist-save-minibuffer-history t) 1129 | (savehist-mode)) 1130 | #+end_src 1131 | ** no-littering 1132 | #+begin_src elisp 1133 | (setup no-littering 1134 | (require 'no-littering) 1135 | ) 1136 | #+end_src 1137 | ** recentf 1138 | #+begin_src elisp 1139 | (setup recentf 1140 | (setq recentf-max-saved-items 100 1141 | recentf-exclude `("/tmp/" "/ssh:" ,(concat user-emacs-directory "lib/.*-autoloads\\.el\\'"))) 1142 | (add-to-list 'recentf-exclude no-littering-var-directory) 1143 | (add-to-list 'recentf-exclude no-littering-etc-directory) 1144 | (with-idle-delay 2 1145 | (recentf-mode)) 1146 | ) 1147 | #+end_src 1148 | ** 自动换行 1149 | #+begin_src elisp 1150 | (setq-default fill-column 100) 1151 | (setq word-wrap t) 1152 | (setq word-wrap-by-category t) 1153 | #+end_src 1154 | ** long-line 1155 | #+begin_src elisp 1156 | (setq-default bidi-display-reordering nil) 1157 | (setq bidi-inhibit-bpa t 1158 | long-line-threshold 1000 1159 | large-hscroll-threshold 1000 1160 | syntax-wholeline-max 1000) 1161 | #+end_src 1162 | ** TRAMP 1163 | #+begin_src elisp 1164 | (setq tramp-default-method "ssh") 1165 | #+end_src 1166 | ** Automatically clean whitespace 1167 | #+begin_src elisp 1168 | (setup ws-butler 1169 | (:hook-into text-mode prog-mode)) 1170 | #+end_src 1171 | ** vundo for undo history 1172 | #+begin_src elisp 1173 | (setup vundo 1174 | (setq undo-limit (* 64 1024 1024) 1175 | undo-strong-limit (* 96 1024 1024) 1176 | undo-outer-limit (* 960 1024 1024) 1177 | ) 1178 | (:bind "l" vundo-forward 1179 | "h" vundo-backward 1180 | "j" vundo-next 1181 | "k" vundo-previous)) 1182 | #+end_src 1183 | * Search 1184 | ** isearch 1185 | #+begin_src elisp 1186 | (setup isearch 1187 | (setq isearch-lazy-count t 1188 | ;; lazy-highlight-cleanup nil 1189 | ) 1190 | (:bind [remap isearch-delete-char] isearch-del-char) 1191 | (:when-loaded 1192 | (defvar isearch-repeat-map 1193 | (let ((map (make-sparse-keymap))) 1194 | (define-key map (kbd "s") #'isearch-repeat-forward) 1195 | (define-key map (kbd "r") #'isearch-repeat-backward) 1196 | map)) 1197 | (dolist (cmd '(isearch-repeat-forward isearch-repeat-backward)) 1198 | (put cmd 'repeat-map 'isearch-repeat-map)) 1199 | 1200 | )) 1201 | #+end_src 1202 | ** Consult Commands 1203 | *** consult 1204 | #+begin_src elisp 1205 | (setup consult 1206 | (keymap-global-set "C-x b" #'consult-buffer) 1207 | (setq register-preview-delay 0.1 1208 | register-preview-function #'consult-register-format 1209 | xref-show-xrefs-function #'consult-xref 1210 | xref-show-definitions-function #'consult-xref 1211 | consult-project-root-function #'(lambda () 1212 | (when-let (project (project-current)) 1213 | (car (project-roots project))))) 1214 | (:with-map minibuffer-local-map 1215 | (:bind "C-r" consult-history))) 1216 | #+end_src 1217 | *** search other cwd 1218 | #+begin_src elisp 1219 | (defun lewis/ripgrep-search-other-dir() 1220 | (interactive) 1221 | (let ((current-prefix-arg '(-1))) 1222 | (call-interactively 'consult-ripgrep))) 1223 | 1224 | (defun lewis/ripgrep-search-notes() 1225 | (interactive) 1226 | (consult-ripgrep (concat nowis-doc-emacs-dir "01-orgmode"))) 1227 | 1228 | (defun lewis/find-file-other-dir() 1229 | (interactive) 1230 | (let ((current-prefix-arg '(-1))) 1231 | (call-interactively 'consult-fd))) 1232 | #+end_src 1233 | *** consult-dir 1234 | #+begin_src elisp 1235 | (setup consult-dir 1236 | (define-key global-map (kbd "C-x C-d") #'consult-dir) 1237 | (define-key minibuffer-local-completion-map (kbd "C-x C-d") #'consult-dir) 1238 | (:when-loaded 1239 | 1240 | ;; add support for zoxide 1241 | (setq consult-dir-default-command #'consult-dir-dired) 1242 | 1243 | (defun consult-dir--zoxide-dirs () 1244 | "Return list of zoxide dirs." 1245 | (split-string (shell-command-to-string "zoxide query -l") "\n" t)) 1246 | 1247 | (defvar consult-dir--source-zoxide 1248 | `(:name "zoxide" 1249 | :narrow ?z 1250 | :category file 1251 | :face consult-file 1252 | :history file-name-history 1253 | :enabled ,(lambda () (executable-find "zoxide")) 1254 | :items ,#'consult-dir--zoxide-dirs) 1255 | "zoxide directory source for `consult-dir'.") 1256 | 1257 | (add-to-list 'consult-dir-sources 'consult-dir--source-zoxide t) 1258 | )) 1259 | #+end_src 1260 | ** rg.el 1261 | #+begin_src elisp 1262 | (setup rg) 1263 | #+end_src 1264 | * 补全 1265 | ** Completions with Vertico 1266 | #+name: vertico 1267 | #+begin_src elisp 1268 | (setq vertico-cycle t) 1269 | (setup vertico 1270 | (:with-map vertico-map 1271 | (:bind [backspace] vertico-directory-delete-char 1272 | "DEL" vertico-directory-delete-char 1273 | )) 1274 | (vertico-mode)) 1275 | #+end_src 1276 | ** Orderless and pinyinlib 1277 | #+begin_src elisp 1278 | (setup orderless 1279 | (setq completion-styles '(orderless basic) 1280 | completion-category-defaults nil 1281 | completion-category-overrides '((file (styles partial-completion))) 1282 | completion-pcm-leading-wildcard t 1283 | ) 1284 | (:when-loaded 1285 | (require 'pinyinlib) 1286 | (defun completion--regex-pinyin (str) 1287 | (orderless-regexp (pinyinlib-build-regexp-string str))) 1288 | (add-to-list 'orderless-matching-styles 'completion--regex-pinyin) 1289 | )) 1290 | #+end_src 1291 | ** Marginalia 1292 | #+begin_src elisp 1293 | (setup marginalia 1294 | (:hook-into after-init)) 1295 | #+end_src 1296 | ** embark 1297 | should be check after reading the embark.el manual 1298 | #+begin_src elisp 1299 | (setup embark-consult 1300 | (add-hook 'embark-collect-mode-hook #'consult-preview-at-point-mode)) 1301 | 1302 | (setup embark 1303 | (:also-load embark-consult) 1304 | (:autoload embark-toggle-highlight) 1305 | (setq prefix-help-command #'embark-prefix-help-command) 1306 | (keymap-global-set "C-S-a" #'embark-act)) 1307 | 1308 | (setup wgrep) 1309 | #+end_src 1310 | ** yasnippet 1311 | #+begin_src elisp 1312 | (setup yasnippet 1313 | (keymap-global-set "M-*" #'yas-insert-snippet) 1314 | (setq yas-snippet-dirs (list (concat nowis-config-useful-tools "snippets"))) 1315 | (with-idle-delay 2 1316 | (yas-global-mode)) 1317 | ) 1318 | #+end_src 1319 | * Window Management 1320 | ** window 1321 | #+begin_src elisp 1322 | (setup window 1323 | (setq quit-restore-window-no-switch t) 1324 | ) 1325 | #+end_src 1326 | ** winner-mode 1327 | #+name: winner-mode 1328 | #+begin_src elisp 1329 | (setup winner 1330 | (winner-mode t) 1331 | ) 1332 | #+end_src 1333 | ** popper 1334 | Popper is a minor-mode to tame the flood of ephemeral windows Emacs produces, while still keeping them within arm’s reach. 1335 | #+begin_src elisp 1336 | (setup popper 1337 | (setq popper-reference-buffers '("\\*Messages\\*" 1338 | "Output\\*$" 1339 | "\\*Async Shell Command\\*" 1340 | "\\*Org Clock Reminder\\*" 1341 | "gt-result" 1342 | help-mode 1343 | helpful-mode 1344 | compilation-mode 1345 | youdao-dictionary-mode) 1346 | popper-window-height 0.33 1347 | ) 1348 | (keymap-global-set "M-~" #'popper-toggle) 1349 | (keymap-global-set "C-M-`" #'popper-toggle-type) 1350 | (popper-mode +1) 1351 | (popper-echo-mode +1)) 1352 | #+end_src 1353 | ** Move 1354 | *** avy 1355 | Jump anywhere in the world 1356 | #+begin_src elisp 1357 | (setup avy 1358 | (keymap-global-set "M-j" #'avy-goto-char-timer) 1359 | ;; (setq avy-keys (number-sequence ?1 ?9)) 1360 | (:when-loaded 1361 | (defun avy-action-embark (pt) 1362 | (unwind-protect 1363 | (save-excursion 1364 | (goto-char pt) 1365 | (embark-act)) 1366 | (select-window 1367 | (cdr (ring-ref avy-ring 0)))) 1368 | t) 1369 | 1370 | (setf (alist-get ?. avy-dispatch-alist) 'avy-action-embark) 1371 | (define-key isearch-mode-map (kbd "M-j") 'avy-isearch) 1372 | )) 1373 | #+end_src 1374 | *** bookmark 1375 | #+begin_src elisp 1376 | (setq bookmark-default-file (concat nowis-doc-emacs-dir "bookmarks")) 1377 | #+end_src 1378 | *** windmove 1379 | #+begin_src elisp 1380 | (setup windmove 1381 | (transient-define-prefix windmove-transient-keybindings() 1382 | "Define windmove maps" 1383 | [[("h" "left" windmove-left :transient t) 1384 | ("H" "swap-left" windmove-swap-states-left :transient t)] 1385 | [("j" "down" windmove-down :transient t) 1386 | ("J" "swap-down" windmove-swap-states-down :transient t)] 1387 | [("k" "up" windmove-up :transient t) 1388 | ("K" "swap-up" windmove-swap-states-up :transient t)] 1389 | [("l" "right" windmove-right :transient t) 1390 | ("L" "swap-right" windmove-swap-states-right :transient t)] 1391 | ]) 1392 | (keymap-global-set "C-x O" #'windmove-transient-keybindings) 1393 | ) 1394 | 1395 | #+end_src 1396 | *** ace-window 1397 | #+begin_src elisp 1398 | (setup ace-window 1399 | (keymap-global-set "M-o" #'ace-window)) 1400 | (setq aw-keys '(?a ?s ?d ?f ?g ?h ?j ?k ?l) 1401 | aw-scope 'frame 1402 | ) 1403 | #+end_src 1404 | * ibuffer 1405 | ** ibuffer 1406 | #+name: ibuffer 1407 | #+begin_src elisp 1408 | (setup ibuffer 1409 | (global-set-key [remap list-buffers] #'ibuffer)) 1410 | #+end_src 1411 | * Input 1412 | ** posframe 1413 | #+begin_src elisp 1414 | (setup posframe) 1415 | #+end_src 1416 | ** rime 1417 | #+begin_src elisp 1418 | (setq default-input-method "rime") 1419 | (with-eval-after-load 'rime 1420 | (defun my/rime-disable-predicates () 1421 | (if (derived-mode-p 'eat-mode) 1422 | ;; 只在 eat buffer 下,禁用 predicates 约束,rime 全时可用 1423 | '(meow-normal-mode-p 1424 | meow-motion-mode-p 1425 | meow-keypad-mode-p 1426 | rime-predicate-after-alphabet-char-p 1427 | rime-predicate-current-input-punctuation-p 1428 | rime-predicate-current-uppercase-letter-p 1429 | rime-predicate-space-after-cc-p 1430 | ) 1431 | ;; 其他 buffer 用你原来的 predicate 约束 1432 | '(meow-normal-mode-p 1433 | meow-motion-mode-p 1434 | meow-keypad-mode-p 1435 | rime-predicate-prog-in-code-p 1436 | rime-predicate-punctuation-line-begin-p ;;在行首要输入符号时 1437 | rime-predicate-after-alphabet-char-p ;;在英文字符串之后(必须为以字母开头的英文字符串) 1438 | rime-predicate-current-input-punctuation-p ;;当要输入的是符号时 1439 | ;; rime-predicate-after-ascii-char-p ;;任意英文字符后 ,enable this to use with slot-number for persistent assignment.") 1652 | 1653 | (defun eat-cycle--get-buffers () 1654 | "Return live eat buffers sorted by assigned slot." 1655 | (let ((bufs (seq-filter (lambda (b) 1656 | (and (buffer-live-p b) 1657 | (eq 'eat-mode (buffer-local-value 'major-mode b)))) 1658 | (buffer-list)))) 1659 | ;; Clean dead buffers from registry 1660 | (maphash (lambda (name _) 1661 | (unless (get-buffer name) 1662 | (remhash name eat-cycle--slots))) 1663 | eat-cycle--slots) 1664 | ;; Sort by slot number 1665 | (sort bufs (lambda (a b) 1666 | (< (or (gethash (buffer-name a) eat-cycle--slots) 999) 1667 | (or (gethash (buffer-name b) eat-cycle--slots) 999)))))) 1668 | 1669 | (defun eat-cycle--ensure-slot (buffer) 1670 | "Ensure buffer has a slot assigned, return (slot . buffer)." 1671 | (let* ((name (buffer-name buffer)) 1672 | (slot (gethash name eat-cycle--slots))) 1673 | (unless slot 1674 | ;; Find first free slot 1675 | (let ((used (hash-table-values eat-cycle--slots))) 1676 | (setq slot (cl-loop for i from 0 below (length eat-cycle-keys) 1677 | unless (memq i used) return i))) 1678 | (when slot (puthash name slot eat-cycle--slots))) 1679 | (when slot (cons slot buffer)))) 1680 | 1681 | ;;;###autoload 1682 | (defun eat-cycle () 1683 | "Cycle through eat buffers with persistent slot numbers." 1684 | (interactive) 1685 | (let* ((buffers (eat-cycle--get-buffers)) 1686 | (slots (delq nil (mapcar #'eat-cycle--ensure-slot buffers))) 1687 | (current (current-buffer))) 1688 | (cond 1689 | ((null buffers) (message "No eat buffers")) 1690 | ((= 1 (length buffers)) (switch-to-buffer (car buffers))) 1691 | (t 1692 | (unless (memq current (mapcar #'cdr slots)) 1693 | (switch-to-buffer (cdar slots))) 1694 | ;; Show slots 1695 | (message "Eat: %s" 1696 | (mapconcat (lambda (s) 1697 | (let ((idx (1+ (car s))) 1698 | (buf (cdr s))) 1699 | (if (eq buf (current-buffer)) 1700 | (propertize (format "[%d:%s]" idx (buffer-name buf)) 1701 | 'face '(:foreground "green" :weight bold)) 1702 | (format " %d:%s " idx (buffer-name buf))))) 1703 | slots " ")) 1704 | ;; Setup transient map 1705 | (set-transient-map 1706 | (let ((map (make-sparse-keymap))) 1707 | (dolist (s slots) 1708 | (let* ((slot-idx (car s)) 1709 | (target-buf (cdr s))) ; 使用 let* 正确捕获变量 1710 | (define-key map (kbd (nth slot-idx eat-cycle-keys)) 1711 | `(lambda () 1712 | (interactive) 1713 | (switch-to-buffer ,target-buf) 1714 | (eat-cycle))))) 1715 | map)))))) 1716 | #+end_src 1717 | ** vterm 1718 | #+begin_src elisp 1719 | (defun meomacs-vterm-meow-setup() 1720 | (add-hook 'meow-normal-mode-hook 'vterm-copy-mode nil t) 1721 | (add-hook 'meow-insert-mode-hook (lambda () (vterm-copy-mode -1)) nil t)) 1722 | 1723 | (with-eval-after-load "meow" 1724 | (with-eval-after-load "vterm" 1725 | (keymap-set vterm-mode-map "C-S-v" 'vterm-yank) 1726 | (define-key vterm-mode-map (kbd "C-\\") nil) 1727 | (add-hook 'vterm-mode-hook 'meomacs-vterm-meow-setup))) 1728 | 1729 | (setup vterm 1730 | (keymap-global-set "M-`" #'vterm-toggle-window) 1731 | 1732 | (:when-loaded 1733 | (add-to-list 'display-buffer-alist 1734 | '((lambda (buffer-or-name _) 1735 | (let ((buffer (get-buffer buffer-or-name))) 1736 | (with-current-buffer buffer 1737 | (or (equal major-mode 'vterm-mode) 1738 | (string-prefix-p "*vterm" (buffer-name buffer)))))) 1739 | (display-buffer-reuse-window display-buffer-at-bottom) 1740 | (reusable-frames . visible) 1741 | (window-height . 0.3)))) 1742 | 1743 | (defun vterm-toggle-window() 1744 | "Toggle vterm buffer window." 1745 | (interactive) 1746 | (let ((vterm-win (seq-find (lambda (w) 1747 | (eq 'vterm-mode (buffer-local-value 'major-mode (window-buffer w)))) 1748 | (window-list)))) 1749 | (if vterm-win 1750 | (delete-window vterm-win) 1751 | (if-let ((buf (car (vterm-cycle--get-buffers)))) 1752 | (progn (pop-to-buffer buf) (vterm-cycle)) 1753 | (unless (featurep 'vterm) (require 'vterm)) 1754 | (vterm) 1755 | (vterm-cycle))))) 1756 | 1757 | (defvar vterm-cycle-keys '("M-1" "M-2" "M-3" "M-4" "M-5" "M-6" "M-7" "M-8" "M-9")) 1758 | (defvar vterm-cycle--slots (make-hash-table :test 'equal) 1759 | "Maps buffer-name -> slot-number for persistent assignment.") 1760 | 1761 | (defun vterm-cycle--get-buffers () 1762 | "Return live vterm buffers sorted by assigned slot." 1763 | (let ((bufs (seq-filter (lambda (b) 1764 | (and (buffer-live-p b) 1765 | (eq 'vterm-mode (buffer-local-value 'major-mode b)))) 1766 | (buffer-list)))) 1767 | ;; Clean dead buffers from registry 1768 | (maphash (lambda (name _) 1769 | (unless (get-buffer name) 1770 | (remhash name vterm-cycle--slots))) 1771 | vterm-cycle--slots) 1772 | ;; Sort by slot number 1773 | (sort bufs (lambda (a b) 1774 | (< (or (gethash (buffer-name a) vterm-cycle--slots) 999) 1775 | (or (gethash (buffer-name b) vterm-cycle--slots) 999)))))) 1776 | 1777 | (defun vterm-cycle--ensure-slot (buffer) 1778 | "Ensure buffer has a slot assigned, return (slot . buffer)." 1779 | (let* ((name (buffer-name buffer)) 1780 | (slot (gethash name vterm-cycle--slots))) 1781 | (unless slot 1782 | ;; Find first free slot 1783 | (let ((used (hash-table-values vterm-cycle--slots))) 1784 | (setq slot (cl-loop for i from 0 below (length vterm-cycle-keys) 1785 | unless (memq i used) return i))) 1786 | (when slot (puthash name slot vterm-cycle--slots))) 1787 | (when slot (cons slot buffer)))) 1788 | 1789 | ;;;###autoload 1790 | (defun vterm-cycle () 1791 | "Cycle through vterm buffers with persistent slot numbers." 1792 | (interactive) 1793 | (let* ((buffers (vterm-cycle--get-buffers)) 1794 | (slots (delq nil (mapcar #'vterm-cycle--ensure-slot buffers))) 1795 | (current (current-buffer))) 1796 | (cond 1797 | ((null buffers) (message "No vterm buffers")) 1798 | ((= 1 (length buffers)) (switch-to-buffer (car buffers))) 1799 | (t 1800 | (unless (memq current (mapcar #'cdr slots)) 1801 | (switch-to-buffer (cdar slots))) 1802 | ;; Show slots 1803 | (message "Vterm: %s" 1804 | (mapconcat (lambda (s) 1805 | (let ((idx (1+ (car s))) 1806 | (buf (cdr s))) 1807 | (if (eq buf (current-buffer)) 1808 | (propertize (format "[%d:%s]" idx (buffer-name buf)) 1809 | 'face '(:foreground "green" :weight bold)) 1810 | (format " %d:%s " idx (buffer-name buf))))) 1811 | slots " ")) 1812 | ;; Setup transient map 1813 | (set-transient-map 1814 | (let ((map (make-sparse-keymap))) 1815 | (dolist (s slots) 1816 | (let* ((slot-idx (car s)) 1817 | (target-buf (cdr s))) 1818 | (define-key map (kbd (nth slot-idx vterm-cycle-keys)) 1819 | `(lambda () 1820 | (interactive) 1821 | (switch-to-buffer ,target-buf) 1822 | (vterm-cycle))))) 1823 | map))))))) 1824 | #+end_src 1825 | * git 1826 | ** magit 1827 | #+begin_src elisp 1828 | (setup with-editor) 1829 | (setup llama) 1830 | (setup cond-let) 1831 | (setup magit) 1832 | #+end_src 1833 | ** ediff 1834 | #+begin_src elisp 1835 | (setup ediff 1836 | (setq ediff-split-window-function 'split-window-horizontally 1837 | ediff-window-setup-function 'ediff-setup-windows-plain) 1838 | ;; restore windows Configuration after ediff 1839 | (add-hook 'ediff-before-setup-hook #'ediff-save-window-conf) 1840 | (add-hook 'ediff-quit-hook #'ediff-restore-window-conf) 1841 | (:when-loaded 1842 | (defvar local-ediff-saved-window-conf nil) 1843 | (defun ediff-save-window-conf () 1844 | (setq local-ediff-saved-window-conf (current-window-configuration))) 1845 | (defun ediff-restore-window-conf () 1846 | (when (window-configuration-p local-ediff-saved-window-conf) 1847 | (set-window-configuration local-ediff-saved-window-conf))) 1848 | )) 1849 | #+end_src 1850 | * Program 1851 | ** Language 1852 | *** elisp 1853 | #+begin_src elisp 1854 | (setq elisp-fontify-semantically t) 1855 | #+end_src 1856 | **** helpful 1857 | #+begin_src elisp 1858 | (setup elisp-refs) 1859 | (setup helpful 1860 | (keymap-global-set "C-h f" #'helpful-callable) 1861 | (keymap-global-set "C-h v" #'helpful-variable) 1862 | (keymap-global-set "C-h k" #'helpful-key) 1863 | (keymap-global-set "C-c C-d" #'helpful-at-point) 1864 | (keymap-global-set "C-h F" #'helpful-function) 1865 | (keymap-global-set "C-h C" #'helpful-command)) 1866 | #+end_src 1867 | **** elisp-demos 1868 | #+begin_src elisp 1869 | (setup elisp-demos 1870 | (advice-add 'helpful-update :after #'elisp-demos-advice-helpful-update)) 1871 | #+end_src 1872 | *** graphviz-dot-mode 1873 | #+begin_src elisp 1874 | (setup graphviz-dot-mode 1875 | (add-to-list 'auto-mode-alist '("\\.dot\\'" . graphviz-dot-mode)) 1876 | (setq graphviz-dot-indent-width 4) 1877 | (setq nowis-graphviz-current-num 0) 1878 | (defun nowis-graphviz-symbol-with-label () 1879 | "Wrap the current symbol with [label=\"symbol\"]." 1880 | (interactive) 1881 | (let ((symbol (thing-at-point 'symbol))) 1882 | (when symbol 1883 | (delete-region (beginning-of-thing 'symbol) (end-of-thing 'symbol)) 1884 | (insert (format "%s [label=\"%s\"]" nowis-graphviz-current-num symbol)) 1885 | (setq nowis-graphviz-current-num (1+ nowis-graphviz-current-num)) 1886 | ))) 1887 | (defun nowis-graphviz-reset-number () 1888 | "Reset number to 0" 1889 | (interactive) 1890 | (setq nowis-graphviz-current-num 0)) 1891 | ) 1892 | #+end_src 1893 | *** plantuml 1894 | This Emacs tool use plantuml to generate images for org, json, yaml files. 1895 | #+begin_src elisp 1896 | ;; download plantuml jar 1897 | (setq plantuml-jar-path (concat no-littering-var-directory "plantuml.jar")) 1898 | (defun plantuml-download-jar () 1899 | "Download the latest PlantUML JAR file and install it into `plantuml-jar-path'." 1900 | (interactive) 1901 | (if (y-or-n-p (format "Download the latest PlantUML JAR file into %s? " plantuml-jar-path)) 1902 | (if (or (not (file-exists-p plantuml-jar-path)) 1903 | (y-or-n-p (format "The PlantUML jar file already exists at %s, overwrite? " plantuml-jar-path))) 1904 | (with-current-buffer (url-retrieve-synchronously "https://search.maven.org/solrsearch/select?q=g:net.sourceforge.plantuml+AND+a:plantuml&core=gav&start=0&rows=1&wt=xml") 1905 | (mkdir (file-name-directory plantuml-jar-path) t) 1906 | (let* ((parse-tree (xml-parse-region)) 1907 | (doc (->> parse-tree 1908 | (assq 'response) 1909 | (assq 'result) 1910 | (assq 'doc))) 1911 | (strs (xml-get-children doc 'str)) 1912 | (version (->> strs 1913 | (--filter (string-equal "v" (xml-get-attribute it 'name))) 1914 | (car) 1915 | (xml-node-children) 1916 | (car)))) 1917 | (message (concat "Downloading PlantUML v" version " into " plantuml-jar-path)) 1918 | (url-copy-file (format "https://search.maven.org/remotecontent?filepath=net/sourceforge/plantuml/plantuml/%s/plantuml-%s.jar" version version) plantuml-jar-path t) 1919 | (kill-buffer))) 1920 | (message "Aborted.")) 1921 | (message "Aborted."))) 1922 | #+end_src 1923 | *** beancount 1924 | Emacs major-mode to work with Beancount ledger files 1925 | #+begin_src elisp 1926 | (setup beancount 1927 | (:match-file "\\.beancount\\'")) 1928 | #+end_src 1929 | *** latex 1930 | **** basic 1931 | #+begin_src elisp 1932 | ;; (setup auctex) 1933 | (setup cdlatex) 1934 | #+end_src 1935 | **** org-elp 1936 | #+begin_src elisp 1937 | (setup org-elp 1938 | (setq org-elp-idle-time 1)) 1939 | #+end_src 1940 | *** python 1941 | **** python 1942 | #+begin_src elisp 1943 | (setup python 1944 | (:with-hook inferior-python-mode-hook 1945 | (:hook (lambda () 1946 | (process-query-on-exit-flag 1947 | (get-process "Python"))))) 1948 | (:when-loaded 1949 | (when (and (executable-find "python3") 1950 | (string= python-shell-interpreter "python")) 1951 | (setq python-shell-interpreter "python3")) 1952 | (with-eval-after-load 'exec-path-from-shell 1953 | (exec-path-from-shell-copy-env "PYTHONPATH")) 1954 | )) 1955 | #+end_src 1956 | *** scheme 1957 | #+begin_src elisp 1958 | (setup geiser) 1959 | (setup geiser-guile) 1960 | #+end_src 1961 | *** common lisp slime 1962 | #+begin_src elisp :tangle no 1963 | (setup slime 1964 | (setq inferior-lisp-program "sbcl")) 1965 | #+end_src 1966 | *** cc-mode 1967 | #+begin_src emacs-lisp 1968 | (setup cc-mode 1969 | (setq c-basic-offset 4)) 1970 | 1971 | (setup hideif 1972 | (setq hide-ifdef-shadow t 1973 | hide-ifdef-initially t) 1974 | (:with-feature hide-ifdef-mode 1975 | (:hook-into c-mode c++-mode))) 1976 | #+end_src 1977 | *** lua-mode 1978 | #+begin_src elisp 1979 | (setup lua-mode) 1980 | #+end_src 1981 | *** cmake-mode 1982 | #+begin_src elisp 1983 | (setup cmake-mode) 1984 | #+end_src 1985 | *** csv-mode 1986 | #+begin_src elisp 1987 | (setup csv-mode) 1988 | #+end_src 1989 | ** Useful programing tools 1990 | *** xref related 1991 | **** xref 1992 | #+begin_src elisp 1993 | (setup xref 1994 | (setq xref-search-program (cond 1995 | ((executable-find "rg") 'ripgrep) 1996 | (t 'grep)) 1997 | xref-history-storage #'xref-window-local-history) 1998 | (:autoload xref-push-marker-stack)) ;; autoload this command for jump-back 1999 | #+end_src 2000 | **** xref jump back 2001 | borrowed from citre, now you can always jump-back use "M-," after any jump in the list. 2002 | #+begin_src elisp 2003 | (defun my--push-point-to-xref-marker-stack (&rest r) 2004 | (xref-push-marker-stack (point-marker))) ;; must autoload this command in xref 2005 | (dolist (func '(find-function 2006 | consult-imenu 2007 | consult-ripgrep 2008 | consult-line 2009 | consult-find 2010 | find-file 2011 | blink-search 2012 | citre-jump 2013 | consult-goto-line 2014 | isearch-forward)) 2015 | (if (fboundp func) 2016 | (advice-add func :before 'my--push-point-to-xref-marker-stack))) 2017 | #+end_src 2018 | *** UI 2019 | **** electric-pair 2020 | #+begin_src elisp 2021 | (setup elec-pair 2022 | (electric-pair-mode)) 2023 | #+end_src 2024 | **** indent-bars 2025 | #+begin_src elisp 2026 | (setup indent-bars 2027 | (:hook-into prog-mode) 2028 | ) 2029 | #+end_src 2030 | **** breadcrumb 2031 | #+begin_src elisp 2032 | (setup breadcrumb 2033 | (setq breadcrumb-idle-time 2 2034 | breadcrumb-imenu-crumb-separator "  " 2035 | breadcrumb-imenu-max-length 0.6 2036 | ) 2037 | (breadcrumb-mode) 2038 | ) 2039 | #+end_src 2040 | *** treesit tools 2041 | **** treesit 2042 | #+begin_src elisp 2043 | (setup treesit 2044 | (setq treesit-font-lock-level 4)) 2045 | #+end_src 2046 | **** treesit-auto 2047 | #+begin_src elisp 2048 | (setup treesit-auto 2049 | (setq treesit-auto-install t 2050 | treesit-auto-langs '(python c cpp json org verilog cmake bash vhdl lua)) 2051 | (if (treesit-available-p) 2052 | (require 'treesit-auto)) 2053 | (:when-loaded 2054 | (global-treesit-auto-mode) 2055 | ) 2056 | ) 2057 | #+end_src 2058 | *** Complete 2059 | **** corfu related 2060 | ***** corfu 2061 | #+begin_src elisp 2062 | (defun corfu-enable-in-minibuffer () 2063 | "Enable Corfu in the minibuffer." 2064 | (when (local-variable-p 'completion-at-point-functions) 2065 | ;; (setq-local corfu-auto nil) ;; Enable/disable auto completion 2066 | (setq-local corfu-echo-delay nil ;; Disable automatic echo and popup 2067 | corfu-popupinfo-delay nil) 2068 | (corfu-mode 1))) 2069 | (add-hook 'minibuffer-setup-hook #'corfu-enable-in-minibuffer) 2070 | 2071 | (setq text-mode-ispell-word-completion nil) 2072 | (setup corfu 2073 | (setq corfu-cycle t ;; Enable cycling for `corfu-next/previous' 2074 | corfu-auto t ;; Enable auto completion 2075 | corfu-quit-no-match t ;; Automatically quit if there is no match 2076 | corfu-preview-current nil ;; Disable current candidate preview 2077 | corfu-auto-prefix 1 2078 | corfu-auto-delay 0.05 2079 | corfu-scroll-margin 5 2080 | ) ;; Use scroll margin 2081 | (:with-map corfu-map 2082 | (:bind "" my-corfu-quit 2083 | "C-SPC" corfu-insert-separator 2084 | )) 2085 | 2086 | (defun my-corfu-quit() 2087 | "when in corfu-map, quit corfu-selection and return to meow normal mode" 2088 | (interactive) 2089 | (corfu-quit) 2090 | (meow-insert-exit)) 2091 | 2092 | (global-corfu-mode) 2093 | ;; (add-hook 'minibuffer-setup-hook #'corfu-enable-always-in-minibuffer 1) 2094 | ) 2095 | (setup corfu-popupinfo 2096 | (:load-after corfu) 2097 | (setq corfu-popupinfo-delay '(0.5 . 0.5)) 2098 | (:when-loaded 2099 | (corfu-popupinfo-mode))) 2100 | 2101 | (setup cape 2102 | ;; don't let dabbrev take over all things 2103 | (defalias 'cape-dabbrev-min-2 (cape-capf-prefix-length #'cape-dabbrev 2)) 2104 | ;; (add-to-list 'completion-at-point-functions #'cape-dabbrev) 2105 | (add-to-list 'completion-at-point-functions #'cape-dabbrev-min-2) 2106 | (add-to-list 'completion-at-point-functions #'cape-elisp-block) 2107 | (add-to-list 'completion-at-point-functions #'cape-dict) 2108 | (add-to-list 'completion-at-point-functions #'cape-file) 2109 | ) 2110 | 2111 | #+end_src 2112 | ***** ispell 2113 | #+begin_src elisp 2114 | (setup ispell 2115 | (:when-loaded 2116 | ;; if not find ispell-dict, use cape as default 2117 | (if (null ispell-alternate-dictionary) 2118 | (progn 2119 | (setq ispell-complete-word-dict (concat nowis-doc-emacs-dir "02-binary-git/binary-files/12-spell-dict/en_US.dict")))))) 2120 | #+end_src 2121 | ***** nerd-icons-corfu 2122 | #+begin_src elisp 2123 | (setup nerd-icons-corfu 2124 | (add-to-list 'corfu-margin-formatters #'nerd-icons-corfu-formatter)) 2125 | #+end_src 2126 | **** lsp mode 2127 | ***** eglot 2128 | #+begin_src elisp 2129 | (setup project) 2130 | (setq read-process-output-max (* 1024 1024)) 2131 | (setup eglot 2132 | (setq eglot-events-buffer-config'(:size 20000 :format full) 2133 | eglot-extend-to-xref t 2134 | ;; eglot-workspace-configuration '((:python.analysis :useLibraryCodeForTypes t)) 2135 | eglot-workspace-configuration '(:basedpyright (:typeCheckingMode "off") 2136 | :basedpyright.analysis (:diagnosticSeverityOverrides (:reportUnusedCallResult "none") 2137 | :inlayHints (:callArgumentNames :json-false) 2138 | )) 2139 | ) 2140 | (:autoload eglot-find-implementation) 2141 | (add-hook 'prog-mode-hook (lambda () 2142 | (unless 2143 | (or (file-remote-p default-directory) 2144 | (derived-mode-p 'emacs-lisp-mode 'lisp-mode 'makefile-mode 'snippet-mode) 2145 | (eglot-ensure))))) 2146 | ;; (add-hook 'text-mode-hook (lambda() (eglot-ensure))) 2147 | 2148 | (:when-loaded 2149 | ;; hightlight face 2150 | (defface new-hi-green 2151 | '((((min-colors 88) (background dark)) 2152 | (:background "light green" :foreground "black")) 2153 | (((background dark)) (:background "green" :foreground "black")) 2154 | (((min-colors 88)) (:background "light green")) 2155 | (t (:background "green"))) 2156 | "Face for hi-lock mode.") 2157 | (set-face-attribute 'eglot-highlight-symbol-face nil :inherit 'new-hi-green) 2158 | ;; more languare server 2159 | (add-to-list 'eglot-server-programs 2160 | '(graphviz-dot-mode . ("dot-language-server" "--stdio"))) 2161 | ;; (add-to-list 'eglot-server-programs 2162 | ;; '(text-mode . ("harper-ls" "--stdio"))) 2163 | ) 2164 | ) 2165 | (setup eldoc 2166 | (setq eldoc-echo-area-use-multiline-p nil 2167 | eldoc-echo-area-display-truncation-message t)) 2168 | ;; (setq eldoc-echo-area-prefer-doc-buffer nil) 2169 | #+end_src 2170 | ***** eglot in org-src 2171 | #+begin_src elisp 2172 | (with-eval-after-load 'org 2173 | (cl-defmacro lsp-org-babel-enable (lang) 2174 | "Support LANG in org source code block." 2175 | (cl-check-type lang stringp) 2176 | (let* ((edit-pre (intern (format "org-babel-edit-prep:%s" lang))) 2177 | (intern-pre (intern (format "lsp--%s" (symbol-name edit-pre))))) 2178 | `(progn 2179 | ;;;;;;;;;;;; always use temp file 2180 | (defun ,intern-pre (info) 2181 | (let ((file-name (make-temp-file "babel-lsp-"))) 2182 | (setq buffer-file-name file-name) 2183 | (eglot-ensure))) 2184 | 2185 | ;; (lsp-deferred))) 2186 | (put ',intern-pre 'function-documentation 2187 | (format "Enable lsp-mode in the buffer of org source block (%s)." 2188 | (upcase ,lang))) 2189 | (if (fboundp ',edit-pre) 2190 | (advice-add ',edit-pre :after ',intern-pre) 2191 | (progn 2192 | (defun ,edit-pre (info) 2193 | (,intern-pre info)) 2194 | (put ',edit-pre 'function-documentation 2195 | (format "Prepare local buffer environment for org source block (%s)." 2196 | (upcase ,lang)))))))) 2197 | (defvar org-babel-lang-list 2198 | '("python" "C++" "C" "c" "cpp" "dot")) 2199 | (dolist (lang org-babel-lang-list) 2200 | (eval `(lsp-org-babel-enable ,lang))) 2201 | ) 2202 | #+end_src 2203 | **** citre 2204 | Citre is an advanced Ctags (or actually, readtags) frontend for Emacs. 2205 | #+begin_src elisp 2206 | (setup citre 2207 | (add-hook 'prog-mode (lambda() 2208 | (require 'citre-config) 2209 | )) 2210 | (setq citre-use-project-root-when-creating-tags t 2211 | citre-prompt-language-for-ctags-command t 2212 | ;; citre-auto-enable-citre-mode-modes '(prog-mode) 2213 | ) 2214 | ) 2215 | #+end_src 2216 | *** spell-check 2217 | **** jinx 2218 | #+begin_src elisp 2219 | (setup jinx 2220 | ;; (dolist (hook '(text-mode-hook conf-mode-hook)) 2221 | ;; (add-hook hook #'jinx-mode)) 2222 | (:when-loaded 2223 | (setq jinx-languages "en_US") 2224 | (add-to-list 'jinx-exclude-regexps '(t "\\cc")) 2225 | (keymap-global-set "M-$" #'jinx-correct) 2226 | (keymap-global-set "C-M-$" #'jinx-languages))) 2227 | #+end_src 2228 | *** debug 2229 | **** gdb 2230 | #+begin_src elisp 2231 | (setup gdb-mi 2232 | (setq gdb-restore-window-configuration-after-quit t) 2233 | ) 2234 | #+end_src 2235 | **** dape 2236 | #+begin_src elisp 2237 | (setup dape 2238 | (setq dape-buffer-window-arrangment 'right) 2239 | (keymap-global-set "" #'dape) 2240 | (:when-loaded 2241 | (add-hook 'dape-repl-mode-hook (lambda() 2242 | (corfu-mode -1) 2243 | ) 2244 | ))) 2245 | #+end_src 2246 | **** edebug 2247 | #+begin_src lisp 2248 | (setup edebug 2249 | (:with-map edebug-mode-map 2250 | (:bind "n" edebug-step-mode 2251 | "N" edebug-next-mode 2252 | ))) 2253 | #+end_src 2254 | *** Code toggle with hideshow, hideif 2255 | #+begin_src elisp 2256 | (setup hideshow 2257 | (:with-hook prog-mode-hook 2258 | (:hook hs-minor-mode)) 2259 | (add-to-list 'hs-special-modes-alist '(verilog-mode "\\(\\\\|\\\\|\\\\|\\\\|\\\\|\\\\)" 2260 | ))) 2261 | #+end_src 2262 | *** format-all 2263 | #+begin_src elisp 2264 | (setup inheritenv) 2265 | (setup language-id) 2266 | (setup format-all) 2267 | #+end_src 2268 | *** compile 2269 | #+begin_src elisp 2270 | (setup compile 2271 | (setq compile-command "cd build && make && ./test")) 2272 | #+end_src 2273 | * Org Mode 2274 | ** org-mode 2275 | #+begin_src elisp 2276 | (setup engrave-faces) ;; for code highlight when exporting pdfs 2277 | (setup org 2278 | (setq org-adapt-indentation nil 2279 | org-startup-indented t 2280 | org-startup-with-inline-images nil 2281 | org-startup-numerated nil 2282 | org-startup-folded nil 2283 | org-hide-block-startup t 2284 | org-imenu-depth 8 2285 | org-return-follows-link t 2286 | org-id-link-to-org-use-id t ;; Create an ID if needed to make a link to the current entry. 2287 | 2288 | org-link-frame-setup '((vm . vm-visit-folder-other-frame) 2289 | (vm-imap . vm-visit-imap-folder-other-frame) 2290 | (gnus . org-gnus-no-new-news) 2291 | (file . find-file) 2292 | (wl . wl-other-frame)) 2293 | ;; org-blank-before-new-entry '((heading . t) 2294 | ;; (plain-list-item . auto)) 2295 | 2296 | org-image-actual-width 800 ;; this will use 600 for width for all the images. 2297 | org-preview-latex-image-directory (concat no-littering-var-directory "ltximg/") 2298 | org-plantuml-jar-path plantuml-jar-path 2299 | org-special-ctrl-a/e t 2300 | ;; org-id 2301 | org-attach-id-dir (concat nowis-doc-emacs-dir "01-orgmode/org-attach") 2302 | org-id-method 'ts 2303 | org-id-ts-format "%Y%m%dT%H%M%S_%6N" 2304 | 2305 | ;; habit 2306 | org-habit-following-days 2 2307 | system-time-locale "C" ;; ensure time format is always english 2308 | ;; todo keywords 2309 | org-todo-keyword-faces '(("TODO" :foreground "red" :weight bold) 2310 | ("NEXT" :foreground "deep sky blue" :weight bold) 2311 | ("WAIT" :foreground "goldenrod" :weight bold) 2312 | ("SMDY" :foreground "medium purple" :weight bold) 2313 | ("DONE" :foreground "forest green" :weight bold) 2314 | ("AXED" :foreground "gray55" :weight bold)) 2315 | ;; save state changes into logbook 2316 | org-log-state-notes-into-drawer t 2317 | ;; plain list 2318 | org-list-demote-modify-bullet '(("+" . "-") ("-" . "+") ("*" . "+")) 2319 | ;; attach 2320 | org-yank-image-save-method (concat nowis-doc-emacs-dir "30-saved-binary/01-pictures/01-org_attachs") 2321 | ) 2322 | (:when-loaded 2323 | (require 'org-tempo) ;; so that png" 2475 | :message "you need install the programs: tectonic and imagemagick." 2476 | :image-input-type "pdf" 2477 | :image-output-type "png" 2478 | :image-size-adjust (1.0 . 1.0) 2479 | :latex-compiler 2480 | ("tectonic -Z shell-escape-cwd=%o --outfmt pdf --outdir %o %f") 2481 | :image-converter 2482 | ("convert -density %D -trim -antialias %f -quality 300 %O"))) 2483 | (setq org-preview-latex-default-process 'tectonic) ;; need to install tectonic and imagemagick 2484 | 2485 | 2486 | (plist-put org-format-latex-options :scale 1.0) ;; use a large preview for latex 2487 | ;; (setq org-preview-latex-default-process 'dvisvgm) 2488 | ;; export and open word 2489 | (add-to-list 'org-file-apps '("\\.docx\\'" . default)) 2490 | (add-to-list 'org-structure-template-alist 2491 | '("jp" . "src jupyter-python :async yes :kernel python3 :session py")) 2492 | 2493 | ;; borrowed from HM0880 2494 | (defun lewis/convert-org-to-docx-with-pandoc () 2495 | "Use Pandoc to convert .org to .docx. 2496 | Comments: 2497 | - The `-N' flag numbers the headers lines. 2498 | - Use the `--from org' flag to have this function work on files 2499 | that are in Org syntax but do not have a .org extension" 2500 | (interactive) 2501 | (shell-command 2502 | (concat "pandoc -N --from org " (buffer-file-name) 2503 | " -o " 2504 | (file-name-sans-extension (buffer-file-name)) 2505 | ".docx")) 2506 | (message "Convert finish: %s" docx-file)) 2507 | 2508 | (defun lewis/convert-md-to-org (start end) 2509 | "Convert region from markdown to org" 2510 | (interactive "r") 2511 | (shell-command-on-region start end "pandoc -f markdown -t org" t t) 2512 | (org-mode)) 2513 | )) 2514 | #+end_src 2515 | ** org-clock 2516 | #+begin_src elisp 2517 | (setup org-clock 2518 | (setq org-clock-mode-line-entry 'current) 2519 | (:when-loaded 2520 | (defun my/org-show-reminder () 2521 | "Function to show a reminder buffer." 2522 | (let ((buf (get-buffer-create "*Org Clock Reminder*")) 2523 | (messages 2524 | (list 2525 | (propertize "Finished a time-box!" 'face '(:weight bold :height 1.5)) 2526 | (propertize "Take a break and think what's most important!" 'face '(:foreground "orange" :weight semi-bold)))) 2527 | ) 2528 | (with-current-buffer buf 2529 | (erase-buffer) 2530 | (insert (make-string (max 0 (/ (- (frame-height) 1) 6)) ?\n)) ;; whitespace line 2531 | (dolist (message messages) 2532 | (insert message "\n")) 2533 | (center-region (point-min) (point-max)) 2534 | (goto-char (point-min)) 2535 | (display-buffer buf) 2536 | ))) 2537 | 2538 | (add-hook 'org-timer-set-hook #'org-clock-in) 2539 | (add-hook 'org-timer-done-hook #'my/org-show-reminder) 2540 | (add-hook 'org-timer-done-hook #'org-clock-out) 2541 | )) 2542 | #+end_src 2543 | ** org-timer 2544 | #+begin_src elisp 2545 | (setup org-timer 2546 | (setq org-timer-default-timer 25)) 2547 | #+end_src 2548 | ** appt 2549 | #+begin_src elisp :tangle no 2550 | (setup appt 2551 | (:load-after org) 2552 | (:when-loaded 2553 | (run-at-time nil 3600 'org-agenda-to-appt) 2554 | ;; 更新agenda时,同步appt 2555 | (add-hook 'org-finalize-agenda-hook 'org-agenda-to-appt) 2556 | ;; 激活提醒 2557 | (appt-activate 1) 2558 | )) 2559 | #+end_src 2560 | ** ui 2561 | *** org mode basic style 2562 | #+begin_src elisp 2563 | (setup org 2564 | (setq org-auto-align-tags nil 2565 | org-tags-column 0 2566 | org-ellipsis " " 2567 | org-hide-emphasis-markers t 2568 | org-pretty-entities nil ;; can perfor ui such as "a_words" into small "awords" 2569 | org-habit-graph-column 50 2570 | ;; Agenda styling 2571 | org-agenda-tags-column 0 2572 | ) 2573 | (:when-loaded 2574 | ;; emphasis 2575 | (defface my-org-emphasis-bold 2576 | '((default :inherit bold) 2577 | (((class color) (min-colors 88) (background light)) 2578 | :foreground "pale violet red") 2579 | (((class color) (min-colors 88) (background dark)) 2580 | :foreground "pale violet red")) 2581 | "My bold emphasis for Org.") 2582 | 2583 | (defface my-org-emphasis-italic 2584 | '((default :inherit italic) 2585 | (((class color) (min-colors 88) (background light)) 2586 | :foreground "green3") 2587 | (((class color) (min-colors 88) (background dark)) 2588 | :foreground "green3")) 2589 | "My italic emphasis for Org.") 2590 | 2591 | (defface my-org-emphasis-underline 2592 | '((default :inherit underline) 2593 | (((class color) (min-colors 88) (background light)) 2594 | :foreground "#813e00") 2595 | (((class color) (min-colors 88) (background dark)) 2596 | :foreground "#d0bc00")) 2597 | "My underline emphasis for Org.") 2598 | 2599 | (setq org-emphasis-alist 2600 | '(("*" my-org-emphasis-bold) 2601 | ("/" my-org-emphasis-italic) 2602 | ("_" underline) 2603 | ("=" org-verbatim verbatim) 2604 | ("~" org-code verbatim) 2605 | ("+" (:strike-through t)) 2606 | )) 2607 | )) 2608 | #+end_src 2609 | *** org beatury 2610 | #+begin_src elisp 2611 | (with-eval-after-load 'org 2612 | (setq org-hide-leading-stars t) 2613 | (let ((star-list '("󰯬" "󰯯" "󰯲" "󰯵" "󰯸" "󰯻" "󰯾" "󰰁" "󰰄" "󰰇" "󰰊"))) 2614 | (dotimes (i (length star-list)) 2615 | (font-lock-add-keywords 2616 | 'org-mode 2617 | `((,(format "^\\(\\*\\{%d\\}\\) " (+ i 1)) ;; 只捕获星号 2618 | (1 (prog1 nil ;; 1 是第一个 group(星号) 2619 | (compose-region (match-beginning 1) (match-end 1) 2620 | ,(nth i star-list)))))))) 2621 | )) 2622 | (add-hook 'org-mode-hook (lambda() 2623 | (setq prettify-symbols-alist 2624 | '(("#+begin_src" . ?) 2625 | ("#+end_src" . ?) 2626 | )) 2627 | (prettify-symbols-mode) 2628 | )) 2629 | #+end_src 2630 | *** org-appear 2631 | #+begin_src elisp 2632 | (setup org-appear 2633 | (:load-after org) 2634 | (:hook-into org-mode)) 2635 | #+end_src 2636 | *** org-visual-outline 2637 | #+begin_src elisp 2638 | (setup org-visual-outline 2639 | (add-hook 'org-mode-hook #'org-visual-indent-mode)) 2640 | #+end_src 2641 | ** ox-hugo 2642 | #+begin_src elisp 2643 | (setup tomelr) 2644 | (setup ox-hugo 2645 | (with-eval-after-load 'ox 2646 | (require 'ox-hugo))) 2647 | #+end_src 2648 | ** org-present 2649 | #+begin_src elisp 2650 | (setup org-present) 2651 | #+end_src 2652 | ** bibtex related 2653 | *** bibtex 2654 | #+begin_src elisp 2655 | (setup bibtex 2656 | (setq bibtex-autokey-year-length 4 2657 | bibtex-autokey-titleword-separator "_" 2658 | bibtex-autokey-name-year-separator "_" 2659 | bibtex-autokey-year-title-separator "_" 2660 | bibtex-autokey-titleword-length 15 2661 | bibtex-autokey-titlewords 10 2662 | bibtex-autokey-titleword-ignore ;; I took "On" out of this 2663 | '("A" "An" "The" "Eine?" "Der" "Die" "Das"))) 2664 | 2665 | (defun do.refs/get-db-file-list () 2666 | "Get the list of all the bib files containing my bib database." 2667 | (if (file-exists-p nowis-bib-dir) 2668 | (directory-files-recursively nowis-bib-dir "\\.bib\\'" t) 2669 | nil)) 2670 | #+end_src 2671 | *** citar 2672 | #+begin_src elisp 2673 | (setup parsebib) 2674 | ;; (setup citeproc) ;;<- (setup queue) (setup string-inflection) 2675 | (setup citar 2676 | (setq org-cite-global-bibliography (do.refs/get-db-file-list) 2677 | org-cite-insert-processor 'citar 2678 | org-cite-follow-processor 'citar 2679 | org-cite-activate-processor 'citar 2680 | citar-library-paths (list nowis-bib-pdf-dir) 2681 | citar-bibliography org-cite-global-bibliography 2682 | ;; org-cite-export-processors '((t . (csl "modern-language-association.csl"))) 2683 | )) 2684 | #+end_src 2685 | *** citar-denote 2686 | #+begin_src elisp 2687 | (setup citar-denote 2688 | (setq citar-denote-title-format "title") 2689 | (with-eval-after-load 'citar 2690 | (citar-denote-mode) 2691 | ) 2692 | ) 2693 | #+end_src 2694 | *** ebib 2695 | #+begin_src elisp 2696 | (setup ebib 2697 | (setq ebib-preload-bib-files org-cite-global-bibliography 2698 | ebib-file-search-dirs (list nowis-bib-pdf-dir) 2699 | ebib-bib-search-dirs (list nowis-bib-dir) 2700 | ebib-default-directory 'first-bib-dir 2701 | ebib-file-associations '(("pdf") 2702 | ("ps" . "gv") 2703 | ("epub")) 2704 | ebib-index-window-size 25 2705 | ebib-index-columns '(("Score" 2 t) 2706 | ("Year" 6 t) 2707 | ("Author/Editor" 10 t) 2708 | ("Title" 80 t) 2709 | ("abstract" 10 t) 2710 | ) 2711 | ebib-reading-list-file (concat nowis-doc-emacs-dir "01-orgmode/xnotes/20230403T125743--ebib-reading-lists.org") 2712 | ebib-use-timestamp t 2713 | ebib-bibtex-dialect 'biblatex 2714 | ebib-create-backups nil 2715 | )) 2716 | #+end_src 2717 | ** toc-org 2718 | #+begin_src elisp 2719 | (setup toc-org 2720 | (:hook-into org-mode)) 2721 | #+end_src 2722 | ** denote and related 2723 | *** denote 2724 | #+begin_src elisp 2725 | (setup denote 2726 | (setq denote-directory (expand-file-name (concat nowis-doc-emacs-dir "01-orgmode/xnotes")) 2727 | ;; denote-dired-directories (ffap-all-subdirs denote-directory) 2728 | denote-date-prompt-use-org-read-date t 2729 | denote-modules '(project) 2730 | denote-prompts '(title keywords signature template) 2731 | denote-dired-directories-include-subdirectories t 2732 | ) 2733 | ;; (add-hook 'dired-mode-hook #'denote-dired-mode-in-directories) 2734 | (setq denote-templates 2735 | `((essence . ,(concat "* 本质思考\n" 2736 | "** 事物的根本属性\n" 2737 | "** 问题的根源\n" 2738 | "** 现象背后的底层逻辑\n" 2739 | "* notes\n")) 2740 | (action . ,(concat "* Destination\n\n" 2741 | "* Roadmap\n\n" 2742 | "* Action\n\n" 2743 | "* Warnings\n\n" 2744 | "* Links\n\n")) 2745 | (gtd . ,(concat "* Important\n\n" 2746 | "* Diary\n\n")) 2747 | )) 2748 | ) 2749 | #+end_src 2750 | *** denote-sort 2751 | #+begin_src elisp 2752 | (defun my-denote--split-luhman-sig (signature) 2753 | "Split numbers and letters in Luhmann-style SIGNATURE string." 2754 | (replace-regexp-in-string 2755 | "\\([a-zA-Z]?\\)\\([0-9]\\)" "\\1=\\2" 2756 | (replace-regexp-in-string 2757 | "\\([0-9]?\\)\\([a-zA-Z]\\)" "\\1=\\2" 2758 | signature))) 2759 | 2760 | (defun my-denote--pad-sig (signature) 2761 | "Create a new signature with padded spaces for all components" 2762 | (combine-and-quote-strings 2763 | (mapcar 2764 | (lambda (x) 2765 | (string-pad x 5 32 t)) 2766 | (split-string (my-denote--split-luhman-sig signature) "=" t)) 2767 | "=")) 2768 | 2769 | (defun my-denote-sort-for-signatures (sig1 sig2) 2770 | "Return non-nil if SIG1 is smaller that SIG2. 2771 | Perform the comparison with `string<'." 2772 | (string< (my-denote--pad-sig sig1) (my-denote--pad-sig sig2))) 2773 | ;; Change the sorting function only when we sort by signature. 2774 | (setq denote-sort-signature-comparison-function #'my-denote-sort-for-signatures) 2775 | #+end_src 2776 | *** denote-journal 2777 | #+begin_src elisp 2778 | (setup denote-journal 2779 | (setq denote-journal-title-format "%Y_%m_%d_%a_%j") 2780 | (add-hook 'calendar-mode-hook #'denote-journal-calendar-mode) 2781 | (defun my/denote-journal-this-week-major-tasks () 2782 | "Open this week's Saturday journal and jump to or insert '本周重点任务' headline." 2783 | (interactive) 2784 | (let ((date (my/current-week-saturday))) 2785 | (denote-journal-new-or-existing-entry date) 2786 | (goto-char (point-min)) 2787 | (unless (re-search-forward "^\\*+ 本周重点任务" nil t) 2788 | (goto-char (point-max)) 2789 | (unless (bolp) (insert "\n")) 2790 | (insert "* 本周重点任务 :week:\n")) 2791 | (org-show-entry))) 2792 | ) 2793 | #+end_src 2794 | *** denote-explorer 2795 | #+begin_src elisp 2796 | (setup denote-explore) 2797 | #+end_src 2798 | ** find orgmode dir files 2799 | #+begin_src elisp 2800 | (defun project-find-searchable-dir-files () 2801 | (interactive) 2802 | (dired (concat nowis-doc-emacs-dir "02-binary-git/binary-files/02-searchable")) 2803 | (project-find-file t)) 2804 | (defun project-find-gtd-dir-files () 2805 | (interactive) 2806 | (dired nowis-gtd-dir) 2807 | (project-find-file t)) 2808 | #+end_src 2809 | ** agenda/gtd 2810 | Borrowed from https://github.com/rougier/emacs-GTD 2811 | 2812 | In short, you will need 3 files: 2813 | 1. =index.org= for capture inbox TODOs 2814 | 2. =agenda.org= for recurrent events 2815 | 3. =action.org= for all tasks moving from inbox 2816 | 4. (Option) =incubate.org= for incubate ideas 2817 | *** file 2818 | #+begin_src elisp 2819 | ;; Files 2820 | (setq org-directory "~/Documents/emacs/01-orgmode/xnotes") 2821 | 2822 | (setup org 2823 | (:when-loaded 2824 | (defun org-agenda-update-agenda-files () 2825 | "Update agenda file list together with refile list." 2826 | (interactive) 2827 | (let* ((gtd-dir (concat org-directory "/gtd")) 2828 | (gtd-files (when (file-exists-p gtd-dir) 2829 | (directory-files-recursively gtd-dir "\\.org$"))) 2830 | ) 2831 | (setq org-agenda-files gtd-files) 2832 | 2833 | (setq org-refile-files 2834 | (cl-remove-if (lambda (file) (string-match-p "inbox.org$" file)) 2835 | org-agenda-files)))) 2836 | (org-agenda-update-agenda-files) 2837 | )) 2838 | 2839 | #+end_src 2840 | *** todos 2841 | #+begin_src elisp 2842 | (setq org-enforce-todo-dependencies t 2843 | org-enforce-todo-checkbox-dependencies t 2844 | ) 2845 | (setq org-log-done 'note) 2846 | (setq org-todo-keywords 2847 | '((sequence "TODO(t)" "NEXT(n)" "WAIT(w)" "SMDY(s)" "|" "AXED(a)" "DONE(d)"))) 2848 | 2849 | (defun log-todo-next-creation-date (&rest ignore) 2850 | "Log NEXT creation time in the property drawer under the key 'ACTIVATED'" 2851 | (when (and (string= (org-get-todo-state) "NEXT") 2852 | (not (org-entry-get nil "ACTIVATED"))) 2853 | (org-entry-put nil "ACTIVATED" (format-time-string "[%Y-%m-%d]")))) 2854 | (add-hook 'org-after-todo-state-change-hook #'log-todo-next-creation-date) 2855 | (setq org-priority-lowest 69) ;; E 2856 | (setq org-priority-default 68) ;; D 2857 | 2858 | #+end_src 2859 | *** capture 2860 | #+begin_src elisp 2861 | ;; Use full window for org-capture 2862 | ;; (add-hook 'org-capture-mode-hook 'delete-other-windows) 2863 | (setup org 2864 | (:when-loaded 2865 | (setq org-capture-templates 2866 | `(("i" "Inbox" entry (file+olp+datetree "gtd/inbox.org") 2867 | ,(concat "* TODO %?\n" 2868 | "/Entered on/ %U")) 2869 | ("d" "Done without clock" entry (file+olp+datetree "gtd/inbox.org") 2870 | ,(concat "* DONE %?\n" 2871 | "CLOSED: %U\n" 2872 | ":LOGBOOK:\n" 2873 | "CLOCK: [%<%Y-%m-%d %a %H:%M>]--[%<%Y-%m-%d %a %H:%M>] => \n" 2874 | ":END:")) 2875 | ("D" "Done with clock" entry (file+olp+datetree "gtd/inbox.org") 2876 | ,(concat "* DONE %?\n" 2877 | "CLOSED: %U")) 2878 | ("m" "Meeting" entry (file+headline "agenda.org" "Future") 2879 | ,(concat "* %? :meeting:\n" 2880 | "<%<%Y-%m-%d %a %H:00>>")) 2881 | ("n" "Note" entry (file "notes.org") 2882 | ,(concat "* Note (%a)\n" 2883 | "/Entered on/ %U\n" "\n" "%?")) 2884 | ("@" "Inbox [mu4e]" entry (file "inbox.org") 2885 | ,(concat "* TODO Reply to \"%a\" %?\n" 2886 | "/Entered on/ %U"))))) 2887 | ) 2888 | #+end_src 2889 | *** refile 2890 | #+begin_src elisp 2891 | (setup org 2892 | (:when-loaded 2893 | (setq org-refile-use-outline-path 'full-file-path) 2894 | (setq org-outline-path-complete-in-steps nil) 2895 | (setq org-refile-targets '((org-refile-files :regexp . "*"))) 2896 | ;; '(("action.org" :regexp . "\\(?:\\(?:Note\\|Task\\)s\\)") 2897 | ;; ("incubate.org" :regexp . "\\(?:\\(?:Note\\|Task\\)s\\)") 2898 | ;; Save the corresponding buffers 2899 | (defun gtd-save-org-buffers () 2900 | "Save `org-agenda-files' buffers without user confirmation. 2901 | See also `org-save-all-org-buffers'" 2902 | (interactive) 2903 | (message "Saving org-agenda-files buffers...") 2904 | (save-some-buffers t (lambda () 2905 | (when (member (buffer-file-name) org-agenda-files) 2906 | t))) 2907 | (message "Saving org-agenda-files buffers... done")) 2908 | 2909 | ;; Add it after refile 2910 | (advice-add 'org-refile :after 2911 | (lambda (&rest _) 2912 | (gtd-save-org-buffers))) 2913 | 2914 | )) 2915 | #+end_src 2916 | *** agenda 2917 | #+begin_src elisp 2918 | (defun org-get-parent-heading () 2919 | (save-excursion 2920 | (when (org-up-heading-safe) 2921 | (let ((parent (org-get-heading 'no-tags 'no-todo 'no-priority 'no-comment))) 2922 | (truncate-string-to-width parent 20 nil ?\s))))) 2923 | (defun nowis-align-to-window-center(text) 2924 | (let* ((title text) 2925 | (width (window-width (get-buffer-window))) 2926 | (pad (/ (1+ (- width (string-width title))) 2))) 2927 | (concat (make-string (max 0 pad) ? ) title))) 2928 | 2929 | ;; custom skip functins 2930 | (defun my-org-agenda-skip-blocked () 2931 | (when (org-entry-blocked-p) 2932 | (or (outline-next-heading) (point-max)))) 2933 | 2934 | (defun my-org-agenda-skip-unblocked () 2935 | (unless (org-entry-blocked-p) 2936 | (or (outline-next-heading) (point-max)))) 2937 | 2938 | (defmacro nowis-create-agenda-command (key description tag) 2939 | `(list ,key ,description 2940 | '( 2941 | (tags-todo ,(concat "+week" tag) 2942 | ((org-agenda-overriding-header 2943 | (nowis-align-to-window-center "󰛨 Week's Target 󰛨\n")) 2944 | (org-agenda-sorting-strategy '(todo-state-up priority-down timestamp-up)) 2945 | (org-agenda-prefix-format "%-20:(org-get-parent-heading): [%-4e] "))) 2946 | (agenda "" 2947 | ((org-agenda-overriding-header (nowis-align-to-window-center " Today's Target ")) 2948 | (org-agenda-span 'day) 2949 | (org-agenda-skip-function 2950 | '(org-agenda-skip-if nil '(todo done))))) 2951 | (tags-todo "+TODO=\"NEXT\"" 2952 | ((org-agenda-overriding-header (nowis-align-to-window-center "NEXT")) 2953 | (org-agenda-prefix-format "%-20:(org-get-parent-heading): [%-4e] ") 2954 | (org-agenda-sorting-strategy '(todo-state-up priority-down timestamp-up)) 2955 | )) 2956 | (tags-todo "inbox-TODO=\"NEXT\"-PRIORITY=\"E\"" 2957 | ((org-agenda-overriding-header (nowis-align-to-window-center "Inbox")) 2958 | (org-agenda-skip-function #'my-org-agenda-skip-blocked) 2959 | (org-agenda-prefix-format "%-20:(org-get-parent-heading): [%-4e] ") 2960 | (org-agenda-sorting-strategy '(todo-state-up priority-down timestamp-up)))) 2961 | ;; (tags-todo ,(concat "+action" tag) ((org-agenda-overriding-header (nowis-align-to-window-center "Soft Time")) 2962 | ;; (org-agenda-prefix-format "%-20:(org-get-parent-heading): [%-4e] ") 2963 | ;; (org-agenda-sorting-strategy '(todo-state-up priority-down timestamp-up)) 2964 | ;; )) 2965 | (tags-todo "inbox-TODO=\"NEXT\"+PRIORITY=\"E\"" 2966 | ((org-agenda-overriding-header (nowis-align-to-window-center "Low Priority")) 2967 | (org-agenda-skip-function #'my-org-agenda-skip-blocked) 2968 | (org-agenda-prefix-format "%-20:(org-get-parent-heading): [%-4e] ") 2969 | (org-agenda-sorting-strategy '(todo-state-up priority-down timestamp-up)))) 2970 | (tags-todo "inbox-TODO=\"NEXT\"" 2971 | ((org-agenda-overriding-header (nowis-align-to-window-center "Blocked")) 2972 | (org-agenda-skip-function #'my-org-agenda-skip-unblocked) 2973 | (org-agenda-prefix-format "%-20:(org-get-parent-heading): [%-4e] ") 2974 | (org-agenda-sorting-strategy '(todo-state-up priority-down timestamp-up)))) 2975 | (tags ,(concat "CLOSED>=\"\"" tag) 2976 | ((org-agenda-overriding-header (nowis-align-to-window-center "Completed today")) 2977 | (org-agenda-prefix-format "%-20:(org-get-parent-heading): [%-4e] ") 2978 | )) 2979 | (tags ,(concat "CLOSED>=\"<-1w>\"" tag) 2980 | ((org-agenda-overriding-header (nowis-align-to-window-center "Completed last 7 days")) 2981 | (org-agenda-prefix-format "%-20:(org-get-parent-heading): [%-4e] ") 2982 | )) 2983 | ))) 2984 | 2985 | (setq org-agenda-custom-commands 2986 | (list (nowis-create-agenda-command "g" "GTD" "") 2987 | (nowis-create-agenda-command "w" "Work" "+work") 2988 | )) 2989 | ;; agenda clockreport 2990 | (setq org-agenda-start-with-clockreport-mode nil 2991 | org-agenda-clockreport-parameter-plist '(:link t :maxlevel 5 :properties ("Effort")) 2992 | org-clock-out-remove-zero-time-clocks t) 2993 | ;; agenda style 2994 | (setq org-agenda-hide-tags-regexp "\\(inbox\\|action\\|journal\\)") 2995 | #+end_src 2996 | *** archive 2997 | #+begin_src elisp 2998 | (defun nowis-get-closed-time-or-current-time () 2999 | "Get the CLOSED time of the current subtree or use the current time if not available." 3000 | (let ((closed-time (org-entry-get (point) "CLOSED"))) 3001 | (if closed-time 3002 | (org-time-string-to-time closed-time) 3003 | (current-time)))) 3004 | 3005 | (defun nowis-org-archive-subtree () 3006 | "Archive the current subtree to a corresponding archive file based on the task's completion date." 3007 | (interactive) 3008 | (let* ((current-file (buffer-file-name)) 3009 | (completed-time (nowis-get-closed-time-or-current-time)) 3010 | (archive-file (concat "gtd_archive_" (format-time-string "%Y" completed-time) 3011 | "::datetree/"))) 3012 | (setq org-archive-location archive-file) 3013 | (org-archive-subtree))) 3014 | 3015 | #+end_src 3016 | ** org-srs 3017 | #+begin_src elisp 3018 | (setup lisp-fsrs) 3019 | (setup org-srs 3020 | ;; (with-eval-after-load 'org 3021 | ;; (require 'org-srs-embed)) 3022 | ;; (add-hook 'org-mode-hook #'org-srs-embed-overlay-mode) 3023 | (add-hook 'org-mode-hook #'org-cloze-overlay-mode) 3024 | (:with-map org-mode-map 3025 | (:bind 3026 | "" org-srs-item-confirm-command 3027 | "" org-srs-review-rate-easy 3028 | "" org-srs-review-rate-good 3029 | "" org-srs-review-rate-hard 3030 | "" org-srs-review-rate-again)) 3031 | (transient-define-prefix org-srs-transient-map() 3032 | "Define transient-key map for org-fc functions" 3033 | [ 3034 | ["review" 3035 | ("s" "start current" org-srs-review-start) 3036 | ("S" "start all" my/denote-review-srs-files-batch) 3037 | ("q" "quit" org-srs-review-quit) 3038 | ] 3039 | ["create" 3040 | ("n" "new create" org-srs-item-create) 3041 | ("c" "cloze" org-srs-item-cloze-dwim) 3042 | ("C" "uncloze" org-srs-item-uncloze-dwim) 3043 | ("u" "update cloze" org-srs-item-cloze-update) 3044 | ]]) 3045 | ;; font lock for cloze 3046 | (defun org-cloze-fontify (limit) 3047 | "Fontify cloze markup up to LIMIT." 3048 | (while (re-search-forward "{{\\([0-9a-z]+\\)}{\\([^}]+\\)}}" limit t) 3049 | (add-text-properties (match-beginning 0) (match-beginning 2) 3050 | '(invisible org-cloze font-lock-multiline t)) 3051 | (put-text-property (match-beginning 0) (1+ (match-beginning 0)) 3052 | 'display "{") 3053 | (add-text-properties (match-beginning 2) (match-end 2) 3054 | '(face my-org-emphasis-bold font-lock-multiline t)) 3055 | (add-text-properties (match-end 2) (match-end 0) 3056 | '(invisible org-cloze font-lock-multiline t)) 3057 | (put-text-property (match-end 2) (1+ (match-end 2)) 3058 | 'display "}") 3059 | (add-text-properties (1- (match-end 0)) (match-end 0) 3060 | '(rear-nonsticky (invisible display))))) 3061 | 3062 | (define-minor-mode org-cloze-overlay-mode 3063 | "Toggle org-cloze-overlay-mode." 3064 | :lighter " Cloze" 3065 | (if org-cloze-overlay-mode 3066 | (progn 3067 | (add-to-invisibility-spec 'org-cloze) 3068 | (font-lock-add-keywords nil '((org-cloze-fontify))) 3069 | (font-lock-flush)) 3070 | (progn 3071 | (remove-from-invisibility-spec 'org-cloze) 3072 | (font-lock-remove-keywords nil '((org-cloze-fontify))) 3073 | (font-lock-flush)))) 3074 | ) 3075 | #+end_src 3076 | ** org-inc 3077 | #+begin_src elisp 3078 | (setup org-inc 3079 | (setq org-inc-directory (expand-file-name "org-inc/" org-directory) 3080 | org-srs-item-confirm #'org-srs-item-confirm-command) 3081 | (:with-map org-mode-map 3082 | (:bind "C-M-" org-inc-continue 3083 | )) 3084 | (:when-loaded 3085 | (defun my/m-z-action () 3086 | "If region active, show message; else call original M-z." 3087 | (interactive) 3088 | (if (region-active-p) 3089 | (org-inc-extract) 3090 | (call-interactively #'zap-to-char))) 3091 | (global-set-key (kbd "M-z") #'my/m-z-action) 3092 | ) 3093 | ) 3094 | #+end_src 3095 | ** insert from clipboard 3096 | #+begin_src elisp 3097 | (setup org 3098 | (:when-loaded 3099 | (defcustom my/org-yank-image-filename-function 3100 | (lambda () (format-time-string "screenshot_%Y%m%d_%H%M%S.png")) 3101 | "A function to generate screenshot name" 3102 | :type 'function 3103 | :group 'org) 3104 | 3105 | (defun my/org-yank-image-from-clipboard-wsl () 3106 | "paste from wsl" 3107 | ;; (interactive) 3108 | (require 'org-attach) 3109 | (let* ((attach-dir (org-attach-dir t)) 3110 | (filename (funcall my/org-yank-image-filename-function)) 3111 | (filepath (expand-file-name filename attach-dir)) 3112 | (wsl-path (string-trim 3113 | (shell-command-to-string 3114 | (format "wslpath -w '%s'" filepath))))) 3115 | (if (= 0 (call-process "powershell.exe" nil nil nil 3116 | "-Command" 3117 | (format "(Get-Clipboard -Format image).Save('%s')" wsl-path))) 3118 | (progn 3119 | (insert (format "[[attachment:%s]]" filename)) 3120 | (org-display-inline-images) 3121 | (message "Image saved to attachment: %s" filepath)) 3122 | (error "Failed to save image from clipboard")))) 3123 | 3124 | (defun my/org-yank-image-from-clipboard-native () 3125 | "use the default yank-media" 3126 | (yank-media)) 3127 | 3128 | (defun my/org-yank-image-from-clipboard () 3129 | "paste pictures from powershell when using wsl, others use yank-media" 3130 | (interactive) 3131 | (if (string= "Arch" (getenv "WSL_DISTRO_NAME")) 3132 | (my/org-yank-image-from-clipboard-wsl) 3133 | (my/org-yank-image-from-clipboard-native))) 3134 | (:with-map org-mode-map 3135 | (:bind "M-" my/org-yank-image-from-clipboard) 3136 | ) 3137 | )) 3138 | #+end_src 3139 | ** org-media-note 3140 | #+begin_src elisp 3141 | (setup org-media-note 3142 | (setq org-media-note-screenshot-image-dir (concat nowis-doc-emacs-dir "30-saved-binary/org-media-note"))) 3143 | #+end_src 3144 | ** org-sliced-images 3145 | #+begin_src elisp 3146 | (setup org-sliced-images 3147 | (:hook-into org-mode) 3148 | ) 3149 | #+end_src 3150 | ** org-noter 3151 | #+begin_src elisp 3152 | (setup org-noter) 3153 | #+end_src 3154 | ** org-graphviz-mindmap 3155 | #+begin_src elisp 3156 | (setup org-graphviz-mindmap) 3157 | #+end_src 3158 | ** org-ladder 3159 | #+begin_src elisp 3160 | (setup org-ladder 3161 | (let* ((gtd-dir (expand-file-name "gtd" org-directory)) 3162 | (gtd-files (when (file-directory-p gtd-dir) 3163 | (directory-files-recursively gtd-dir ".*")))) 3164 | (setq org-ladder-files gtd-files)) 3165 | ) 3166 | #+end_src 3167 | * 阅读 3168 | ** pdf-tools 3169 | #+begin_src elisp :tangle no 3170 | (setup tablist) 3171 | (setup pdf-tools 3172 | (setq pdf-view-use-scaling t 3173 | pdf-annot-list-format '((page . 3) 3174 | (type . 10) 3175 | (contents . 56) 3176 | (date . 24))) 3177 | (:with-map pdf-view-mode-map 3178 | (:bind "h h" pdf-annot-add-highlight-markup-annotation 3179 | "[" pdf-view-scroll-down-or-previous-page 3180 | "]" pdf-view-scroll-up-or-next-page)) 3181 | (pdf-loader-install) 3182 | ) 3183 | ;; (add-hook 'pdf-view-mode-hook (lambda() (linum-mode -1)))) 3184 | (setq TeX-view-program-selection '((output-pdf "PDF Tools")) 3185 | TeX-view-program-list '(("PDF Tools" TeX-pdf-tools-sync-view)) 3186 | TeX-source-correlate-start-server t) 3187 | 3188 | (add-hook 'TeX-after-compilation-finished-functions 3189 | #'TeX-revert-document-buffer) 3190 | #+end_src 3191 | ** pdf-view-pagemark 3192 | #+begin_src elisp :tangle no 3193 | (setup pdf-view-pagemark 3194 | (:hook-into pdf-view-mode-hook)) 3195 | #+end_src 3196 | ** newsticker 3197 | #+begin_src elisp 3198 | (setq newsticker-url-list '(("Planet Emacslife" "https://planet.emacslife.com/atom.xml") 3199 | ("sachachua" "https://sachachua.com/blog/feed/") 3200 | ("karthinks" "https://karthinks.com/index.xml") 3201 | ("protesilaos" "https://protesilaos.com/codelog.xml") 3202 | ("lazycat" "https://manateelazycat.github.io/feed.xml") 3203 | ("zhihu" "https://plink.anyfeeder.com/zhihu/daily") 3204 | )) 3205 | #+end_src 3206 | ** nov 3207 | #+begin_src elisp 3208 | (setup esxml) ;; <- (setup kv) 3209 | (setup nov 3210 | (:bind "]" nov-scroll-up 3211 | "[" nov-scroll-down)) 3212 | (add-to-list 'auto-mode-alist '("\\.epub\\'" . nov-mode)) 3213 | 3214 | #+end_src 3215 | ** darkroom 3216 | Simple distraction-free editing. I use darkroom instead of writeroom because it's more simple 3217 | #+begin_src elisp 3218 | (setup darkroom) 3219 | #+end_src 3220 | ** markdown-mode 3221 | #+begin_src elisp 3222 | (setup markdown-mode 3223 | (:match-file "\\.md\\'")) 3224 | #+end_src 3225 | * tools 3226 | ** ai related 3227 | *** gptel 3228 | #+begin_src elisp 3229 | (setup gptel 3230 | (setq gptel-default-mode 'org-mode 3231 | gptel-crowdsourced-prompts-file (concat nowis-doc-emacs-dir "09-scripts/chatgpt.csv") 3232 | gptel-highlight-methods '(face) 3233 | ;; gptel-model 'deepseek-v3 3234 | gptel-model 'gpt-4.1 3235 | ) 3236 | (keymap-global-set "M-p" #'gptel-send) 3237 | (keymap-global-set "M-r" #'gptel-rewrite) 3238 | (keymap-global-set "M-P" #'gptel) 3239 | (:hook gptel-highlight-mode) 3240 | (:when-loaded 3241 | (setq-default gptel-backend (gptel-make-gh-copilot "Copilot")) 3242 | (gptel-make-openai "chatanywhere" 3243 | :host "api.chatanywhere.tech" 3244 | :header (lambda () `(("Authorization" . ,(concat "Bearer " (gptel--get-api-key))))) 3245 | :key 'gptel-api-key 3246 | :stream t 3247 | :models '(gpt-5 deepseek-v3.1-250821 claude-haiku-4-5-20251001)) 3248 | (gptel-make-openai "momenta" 3249 | :host "llm-gateway.momenta.works" 3250 | :header (lambda () `(("Authorization" . ,(concat "Bearer " (gptel--get-api-key))))) 3251 | :key 'gptel-api-key 3252 | :stream t 3253 | :models '(claude-sonnet-4.5 claude-haiku-4.5 minimax-m2 gemini-3-pro deepseek-v3.2)) 3254 | (gptel-make-gemini "Gemini" :key 'gptel-api-key :stream t) 3255 | (gptel-make-deepseek "DeepSeek" 3256 | :stream t 3257 | :key 'gptel-api-key) 3258 | )) 3259 | #+end_src 3260 | *** gptel-agent 3261 | #+begin_src elisp 3262 | (setup gptel-agent 3263 | (:when-loaded 3264 | (gptel-agent-update) 3265 | ) 3266 | ) 3267 | #+end_src 3268 | *** nowis-gptel-tools 3269 | #+begin_src elisp 3270 | (setup nowis-gptel-tools 3271 | (:load-after gptel) 3272 | ) 3273 | #+end_src 3274 | *** gptel-local-org-prompts 3275 | #+begin_src elisp 3276 | (setup gptel-local-org-prompts 3277 | (keymap-global-set "M-L" #'gptel-choose-org-prompt) 3278 | (setq gptel-local-org-prompts-directory (expand-file-name "13-gptel-prompts/" nowis-doc-emacs-dir) 3279 | gptel-local-org-prompts-preview-length 100) 3280 | ) 3281 | #+end_src 3282 | *** gptel-aibo 3283 | #+begin_src elisp 3284 | (setup gptel-aibo 3285 | (:when-loaded 3286 | (define-key gptel-aibo-mode-map 3287 | (kbd "M-p") #'gptel-aibo-send) 3288 | (keymap-global-set "M-c" #'gptel-aibo-summon) 3289 | )) 3290 | #+end_src 3291 | *** gptel-quick 3292 | #+begin_src elisp 3293 | (setup gptel-quick 3294 | (setq gptel-quick-timeout 40 3295 | gptel-quick-system-message (lambda (count) 3296 | (format "用小于%d 个字的中文解释." count)) 3297 | ) 3298 | (keymap-global-set "M-l" #'gptel-quick) 3299 | (with-eval-after-load 'embark 3300 | (keymap-set embark-general-map "?" #'gptel-quick)) 3301 | ) 3302 | #+end_src 3303 | *** whisper 3304 | #+begin_src elisp 3305 | (setup whisper 3306 | (setq whisper-language "auto" 3307 | whisper-model "base" 3308 | whisper-quantize nil 3309 | whisper-translate nil 3310 | whisper-use-threads (- (num-processors) 1) 3311 | whisper--ffmpeg-input-device "default" 3312 | whisper--ffmpeg-input-format "pulse" 3313 | ) 3314 | (:when-loaded 3315 | ;; (defun whisper--ctranslate2-command (input-file) 3316 | ;; `("whisper-ctranslate2" 3317 | ;; ,@(when whisper-use-threads (list "--threads" (number-to-string whisper-use-threads))) 3318 | ;; "--task" ,(if whisper-translate "translate" "transcribe") 3319 | ;; "--model" ,whisper-model 3320 | ;; "--language" "zh" 3321 | ;; "--output_dir" "/tmp/" 3322 | ;; "--output_format" "txt" 3323 | ;; ,input-file)) 3324 | 3325 | ;; (advice-add 'whisper-command :override #'whisper--ctranslate2-command) 3326 | ) 3327 | ) 3328 | #+end_src 3329 | *** eca 3330 | #+begin_src elisp 3331 | (setup eca 3332 | (setq eca-server-download-method 'curl) 3333 | ) 3334 | #+end_src 3335 | ** webjump 3336 | #+begin_src elisp 3337 | (setup webjump 3338 | (setq webjump-sites '( 3339 | ("Google" . 3340 | [simple-query "www.google.com" 3341 | "www.google.com/search?q=" ""]) 3342 | ("DouBan DuShu" . 3343 | [simple-query "book.douban.com" 3344 | "search.douban.com/book/subject_search?search_text=" ""]) 3345 | ("Github" . 3346 | [simple-query "github.com" 3347 | "github.com/search?ref=simplesearch&q=" ""]) 3348 | ("Aur" . 3349 | [simple-query "aur.archlinux.org" 3350 | "aur.archlinux.org/packages?O=0&K=" ""]) 3351 | ("leetcode-cn" . 3352 | [simple-query "leetcode.cn" 3353 | "leetcode.cn/search/?q=" ""]) 3354 | ("superlib" . 3355 | [simple-query "book.ucdrs.superlib.net" 3356 | "http://book.ucdrs.superlib.net/search?sw=" "&allsw=%23%2Call&bCon=&ecode=utf-8&channel=search&Field=all"]) 3357 | ("cppinfo" . 3358 | [simple-query "book.cppinfo.cn" 3359 | "book.cppinfo.cn/so/home/qhsearch?q=" ""]) 3360 | ))) 3361 | #+end_src 3362 | ** backup scripts 3363 | #+begin_src elisp 3364 | (defun rsync-push-binary-files() 3365 | (interactive) 3366 | (async-shell-command "rsync -avbihn --exclude '.git' --exclude '.svn' --delete \ 3367 | ~/Documents/emacs/02-binary-git/binary-files/ lewis-nas@192.168.31.108:/share/my_webdav/rsync/02-binary-git/binary-files/") 3368 | (let ((answer (read-char-choice "Do you want to continue? [y/n] " '(?y ?n)))) 3369 | (cond 3370 | ((eq answer ?y) 3371 | (async-shell-command " rsync -avbih --exclude '.git' --exclude '.svn' --delete \ 3372 | ~/Documents/emacs/02-binary-git/binary-files/ lewis-nas@192.168.31.108:/share/my_webdav/rsync/02-binary-git/binary-files/")) 3373 | ((eq answer ?n) (message "transfer exit"))))) 3374 | 3375 | (defun rsync-pull-binary-files() 3376 | (interactive) 3377 | (async-shell-command " rsync -avbih --exclude '.git' --exclude '.svn' --delete\ 3378 | lewis-nas@192.168.31.108:/share/my_webdav/rsync/02-binary-git/binary-files/ ~/Documents/emacs/02-binary-git/binary-files/")) 3379 | 3380 | (transient-define-prefix backup-leader-map() 3381 | "Define leader-key map for backup functions" 3382 | [["rsync" 3383 | ("p" "push doc" rsync-push-binary-files) 3384 | ("F" "pull doc" rsync-pull-binary-files)]]) 3385 | #+end_src 3386 | ** server 3387 | #+begin_src elisp 3388 | (setup server 3389 | (progn 3390 | (require 'server) 3391 | (unless (server-running-p) 3392 | (server-start)) 3393 | )) 3394 | #+end_src 3395 | ** macos-ocr 3396 | #+begin_src elisp 3397 | (defun my/siri-ocr () 3398 | (interactive) 3399 | (shell-command "shortcuts run \"OCR Selected Area\"") 3400 | (do-applescript "tell application id \"org.gnu.Emacs\" to activate") 3401 | ) 3402 | (keymap-global-set "C-c M-o" #'my/siri-ocr) 3403 | #+end_src 3404 | ** esup 3405 | ESUP - Emacs Start Up Profiler 3406 | #+begin_src elisp 3407 | (setup esup 3408 | ;; (if (eq system-type 'darwin) 3409 | (setq esup-depth 0) 3410 | ;; ) 3411 | ) 3412 | #+end_src 3413 | ** uniline 3414 | #+begin_src elisp 3415 | (setup uniline 3416 | (:bind "M-i" #'uniline-launch-interface) 3417 | ) 3418 | (setup uniline-transient 3419 | (:autoload uniline-mode uniline-launch-interface) 3420 | ) 3421 | #+end_src 3422 | ** excalidraw 3423 | #+begin_src elisp 3424 | (setq org-excalidraw-default-directory (concat denote-directory "/excalidraw/")) 3425 | (defconst org-excalidraw-default-template 3426 | "{ 3427 | \"type\": \"excalidraw\", 3428 | \"version\": 2, 3429 | \"source\": \"https://excalidraw.com\", 3430 | \"elements\": [], 3431 | \"appState\": { 3432 | \"gridSize\": null, 3433 | \"viewBackgroundColor\": \"#ffffff\" 3434 | }, 3435 | \"files\": {} 3436 | } 3437 | " 3438 | "excalidraw template in JSON.") 3439 | 3440 | (defun org-excalidraw-create-drawing () 3441 | "Create an excalidraw drawing and optionally insert an org-mode link at point." 3442 | (interactive) 3443 | (let* ((directory (if org-excalidraw-default-directory 3444 | (expand-file-name org-excalidraw-default-directory) 3445 | nil)) 3446 | (temp-path (concat directory "temp.excalidraw")) 3447 | (origin-buffer (current-buffer)) 3448 | (new-buf (find-file-noselect temp-path)) 3449 | (new-path (with-current-buffer new-buf 3450 | (insert org-excalidraw-default-template) 3451 | (save-buffer) 3452 | (let ((new-path (call-interactively #'denote-rename-file))) 3453 | (embark-open-externally new-path) 3454 | new-path)) 3455 | )) 3456 | (switch-to-buffer origin-buffer) 3457 | (when (derived-mode-p 'org-mode) 3458 | (insert (format "[[file:%s]]" new-path))))) 3459 | #+end_src 3460 | ** manage-web-bookmarks 3461 | #+begin_src elisp 3462 | (setq org-bookmarks-file (concat nowis-doc-emacs-dir "01-orgmode/xnotes/20250731T173729--bookmarks.org")) 3463 | (defun my/add-bookmark () 3464 | "add bookmark for url into org files" 3465 | (interactive) 3466 | (let ((url (read-string "URL: ")) 3467 | (title (read-string "TiTle: ")) 3468 | (timestamp (format-time-string "[%Y-%m-%d %a %H:%M]"))) 3469 | (with-current-buffer (find-file-noselect org-bookmarks-file) 3470 | (goto-char (point-max)) 3471 | (insert (format "\n* %s\n[[%s]]\n added: %s\n" title url timestamp)) 3472 | (save-buffer)))) 3473 | 3474 | (defun my/consult-org-bookmarks () 3475 | "A bookmark browser based on consult-org-heading, will return to origin place after opening url" 3476 | (interactive) 3477 | (let ((original-buffer (current-buffer)) 3478 | (original-point (point))) 3479 | (find-file org-bookmarks-file) 3480 | (condition-case err 3481 | (progn 3482 | (consult-org-heading) 3483 | (let ((url (save-excursion 3484 | (forward-line 1) 3485 | (when (looking-at "\\[\\[\\([^]]+\\)\\]\\]") 3486 | (match-string 1))))) 3487 | (when url 3488 | (if (not (featurep 'embark)) 3489 | (require 'embark)) 3490 | (embark-open-externally url))) 3491 | (switch-to-buffer original-buffer) 3492 | (goto-char original-point)) 3493 | (quit 3494 | (switch-to-buffer original-buffer) 3495 | (goto-char original-point)) 3496 | (error 3497 | (switch-to-buffer original-buffer) 3498 | (goto-char original-point) 3499 | (signal (car err) (cdr err)))))) 3500 | #+end_src 3501 | * games 3502 | ** minesweeper 3503 | #+begin_src elisp 3504 | (setup minesweeper 3505 | (setq gamegrid-user-score-file-directory (concat nowis-doc-emacs-dir "66-gamegrid-user-score")) 3506 | ) 3507 | #+end_src 3508 | * system-specific-config 3509 | ** windows-wslg 3510 | These codes are used to solve copy & paste problems under wslg inside win10/win11 3511 | #+begin_src elisp 3512 | ;; solve the problem of copying from windows to wslg 3513 | (if (string= "Arch" (getenv "WSL_DISTRO_NAME")) 3514 | (progn 3515 | ;; (set-clipboard-coding-system 'gbk-dos) 3516 | ;; solve the problem of copying from wslg to windows 3517 | (defun wsl-copy-region-to-clipboard (start end) 3518 | "Copy region to Windows clipboard." 3519 | (interactive "r") 3520 | (call-process-region start end "wl-copy" nil 0)) 3521 | 3522 | (defun wsl-clipboard-to-string () 3523 | "Return Windows clipboard as string." 3524 | (let ((coding-system-for-read 'dos)) 3525 | (substring; remove added trailing \n 3526 | (shell-command-to-string 3527 | "wl-paste") 0 -1))) 3528 | (defun wsl-paste-from-clipboard (arg) 3529 | "Insert Windows clipboard at point. With prefix ARG, also add to kill-ring" 3530 | (interactive "P") 3531 | (let ((clip (wsl-clipboard-to-string))) 3532 | (insert clip) 3533 | (if arg (kill-new clip)))) 3534 | (global-set-key [remap kill-ring-save] #'wsl-copy-region-to-clipboard) 3535 | (global-set-key [remap meow-yank] #'wsl-paste-from-clipboard) 3536 | )) 3537 | #+end_src 3538 | ** android 3539 | #+begin_src elisp 3540 | (if (eq system-type 'android) 3541 | (progn 3542 | (setq touch-screen-display-keyboard t) 3543 | (setq overriding-text-conversion-style nil) 3544 | )) 3545 | (defun android-toggle-keyboard() 3546 | (interactive) 3547 | (if touch-screen-display-keyboard 3548 | (progn 3549 | (setq touch-screen-display-keyboard nil) 3550 | (tool-bar-add-item 3551 | "keyboard-off" 'android-toggle-keyboard 3552 | 'android-toggle-keyboard 3553 | :help "Toggle keyboard") 3554 | (message "Disable virtual keyboard")) 3555 | (setq touch-screen-display-keyboard t) 3556 | (tool-bar-add-item 3557 | "keyboard" 'android-toggle-keyboard 3558 | 'android-toggle-keyboard 3559 | :help "Toggle keyboard") 3560 | (message "Enable virtual keyboard"))) 3561 | #+end_src 3562 | --------------------------------------------------------------------------------