macros.fnl 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. ;;; macros.fnl - useful macros
  2. ;; Helpful keymaping functions
  3. (lambda bind! [modes key cmd ?a1 ?a2]
  4. (let [desc (or ?a2 ?a1)
  5. buf (if (and ?a1 ?a2) ?a1 ?a2)
  6. opts { :noremap true
  7. :silent true
  8. :buffer buf }]
  9. (when desc
  10. (tset opts :desc desc))
  11. (if (table? modes)
  12. (let [output {}]
  13. (each [_ mode (ipairs modes)]
  14. (table.insert output `(vim.keymap.set ,mode ,key ,cmd ,opts)))
  15. output)
  16. `(vim.keymap.set ,modes ,key ,cmd ,opts))))
  17. ;; Better autocommands
  18. (lambda hook! [hooks ?patterns callback]
  19. (let [hook_table (if (= (type hooks) :table)
  20. hooks
  21. [ hooks ])
  22. pattern_table (if (not ?patterns)
  23. []
  24. (= (type ?patterns) :table)
  25. ?patterns
  26. [ ?patterns ])]
  27. (var group (.. (tostring (math.random 0 1000000000) "-config-hook")))
  28. (each [_ hook (ipairs hook_table)]
  29. (set group (.. group "-" hook)))
  30. (each [_ pattern (ipairs pattern_table)]
  31. (set group (.. group "-" pattern)))
  32. `(vim.api.nvim_create_autocmd ,hook_table
  33. { :group
  34. (vim.api.nvim_create_augroup ,group
  35. { :clear true })
  36. :pattern ,pattern_table
  37. :callback ,callback })))
  38. ;; Utility functions for use!
  39. (lambda create-list-entries [...]
  40. (let [output { :active-entry nil
  41. :entries {} }]
  42. (lambda output.process [self entry]
  43. (var result false)
  44. (when self.active-entry
  45. (if (and (. self :entries self.active-entry :is-first)
  46. (not (list? entry)))
  47. (do (tset self :entries self.active-entry :data entry)
  48. (set self.active-entry nil)
  49. (set result true))
  50. (= (type entry) :string)
  51. (set self.active-entry nil)
  52. (do (table.insert (. self :entries self.active-entry :data) entry)
  53. (tset self :entries self.active-entry :is-first false)
  54. (set result true))))
  55. (when (and (= (type entry) :string) (. self :entries entry))
  56. (assert-compile (not (. self :entries entry :present))
  57. (.. "':" entry "' cannot appear more than once in `use'"))
  58. (set self.active-entry entry)
  59. (tset self :entries entry :present true)
  60. (set result true))
  61. result)
  62. (lambda output.splice-into [self other]
  63. (each [name entry (pairs self.entries)]
  64. (when entry.present
  65. (tset other name entry.data))))
  66. (each [_ val (ipairs [...])]
  67. (tset output :entries val { :present false :is-first true :data `(lambda [])}))
  68. output))
  69. ;; Nicer macro for use
  70. ;; :config acts like use-package's :init and :config options,
  71. ;; taking in the following lisp expressions as its arguments
  72. (lambda use! [repo ...]
  73. (local output [ repo ])
  74. (var last_key nil)
  75. (var list_entries (create-list-entries :config :setup
  76. :run))
  77. (each [_ val (ipairs [...])]
  78. (if last_key
  79. (do (tset output last_key val)
  80. (set last_key nil))
  81. (not (list_entries:process val))
  82. (set last_key val)))
  83. (list_entries:splice-into output)
  84. `(use ,output))
  85. ;; Call a plugin's `setup function'
  86. (lambda setup! [pkg ...]
  87. (local output [ ])
  88. (var last_key nil)
  89. (each [_ val (ipairs [...])]
  90. (if last_key
  91. (do (tset output last_key val)
  92. (set last_key nil))
  93. (set last_key val)))
  94. `((. (require ,pkg) :setup) ,output))
  95. ;; Call module function
  96. (lambda module-call! [mod func ...]
  97. `((. (require ,mod) ,func) ,...))
  98. ;; Return module function
  99. (lambda module-fn! [mod func]
  100. `(. (require ,mod) ,func))
  101. ;; Basically does what the Emacs function of the same name does.
  102. ;; Wraps the code inside with a `winsaveview' and `winrestview'
  103. (lambda save-excursion! [...]
  104. (let [args [...]
  105. len (# args)]
  106. (tset args len `(let [retvar# ,(. args len)]
  107. (vim.fn.winrestview save#)
  108. retvar#))
  109. `(let [save# (vim.fn.winsaveview)]
  110. ,(unpack args))))
  111. {: bind!
  112. : hook!
  113. : use!
  114. : setup!
  115. : module-call!
  116. : module-fn!
  117. : save-excursion!}