From 6bdf6db3b453cff3a3f46f1b8f33cac6426f98ac Mon Sep 17 00:00:00 2001 From: dx Date: Wed, 15 Jul 2020 15:56:08 +0100 Subject: ~~/.doom.d -> ~/.config/doom --- Doom/.config/doom/org/config.org | 354 +++++++++++++++++++++++++++++++++++++ Doom/.config/doom/org/literate.org | 105 +++++++++++ Doom/.config/doom/org/packages.org | 59 +++++++ Doom/.config/doom/org/personal.org | 101 +++++++++++ 4 files changed, 619 insertions(+) create mode 100644 Doom/.config/doom/org/config.org create mode 100644 Doom/.config/doom/org/literate.org create mode 100644 Doom/.config/doom/org/packages.org create mode 100644 Doom/.config/doom/org/personal.org (limited to 'Doom/.config/doom/org') diff --git a/Doom/.config/doom/org/config.org b/Doom/.config/doom/org/config.org new file mode 100644 index 0000000..e0bf129 --- /dev/null +++ b/Doom/.config/doom/org/config.org @@ -0,0 +1,354 @@ +#+TITLE: Oreodave's Emacs configuration +#+AUTHOR: Oreodave +#+DESCRIPTION: My Doom Emacs configuration! + +* Preclude +- This is my [[https://github.com/hlissner/doom-emacs][Doom Emacs]] configuration. +- Use it for most of my code editing and development needs. +- Incredibly versatile tool in my inventory. +* Initial setup +** Doom Variables +- Set the doom local-leader to "SPC ," because it's faster +- Good font choices: + - Hack + - Source Code Pro/Variable + - IBM Plex Mono + - Space Mono + - Z003 if I'm feeling fancy (▀̿Ĺ̯▀̿̿) +#+BEGIN_SRC elisp +(after! core-keybinds + (map! :leader "," nil) + (setq doom-localleader-key "SPC ,") + (setq doom-themes-enable-italic nil) + (setq doom-themes-enable-bold t) + (setq doom-theme 'doom-monokai-classic) + (setq doom-font (font-spec :family "Source Code Pro" :size 15))) +#+END_SRC +** Other variables +Some quality of life things and others that I couldn't really put in one category +- Using line-numbers that are relative now instead of nothing. +- Set org directory +- Add libgen to search providers +#+BEGIN_SRC elisp +(setq completion-ignore-case t + truncate-lines t + display-line-numbers-type t + bookmark-default-file (expand-file-name (concat doom-private-dir "bookmarks"))) +(setq-default frame-title-format '("%b - Emacs")) +(add-to-list 'default-frame-alist '(alpha . 90)) +(cl-pushnew '("Libgen" "http://gen.lib.rus.ec/search.php?req=%s") +lookup-provider-url-alist :key #'car :test 'string=) +#+END_SRC +** HACK: Load org mode again? +#+BEGIN_SRC elisp +(load (expand-file-name (concat user-emacs-directory "modules/lang/org/config.el"))) +#+END_SRC +* Package Configuration +Configuration for or based heavily around specific packages that I find very important +** Ido +Just add vimish keybindings to ido completion +#+BEGIN_SRC elisp +(map! + :map (ido-common-completion-map ido-file-completion-map ido-buffer-completion-map) + "C-k" #'ido-prev-match + "C-j" #'ido-next-match) + +(setq ido-ignore-buffers '("\\` " "^\\*ESS\\*" "^\\*[Hh]elp" "^\\*.*Completions\\*$" "^\\*tramp" "^\\*cvs-" "^*Ido")) +#+END_SRC +** DAP +*** Function +First to setup is a routine for setting up all the dap-panes for debugging. +Easier to do than just running all those functions manually +- Routine sets up the panes that I like to use, instead of M-x'ing it +- *cD* starts up the routine +#+BEGIN_SRC elisp +(after! dap-mode + (defun dx:debug () + (interactive) + (dap-ui-mode) + (dap-ui-locals) + (dap-ui-sessions))) +#+END_SRC +*** Keybind +#+BEGIN_SRC elisp +(map! + :after dap-mode + :leader + :desc "Start debugging setup" "cD" #'dx:debug) +#+END_SRC +** Spelling checker +Keybinds to org-mode for flyspell package +#+BEGIN_SRC elisp +(map! + :after (flyspell org) + :localleader + :map org-mode-map + :prefix "w" + :desc "Correct current word" "c" #'flyspell-correct-at-point + :desc "Autocorrect word" "a" #'flyspell-auto-correct-word + :desc "Goto next error" "w" #'flyspell-goto-next-error) +#+END_SRC +** Projectile +Add CMakeLists.txt to projectile-project-roots. +#+BEGIN_SRC elisp +(after! projectile + (cl-pushnew "CMakeLists.txt" projectile-project-root-files :test 'string=) + (setq projectile-tags-command + "ctags -e -R --exclude=dist --exclude=.ccls --exclude=.ccls-cache")) +#+END_SRC +** Prettify symbols +Configuration for the module (pretty-code). +*** Setup symbols +Some symbols aren't present in the current doom version, or my fonts are screwing up, so I wrote them here. +Maybe a bit of a bandage over broken glass, but at least it's something. +#+BEGIN_SRC elisp +(setq +pretty-code-symbols + '(:name "»" + :src_block "»" + :src_block_end "«" + :quote "“" + :quote_end "”" + :lambda "λ" + :def "ƒ" + :composition "∘" + :map "↦" + :null "∅" + :true "𝕋" + :false "𝔽" + :int "ℤ" + :float "ℝ" + :str "𝕊" + :bool "𝔹" + :not "¬" + :in "∈" + :not-in "∉" + :and "∧" + :or "∨" + :for "∀" + :some "∃" + :return "⟼" + :yield "⟻" + :tuple "⨂" + :pipe "|" + :dot "•")) +#+END_SRC + +The 'x' symbol in the =+pretty-code-fira-code-font-ligatures= is annoying, and unneeded. +So I remove it. +#+BEGIN_SRC elisp +(assoc-delete-all "x" +pretty-code-fira-code-font-ligatures #'string=) +#+END_SRC +*** Pretty symbols +Setup pretty symbols specifically for C++. +I import the string type via `using std::string` which isn't supported in standard doom so I added support for it as well. +#+BEGIN_SRC elisp +(after! cc-mode + (set-pretty-symbols! + '(c-mode c++-mode) + :return "return" + :or "||" + :and "&&" + :not "!" + :bool "bool" + :str "string" + :str "std::string" + :float "float" + :int "int" + :false "false" + :true "true" + :null "nullptr")) +#+END_SRC +** Calc +*** Configuration +#+BEGIN_SRC elisp +(use-package! calc + :config + (setq calc-angle-mode 'rad) + (map! + :leader + :desc "Calc" ":" #'calc)) +#+END_SRC +** Dired and ranger +I like doing shell comamnds from dired, but I don't want Emacs to hang when doing them. +So, as '!' is a common use command and "&" is the async comamnd, I'll just switcheroo the "!" and "&" for their designated commands. +#+BEGIN_SRC elisp +(map! + :map dired-mode-map + :n "!" #'dired-do-async-shell-command + :n "&" #'dired-do-shell-command) +#+END_SRC +** Compilation +Add keybind to recompile (inside the buffer) +#+BEGIN_SRC elisp +(map! + (:map 'compilation-mode-map + :n "u" #'recompile)) +#+END_SRC +** Company +#+BEGIN_SRC elisp +(add-hook + 'company-mode-hook + #'(lambda () (setq company-frontends '(company-preview-frontend company-pseudo-tooltip-frontend)))) +#+END_SRC +* Language Configuration +Configuration for various languages which I feel can be useful +** C-style languages +Configuration for C and C++. +Emacs doesn't have the full range of styles that I want, so lemme just do it myself. +#+BEGIN_SRC elisp +(after! cc-mode + (c-add-style + "user" + '((c-basic-offset . 2) + (c-comment-only-line-offset . 0) + (c-hanging-braces-alist (brace-list-open) + (brace-entry-open) + (substatement-open after) + (block-close . c-snug-do-while) + (arglist-cont-nonempty)) + (c-cleanup-list brace-else-brace) + (c-offsets-alist + (statement-block-intro . +) + (knr-argdecl-intro . 0) + (substatement-open . 0) + (substatement-label . 0) + (access-label . 0) + (label . 0) + (statement-cont . +)))) + (setq c-default-style "user")) +#+END_SRC +** Python +Configuration for the Python language in doom +*** Set interpreter and flycheck to Python 3 +I do python development for Python3 so I need to set the flycheck python checker, as well as the interpreter, to be Python3 +#+BEGIN_SRC elisp +(after! python + (setq python-version-checked t) + (setq python-python-command "python3") + (setq python-shell-interpreter "python3") + (setq flycheck-python-pycompile-executable "python3")) +#+END_SRC +*** Map to python-mode-map +Most of my python work is in scripts or ideas, so I don't need extensive testing utilities or anything like that +I adhere greatly to the REPL in python, so I need access to it often. +#+BEGIN_SRC elisp +(after! python + (map! ; Python keybinds + :map python-mode-map + :localleader + :desc "Start python minor" "c" #'run-python + :desc "Format buffer" "=" #'py-yapf-buffer + (:prefix "s" + :desc "Send region REPL" "r" #'python-shell-send-region + :desc "Send buffer" "b" #'python-shell-send-buffer + :desc "Send function" "f" #'python-shell-send-defun))) +#+END_SRC +** Typescript +- Typescript (in my opinion) should be indented by 2 +- Setup the LSP server on the lsp-language-id-config in case it hasn't already +#+BEGIN_SRC elisp +(after! typescript-mode + (setq typescript-indent-level 2) + (setq tide-format-options '(:indentSize 2 :tabSize 2)) + (after! lsp + (cl-pushnew '(typescript-mode . "typescript") lsp-language-id-configuration :key #'car) + (lsp-register-client + (make-lsp-client + :new-connection (lsp-stdio-connection "typescript-language-server --stdio") + :major-modes '(typescript-mode) + :server-id 'typescript)))) +#+END_SRC +** Org +Org configuration to maximise org workflow. +*** Org variables +Setup the agenda-files and the org-directory. +#+BEGIN_SRC elisp +(after! org + (add-hook 'org-mode-hook #'visual-line-mode) + (add-hook 'org-mode-hook #'org-toggle-latex-fragment) + (setq org-directory "~/Text" + org-agenda-files '("~/Text/") + org-src-window-setup 'split-window-right + org-superstar-headline-bullets-list '("◉" "‣" "⧈" "⬠") + org-log-repeat 'note)) +#+END_SRC +*** Fragtog +#+BEGIN_SRC elisp +(use-package! org-fragtog + :config + (add-hook 'org-mode-hook #'org-fragtog-mode)) +#+END_SRC +*** Thesaurus +Powerthesaurus installation, added a keybind in org-mode for looking up words. +#+BEGIN_SRC elisp +(use-package! powerthesaurus + :after-call (org-mode) + :defer-incrementally (org) + :config + (map! + :localleader + :map org-mode-map + :prefix "w" + :desc "Thesaurus" "t" #'powerthesaurus-lookup-word-at-point)) +#+END_SRC +Powerthesaurus for thesaurus on writer files +*** Org keymap +- I like using org-export often, so bind it to a primary bind. +- Loading latex fragments is nice +#+BEGIN_SRC elisp +(map! ; Org keybinds + :after org + :map org-mode-map + :localleader + :desc "Org dispatch" "e" #'org-export-dispatch + :desc "Org LaTeX" "E" #'org-latex-export-as-latex) +#+END_SRC +** Haskell +Setup repl binds for Haskell +#+BEGIN_SRC elisp +(map! + :after haskell-mode + :map haskell-mode-map + :localleader + "l" #'haskell-process-load-file + "r" #'haskell-process-reload + "o" #'haskell-process-start) +#+END_SRC +** Sxhkd +Define a major-mode for sxhkd config files. +#+BEGIN_SRC elisp +(define-generic-mode sxhkd-mode + '(?#) + '("alt" "Escape" "super" "bspc" "ctrl" "space" "shift" "hyper" "XF86*") + '("{" "}") + '("sxhkdrc") + nil + "Simple mode for sxhkdrc files.") +#+END_SRC +* Key-map +General keymap +** Personal +- Prefix "SPC m" (rebound from local-leader) that will hold personal keybinds for functions that I like using +- Mostly opening directories I use a lot or doing custom stuff that I can't really put in anything in particular +#+BEGIN_SRC elisp +(map! + :leader + :prefix ("m" . "personal") ; Personal + :desc "Open books" "b" #'(lambda () (interactive) (dired (concat org-directory "/Books"))); I like my books + :desc "Convert auto-fill" "f" #'dx:org/fill-to-long-lines + :desc "Change theme" "t" #'dx:themes/set-new-theme ; From my own collection + :desc "Generate template" "g" #'+gentemplate/generate-template) ; From my own collection +#+END_SRC +** Remaps +Adding a new configuration option. +Remapping functions that other modules set to default functions. +#+BEGIN_SRC elisp +(define-key! + [remap compile] #'compile) +#+END_SRC +** Non-leader +Non-leader bindings for text-based commands. +#+BEGIN_SRC elisp +(map! + "M-v" #'dx:newline + "M-V" #'(lambda () (interactive) (dx:newline 1))) +#+END_SRC diff --git a/Doom/.config/doom/org/literate.org b/Doom/.config/doom/org/literate.org new file mode 100644 index 0000000..53bd6a2 --- /dev/null +++ b/Doom/.config/doom/org/literate.org @@ -0,0 +1,105 @@ +#+TITLE: Literate configuration (NO LONGER IN USE) + +* Preclude +My setup to produce a literate configuration. +Allows me to write org files all around the /doom-private-dir/ and access them. +Also shaved like 0.2s off my loading time. + +/Note/: My current literate system now uses the =org-babel-load*= functions to handle most of the hard work. +It's easier to use and manage, and I just don't use that many org files anymore so no need for such a big setup. +* Constants +Initialise some basic constants for where stuff is. +- literate/bin-dir: Where to compile to +- literate/preloaded-files: Relative to ~$DOOM~, which files are already + preloaded/don't need to be compiled +#+BEGIN_SRC elisp +(defconst dx:literate/bin-dir (expand-file-name (concat doom-private-dir "bin/")) "Directory to store elisp compiled files") +(defconst dx:literate/load-files '("~/.doom.d/org/personal.org") "Files to load after compilation") +(defconst dx:literate/directory (expand-file-name (concat doom-private-dir "org/")) "Directory to get org files from") +#+END_SRC +* Remove function +When loading the lisp, we need to load everything excluding "config.el" (preloaded by doom) and "literate.el" (loaded by "config.el"). +We'll make a very specific remove function that will remove entries from a given list and return the new list, given the fact that the files variable will be a list of fully expanded file names. +#+BEGIN_SRC elisp +(defun dx:literate/remove-mult (remove-files files) + "Remove any occurrences of `remove-files' from `files'" + (let ((parsed-remove-files (map 'list + #'(lambda (i) (expand-file-name (concat doom-private-dir i))) + remove-files))) ; Generate a list of all fully expanded files to remove + (remove-if #'(lambda (l) (member l parsed-remove-files)) files))) ; remove any files that are in the remove-files +#+END_SRC +* Destination for parser +Generate the destination for a literate config org file to parse to, in this case the bin folder in the private directory. +This is not fitted onto the parser because the parser could be fitted to multiple /differing/ outputs easily if it isn't specified a destination. +#+BEGIN_SRC elisp +(defun dx:literate/destination(SRC) + "Parse a src.org file to a bin/src.el file" + (replace-regexp-in-string ".*/\\(\\w+\\).org" + (expand-file-name (concat dx:literate/bin-dir "\\1.el")) SRC)) +#+END_SRC +* Parser +** Tangle function +First we need to get some sort of parser which can, given a source org file and a destination, parse and produce an Emacs lisp file. +We'll copy this from the literate module of doom. +#+BEGIN_SRC elisp +(defun dx:literate/tangle (SRC DEST) + "Tangle a source org file into a destination el file using a new emacs instance" + (let ((default-directory doom-private-dir)) + (when (file-newer-than-file-p SRC DEST) + (let ((output (get-buffer-create "*org-tangle*"))) + (unwind-protect + (async-shell-command + (concat "emacs " + "-q " "--batch " + "-l " "ob-tangle " + "--eval " + (format "'(org-babel-tangle-file %S %S)'" SRC DEST)) + "*org-tangle-messages*" + "*org-tangle-errors*")))))) +#+END_SRC +** Popup rules +I don't want Emacs to focus onto the output buffer of the tangling process when I save, which is what happens with a standard async-shell-command. +So setup a rule for the 'messages' and 'errors' buffers to not focus them (by setting their time to live to 0). +#+BEGIN_SRC elisp +(set-popup-rule! "\*org-tangle-.*" :ttl 0 :quit t) +#+END_SRC +* Hook on save +Now we need to make a hook function that, when the current buffer is an org file in the doom directory, will run the literate config procedure from above. +Use this hook function and add it to the after-save-hook once org mode has been loaded. +README.org has been added as an exception because it doesn't contain literate contents. +#+BEGIN_SRC elisp +(defun dx:literate/compile-hook () + "Any org file within $DOOM/org will be compiled on save" + (when (and (eq major-mode 'org-mode) + (or (file-in-directory-p buffer-file-name doom-private-dir) + (file-in-directory-p buffer-file-name (concat doom-private-dir "org"))) + (not (string= buffer-file-name (expand-file-name (concat doom-private-dir "README.org"))))) + (dx:literate/tangle buffer-file-name (dx:literate/destination buffer-file-name)))) + +(after! org + (add-hook 'after-save-hook #'dx:literate/compile-hook)) +#+END_SRC +* Procedure for all files +A procedure that parses all the org files in a given directory into Emacs lisp +files, using the parser function made. Assume all org files in the "location" +directory contribute to the config. +The location is not set because this function could be easily programmed to use +multiple /differing/ sources to produce the config. The tangle function is set +because this is the function we'll be using for tangling all org files to ELisp files. +#+BEGIN_SRC elisp +(defun dx:literate/tangle-all (&optional location) + "Tangle all org files in `location' to el files in the `destination'" + (interactive) + (or location (setq location doom-private-dir)) + (message "Starting compilation process") + (let ((files (directory-files-recursively location ".org"))) + (dolist (file files) + (message "Compiling and parsing %s" file) + (dx:literate/tangle file (dx:literate/destination file))))) +#+END_SRC +* Load configuration +Final step of the literate cycle: load the config for the first time. Load any org files in =dx:literate/load-files=. +#+BEGIN_SRC elisp +(dolist (file dx:literate/load-files) + (load (dx:literate/destination file))) +#+END_SRC diff --git a/Doom/.config/doom/org/packages.org b/Doom/.config/doom/org/packages.org new file mode 100644 index 0000000..67040fa --- /dev/null +++ b/Doom/.config/doom/org/packages.org @@ -0,0 +1,59 @@ +#+TITLE: Packages + +* Preclude +A list of extra packages I have added to doom, and justification for why. +Here are some examples of how to do packages in Doom. +#+BEGIN_SRC elisp :tangle no +(package! some-package) ;melpa +(package! another-package :recipe (:host github :repo "username/repo")) +(package! builtin-package :disable t) +#+END_SRC +* Header +Don't byte compile this, not a good idea. +#+BEGIN_SRC elisp +;; -*-no-byte-compile: t-*- +#+END_SRC +* General +** powerthesaurus +Thesaurus for Emacs, amazingly useful. +I do know that doom has it's own dictionary and thesaurus module, but I wish to use my own cos I have very specific needs +#+BEGIN_SRC elisp +(package! powerthesaurus) +#+END_SRC +* Org-mode +** Fragtog +Fragtog allows for latex segments to be instantly compiled and only when you hover over them will you get the code, similar to prettify-symbols. +#+BEGIN_SRC elisp +(package! org-fragtog :recipe (:host github :repo "io12/org-fragtog")) +#+END_SRC +* Coding +** Tags +Should really be an inbuilt feature for Ivy, as it is so damn useful. +Better than the Helm or inbuilt "TAGS" searching options as it provides ways to quickly filter data from the tag set which makes it incredibly fast. +I use it in some of my personal functions such as the global testing function I have for C# using both tags and OmniSharp. +#+BEGIN_SRC elisp +(package! counsel-etags) +#+END_SRC +** Arduino +I sometimes dabble in Arduino coding, and absolutely adore Emacs, so who says I can't make Emacs an Arduino IDE? +*** arduino-mode +Absolutely necessary for Arduino development: syntax highlighting. +I soon plan to make my own Arduino mode on the back of cc-mode, but who knows when that will happen? +#+BEGIN_SRC elisp +(package! arduino-mode) +#+END_SRC +*** company-arduino +Auto complete is essential to make the ultimate IDE experience™. Thus, company-arduino. +#+BEGIN_SRC elisp +(package! company-arduino) +#+END_SRC +** YAML +YAML packages which I think would be cool to use: +- yaml-mode is just necessary as you can't edit without coloring (in my opinion) +- yaml-imenu is a cool package for large yaml files +- flycheck-yamllint is a nice little package which +#+BEGIN_SRC elisp +(package! yaml-mode) +(package! yaml-imenu) +(package! flycheck-yamllint) +#+END_SRC diff --git a/Doom/.config/doom/org/personal.org b/Doom/.config/doom/org/personal.org new file mode 100644 index 0000000..7398769 --- /dev/null +++ b/Doom/.config/doom/org/personal.org @@ -0,0 +1,101 @@ +#+TITLE: Personal module + +* Preclude +Personal functionality or variables that aid my workflow or are just cool. +* Variables +Some user variables +#+BEGIN_SRC elisp +(setq user-full-name "Aryadev Chavali" + user-mail-address "aryadevchavali1@gmail.com") +#+END_SRC +* Change theme +Allow user to set a theme from a limited set of candidates, based on "dx:theme-list". + +- Themes sanctioned by me: + - doom-solarized-dark: just the right everything. best for day. + - doom-gruvbox: good contrast, better for night. + - doom-city-lights: Eh contrast, quite dark + - doom-outrun-electric: Interesting colour palette + - doom-vibrant: Good contrast, bit lighter + - doom-molokai/doom-monokai-classic: hacker style + - doom-solarized-light: Light orange theme that's actually okay on the eyes + - doom-acario-light: Light theme with not bad colours +- Themes not sanctioned: + - Light themes other than solarized-light and acario + - Horrid low contrast ones with no colour. Grayscale particularly. I can't + handle those. + +#+BEGIN_SRC elisp +(setq dx:themes/theme-list '(doom-solarized-dark + doom-gruvbox + doom-molokai + doom-monokai-classic + doom-solarized-light + doom-acario-light)) + +(defun dx:themes/set-new-theme () + "Set the theme from my own selection, mutate as you see fit" + (interactive) + (let ((theme (completing-read "Select theme: " dx:themes/theme-list))) + (condition-case nil + (progn + (mapc #'disable-theme custom-enabled-themes) + (load-theme (intern theme) t) + (when (fboundp 'powerline-reset) + (powerline-reset))) + (error "Problem loading theme %s" theme)))) +#+END_SRC +* Password store +Function to get a password given a key. +#+BEGIN_SRC elisp +(defun dx:password-store/get-password (KEY) + (shell-command-to-string (concat "pass " KEY))) +#+END_SRC +* Insert newlines without o/O +Insert a newline without having to exit normal mode! +#+BEGIN_SRC elisp +(defun dx:newline (&optional BACKWARD) + (interactive) + (message "%s" BACKWARD) + (let ((old (point))) + (cond ((and BACKWARD (= BACKWARD 1)) (+default/newline-above)) + (t (+default/newline-below))) + (goto-char (+ old 1)) + (evil-normal-state))) +#+END_SRC +* Convert auto-fill lines to long truncate-lines +Consider some org file with auto filled lines. +I don't like auto-filled lines. +So I want to convert them. +I've setup macros countless times to do this operation for me, may as well formalize it as a function. + +Firstly, I need a function to count the number of instances of some substring occur in some other string. +Shamelessly copied from rosetta code. +#+BEGIN_SRC elisp +(defun dx:org/count-sub (str pat) + (loop with z = 0 with s = 0 while s do + (when (setf s (cl-search pat str :start2 s)) + (incf z) (incf s (length pat))) + finally (return z))) +#+END_SRC + +Then the main function, works like so: +1) Search the text in the region for newlines then join the lines to make a single segment +2) Search for sentences through Emacs builtin =forward-sentence= and =forward-char= functions then newline via sentences +#+BEGIN_SRC elisp +(defun dx:org/fill-to-long-lines () + (interactive) + (let* ((beg (region-beginning)) + (end (region-end)) + (region-text (buffer-substring-no-properties beg end)) + (n-sentences (dx:org/count-sub region-text ".")) + (parsed-text (apply #'concatenate 'string (cl-loop for c from beg to end collect + (if (string= (buffer-substring-no-properties c (+ c 1)) "\n") " " + (buffer-substring-no-properties c (+ c 1))))))) + (delete-region beg end) + (insert parsed-text) + (message "%s" n-sentences) + (evil-normal-state) + (evil-digit-argument-or-evil-beginning-of-line) + (cl-loop for i from 1 to n-sentences do (forward-sentence) (forward-char) (newline)))) +#+END_SRC -- cgit v1.2.3-13-gbd6f