From 8fd660aa7adca4abff3f776606cc2a22f0f2b230 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Joly?= Date: Sun, 21 Aug 2022 23:15:20 +0100 Subject: [PATCH] docs: automatically generate help files from code This takes the fennel code to generate documentation listing the shortcuts installed. --- .gitignore | 1 + Makefile | 21 +++++- fnl/bepo.fnl | 175 +++++++++++++++++++++------------------------ gen_doc.fnl | 113 +++++++++++++++++++++++++++++ help/bepo-nvim.txt | 120 +++++++++++++++++++++++++++++++ 5 files changed, 334 insertions(+), 96 deletions(-) create mode 100644 .gitignore create mode 100644 gen_doc.fnl create mode 100644 help/bepo-nvim.txt diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3bce614 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +bepo-nvim-mapping diff --git a/Makefile b/Makefile index 0ae0e0b..b0abeaf 100644 --- a/Makefile +++ b/Makefile @@ -1,9 +1,11 @@ fnl_files = $(wildcard fnl/*.fnl) -out_files = $(fnl_files:fnl/%.fnl=lua/%.lua) +help_file = help/bepo-nvim.txt +help_file_mapping = bepo-nvim-mapping +out_files = $(fnl_files:fnl/%.fnl=lua/%.lua) $(help_file) $(help_file_mapping) all: $(out_files) -fmt: $(fnl_files) +fmt: $(fnl_files) gen_doc.fnl fnlfmt --fix $< lua/%.lua: fnl/%.fnl lua/ @@ -15,4 +17,17 @@ lua/: clean: rm -rf lua -.PHONY: clean compile +doc: $(help_file) + +$(help_file): $(help_file_mapping) help/ + rm $(help_file) + cat $(help_file_mapping) >>$(help_file) + rm $(help_file_mapping) + +$(help_file_mapping): gen_doc.fnl $(fnl_files) + fennel --raw-errors --no-compiler-sandbox --metadata --globals '*' gen_doc.fnl > $(help_file_mapping) + +help/: + mkdir -p help + +.PHONY: clean doc $(help_file_mapping) diff --git a/fnl/bepo.fnl b/fnl/bepo.fnl index 96a035a..c51affc 100644 --- a/fnl/bepo.fnl +++ b/fnl/bepo.fnl @@ -36,104 +36,93 @@ (map-normal key target) (map-text-object key target)) -(fn mapping-movement [] - ;; on préserve {hjkl} pour les directions - (map-all :c :h) - (map-all :t :j) - (map-all :s :k) - (map-all :r :l) - (map-all :C :H) - ;; ------ - ;; {JKL} devient [TSR] - (map-all :T :J) - (map-all :S :K) - (map-all :R :L) - ;; ------ - ;; on préserve les variantes avec 'g' - (map-all :gt :gj) - (map-all :gs :gk) - ;; ------ - ;; on préserve les variantes avec 'z' - (map-all :zT :zt) - (map-all :zt :zj) - (map-all :zk :zs) - (map-all :zs :zk) - ;; ------ - ;; {t} devient [h] pour être proche de [f] - (map-all :h :t) - ;; idem pour {T} et [H] - (map-all :H :T) - ;; {c} devient [l] - (map-all :l :c) - ;; {C} devient [L] - (map-all :L :C) - ;; {j} devient [r] - (map-all :j :r) - ;; {J} devient [R] - (map-all :J :R) - ;; {k} devient [s] - (map-all :k :s) - ;; {K} devient [S] - (map-all :K :S)) +(macro 𝛅 [...] + "When called with the right context, this will print the documentation of the + mappings, instead of attempting to bind. Since we access _G, this needs to be + called with --no-compiler-sandbox (see + https://fennel-lang.org/reference#compiler-environment)" + (fn fun-to-mods [fun] + "Converts a function to the modes it sets mappings for" + (match (tostring fun) + :map-text-object :ox + :map-visual :v + :map-normal :n + :map-all :nx + other (error (.. "Unsupported function " other)))) -(fn mapping-tabs [] - ;; le couple [gb]/[gé] agit sur les tabs - (map-normal :gb :gT) - (map-normal "gé" :gt) - ;; [gB] va au premier tab - (map-normal :gB ":execute \"silent! tabfirst\"") - ;; [gÉ] au dernier - (map-normal "gÉ" ":execute \"silent! tablast\"") - ;; [gT] est libéré et peut agir sur les tags - (map-normal :gT "")) + (if _G.gen-doc + (let [args [...] + docstring (. args 3) + (docstring body-pos) (if (= :string (type docstring)) + (values docstring 4) + (values nil 3)) + body (-> args (unpack body-pos) (list) + (#(icollect [_ v (pairs $1)] + (match (type v) + :string {:comment v} + :table {:bepo (. v 2) + :qwerty (. v 3) + :modes (fun-to-mods (. v 1))} + other (error (.. "Unsupported type" other)))))) + doc-struct {:fname (. args 1) : docstring : body}] + `(local ,doc-struct.fname ,doc-struct)) + `(fn ,(unpack [...])))) -(fn mapping-easy-access [] - ;; [<] est moins accessible que [«] - (map-normal "«" "<") - (map-visual "«" "] - (map-normal "»" ">") - (map-visual "»" ">gv") - ;; idem pour [g,] et [g;] qui sont permutés - (map-all "g," "g;") - (map-all "g;" "g,") - ;; [w] est peu accessible, on utilise [é] - (map-all "é" :w) - ;; idem pour [W] et [É] - (map-all "É" :W) - ;; idem pour [aw] et [aé] - (map-text-object "aé" :aw) - ;; idem pour [aW] et [aÉ] - (map-text-object "aÉ" :aW) - ;; idem pour [iw] et [ié] - (map-text-object "ié" :iw) - ;; idem pour [iW] et [iÉ] - (map-text-object "iÉ" :iW)) +(𝛅 mapping-movement [] "on préserve {hjkl} pour les directions" + (map-all :c :h) (map-all :t :j) (map-all :s :k) (map-all :r :l) + (map-all :C :H) ;; ------ + ;; {JKL} devient [TSR] + (map-all :T :J) (map-all :S :K) (map-all :R :L) ;; ------ + ;; on préserve les variantes avec 'g' + (map-all :gt :gj) (map-all :gs :gk) ;; ------ + ;; on préserve les variantes avec 'z' + (map-all :zT :zt) (map-all :zt :zj) (map-all :zk :zs) (map-all :zs :zk) + ;; ------ + ;; {t} devient [h] pour être proche de [f] + (map-all :h :t) ;; idem pour {T} et [H] + (map-all :H :T) ;; {c} devient [l] + (map-all :l :c) ;; {C} devient [L] + (map-all :L :C) ;; {j} devient [r] + (map-all :j :r) ;; {J} devient [R] + (map-all :J :R) ;; {k} devient [s] + (map-all :k :s) ;; {K} devient [S] + (map-all :K :S)) -(fn mapping-window [] - ;; [w] est libre pour faire - (map-normal :w :) - ;; et [w] pour faire - (map-normal :W :) - ;; on map [w]+direction, miniscule + majuscule - (map-normal :wc :h) - (map-normal :wt :j) - (map-normal :ws :k) - (map-normal :wr :l) - (map-normal :wC :H) - (map-normal :wT :J) - (map-normal :wS :K) - (map-normal :wR :L) - ;; crée un split _h_orizontal - (map-normal :wh :s) - ;; va en haut à gauche - (map-normal "wé" :t) - ;; déplace sur un nouveau tab - (map-normal "wÉ" :T)) +(𝛅 mapping-tabs [] ;; le couple [gb]/[gé] agit sur les tabs + (map-normal :gb :gT) (map-normal "gé" :gt) ;; [gB] va au premier tab + (map-normal :gB ":execute \"silent! tabfirst\"") ;; [gÉ] au dernier + (map-normal "gÉ" ":execute \"silent! tablast\"") + ;; [gT] est libéré et peut agir sur les tags + (map-normal :gT "")) + +(𝛅 mapping-easy-access [] ;; [<] est moins accessible que [«] + (map-normal "«" "<") (map-visual "«" :] + (map-normal "»" ">") (map-visual "»" :>gv) + ;; idem pour [g,] et [g;] qui sont permutés + (map-all "g," "g;") (map-all "g;" "g,") + ;; [w] est peu accessible, on utilise [é] + (map-all "é" :w) ;; idem pour [W] et [É] + (map-all "É" :W) ;; idem pour [aw] et [aé] + (map-text-object "aé" :aw) ;; idem pour [aW] et [aÉ] + (map-text-object "aÉ" :aW) ;; idem pour [iw] et [ié] + (map-text-object "ié" :iw) ;; idem pour [iW] et [iÉ] + (map-text-object "iÉ" :iW)) + +(𝛅 mapping-window [] ;; [w] est libre pour faire + (map-normal :w :) ;; et [w] pour faire + (map-normal :W :) ;; on map [w]+direction, miniscule + majuscule + (map-normal :wc :h) (map-normal :wt :j) (map-normal :ws :k) + (map-normal :wr :l) (map-normal :wC :H) (map-normal :wT :J) + (map-normal :wS :K) (map-normal :wR :L) + ;; crée un split _h_orizontal + (map-normal :wh :s) ;; va en haut à gauche + (map-normal "wé" :t) ;; déplace sur un nouveau tab + (map-normal "wÉ" :T)) (fn setup [] - "Keys that are still free: - * , and ; as they may be used as leaders (if you don’t use those as leaders, you may want to swap the two) + "In any case, the following keys are always free for you to remap as you see fit: + * , and ; as they may be used as leaders (if you don’t use those as leaders, + you may want to swap the two) * à and À * ç and Ç * è and È" diff --git a/gen_doc.fnl b/gen_doc.fnl new file mode 100644 index 0000000..ab8ab6d --- /dev/null +++ b/gen_doc.fnl @@ -0,0 +1,113 @@ +;; bepo.nvim: bepo mapping for neovim +;; Copyright 2022 Clément Joly +;; +;; Licensed under the Apache License, Version 2.0 (the "License"); +;; you may not use this file except in compliance with the License. +;; You may obtain a copy of the License at +;; +;; http://www.apache.org/licenses/LICENSE-2.0 +;; +;; Unless required by applicable law or agreed to in writing, software +;; distributed under the License is distributed on an "AS IS" BASIS, +;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +;; See the License for the specific language governing permissions and +;; limitations under the License. +;; + +(local fennel (require :fennel)) + +(fn ==== [] + (print (string.rep "=" 80))) + +(fn ---- [] + (print (string.rep "-" 80))) + +(fn right-align [str max] + (let [len (length str)] + (.. str (string.rep " " (- max len))))) + +(fn print-mapping-struct [struct] + (match struct + {: bepo : modes : qwerty} + (print (string.format "%6s %5s %s" modes bepo qwerty)) + _ (error (.. "Received an invalid struct" (fennel.view struct))))) + +(fn print-lua-import [name] + (->> (values (right-align (string.format "require(\"bepo\").%s()" name) 46) + (.. :*bepo.nvim- name "*")) + (string.format "%s %35s") + (print))) + +(set _G.gen-doc true) +(local bepo (require :fnl/bepo)) + +;; Content of the help file +(print "*bepo.nvim* mappings for the bépo layout + + + +Author: Clément Joly +Homepage: +License: APACHE license + + + Type |gO| to see the table of contents. +") + +(====) + +(print "USAGE *bepo.nvim-usage* + +For a basic setup with all mappings defined, just add the following to your +init.lua: + *bepo.nvim-setup* + + require(\"bepo\").setup() + +See |bepo.nvim-cherry-pick| to apply only some groups of mapping. By default, +setup() applies all mapping groups. +") + +(print " *bepo.nvim-always-free*") + +(print (fennel.metadata:get bepo.setup :fnl/docstring)) +(print "") + +(====) +(print "MAPPING CHERRY-PICK *bepo.nvim-cherry-pick* + +You can also pick only some groups of mapping, for instance because you have +your own preferences for some key that don’t match this extension. To apply +only the “window” and “movement” groups of mapping, use this instead of +|bepo.nvim-setup| in your init.lua: + + require(\"bepo\").movement() + require(\"bepo\").window() + +The following subsections go into details of exactly what mappings are +in each group. “Modes” have the same meaning as in the |map-table|. +") + +(let [tbl (collect [name docstruct (pairs bepo)] + (if (= name :setup) + nil + (values name docstruct)))] + (do + (table.sort tbl) + (each [name docstruct (pairs tbl)] + (do + (----) + (print-lua-import name) + (-?> docstruct (?. :docstring) print) + (print "") + (if (> (length docstruct.body) 0) + (print-mapping-struct {:bepo :Bepo :modes :Modes :qwerty :Qwerty})) + (each [_ mapping-struct (pairs docstruct.body)] + (match mapping-struct + {:comment c} (print c) + _ (print-mapping-struct mapping-struct))) + (print ""))))) + +;; We split the vim and the : to prevent vim from picking up that for the fennel file +(print (.. "\nvim" ":tw=78:ts=8:ft=help:norl:")) + diff --git a/help/bepo-nvim.txt b/help/bepo-nvim.txt new file mode 100644 index 0000000..62c13b2 --- /dev/null +++ b/help/bepo-nvim.txt @@ -0,0 +1,120 @@ +*bepo.nvim* mappings for the bépo layout + + + +Author: Clément Joly +Homepage: +License: APACHE license + + + Type |gO| to see the table of contents. + +================================================================================ +USAGE *bepo.nvim-usage* + +For a basic setup with all mappings defined, just add the following to your +init.lua: + *bepo.nvim-setup* + + require("bepo").setup() + +See |bepo.nvim-cherry-pick| to apply only some groups of mapping. By default, +setup() applies all mapping groups. + + *bepo.nvim-always-free* +In any case, the following keys are always free for you to remap as you see fit: + * , and ; as they may be used as leaders (if you don’t use those as leaders, + you may want to swap the two) + * à and À + * ç and Ç + * è and È + +================================================================================ +MAPPING CHERRY-PICK *bepo.nvim-cherry-pick* + +You can also pick only some groups of mapping, for instance because you have +your own preferences for some key that don’t match this extension. To apply +only the “window” and “movement” groups of mapping, use this instead of +|bepo.nvim-setup| in your init.lua: + + require("bepo").movement() + require("bepo").window() + +The following subsections go into details of exactly what mappings are +in each group. “Modes” have the same meaning as in the |map-table|. + +-------------------------------------------------------------------------------- +require("bepo").movement() *bepo.nvim-movement* +on préserve {hjkl} pour les directions + + Modes Bepo Qwerty + nx c h + nx t j + nx s k + nx r l + nx C H + nx T J + nx S K + nx R L + nx gt gj + nx gs gk + nx zT zt + nx zt zj + nx zk zs + nx zs zk + nx h t + nx H T + nx l c + nx L C + nx j r + nx J R + nx k s + nx K S + +-------------------------------------------------------------------------------- +require("bepo").window() *bepo.nvim-window* + + Modes Bepo Qwerty + n w + n W + n wc h + n wt j + n ws k + n wr l + n wC H + n wT J + n wS K + n wR L + n wh s + n wé t + n wÉ T + +-------------------------------------------------------------------------------- +require("bepo").easy_access() *bepo.nvim-easy_access* + + Modes Bepo Qwerty + n « < + v « + v » >gv + nx g, g; + nx g; g, + nx é w + nx É W + ox aé aw + ox aÉ aW + ox ié iw + ox iÉ iW + +-------------------------------------------------------------------------------- +require("bepo").tabs() *bepo.nvim-tabs* + + Modes Bepo Qwerty + n gb gT + n gé gt + n gB :execute "silent! tabfirst" + n gÉ :execute "silent! tablast" + n gT + + +vim:tw=78:ts=8:ft=help:norl: