emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[elpa] scratch/expand-region 4168da1b9d 05/23: feat: add `yaml-mode` exp


From: Stefan Monnier
Subject: [elpa] scratch/expand-region 4168da1b9d 05/23: feat: add `yaml-mode` expansions
Date: Sun, 15 Oct 2023 20:53:30 -0400 (EDT)

branch: scratch/expand-region
commit 4168da1b9d1ea5fda64754e2226af15c11140889
Author: Aaron Gonzales <aaronzinho@ucla.edu>
Commit: Magnar Sveen <magnars@gmail.com>

    feat: add `yaml-mode` expansions
---
 expand-region.el        |   1 +
 yaml-mode-expansions.el | 156 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 157 insertions(+)

diff --git a/expand-region.el b/expand-region.el
index 1c6d4b44b6..de8630eafb 100644
--- a/expand-region.el
+++ b/expand-region.el
@@ -190,6 +190,7 @@ before calling `er/expand-region' for the first time."
 (eval-after-load 'sml-mode       '(require 'sml-mode-expansions))
 (eval-after-load 'enh-ruby-mode  '(require 'enh-ruby-mode-expansions))
 (eval-after-load 'subword        '(require 'subword-mode-expansions))
+(eval-after-load 'yaml-mode      '(require 'yaml-mode-expansions))
 
 (provide 'expand-region)
 
diff --git a/yaml-mode-expansions.el b/yaml-mode-expansions.el
new file mode 100644
index 0000000000..a9c90d3b4d
--- /dev/null
+++ b/yaml-mode-expansions.el
@@ -0,0 +1,156 @@
+;;; yaml-mode-expansions.el --- expansions for yaml mode
+
+;; Copyright (C) 2021 Aaron Gonzales
+
+;; Author: Aaron Gonzales
+;; Keywords: marking region yaml YAML expand
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+;;
+;;  - Additions implemented here:
+;;    - er/mark-yaml-key-value
+;;    - er/mark-yaml-list-item
+;;    - er/mark-yaml-block
+
+;;; Code:
+
+(require 'expand-region-core)
+
+(defconst yaml-indent 2)
+
+(if (not (fboundp 'yaml-indent-offset))
+    (defalias 'yaml-indent-offset 'yaml-indent))
+
+(defvar er--yaml-key-value-regex
+  (rx (one-or-more
+       (any "0-9A-Za-z"))
+      ":"
+      (zero-or-more " ")
+      (one-or-more
+       (any "0-9A-Za-z" " '_-"))))
+
+(defvar er--yaml-list-item-regex
+  (rx (seq "- "
+           (one-or-more
+            (any "0-9A-Za-z" " '_-"))
+           "\n")))
+
+(defvar er--yaml-block-regex
+  (rx (seq (zero-or-more
+            (any " -"))
+           (one-or-more
+            (any "0-9A-Za-z" " '_-"))
+           ":\n")))
+
+(defun er--get-regex-indentation-level (regex)
+  "Return the indentation level of the code with respect to the REGEX passed."
+  (if (looking-at regex)
+      ;; Block start means that the next level is deeper.
+      (+ (current-indentation) yaml-indent-offset)
+    ;; Assuming we're inside the block that we want to mark
+    (current-indentation)))
+
+(defun er/mark-yaml-line-base (regex)
+  "Mark line of yaml file based on simple REGEX."
+  (back-to-indentation)
+  (if (looking-at regex)
+      (set-mark (line-end-position))))
+
+(defun er/mark-yaml-block-base (regex &optional next-indent-level)
+  "Mark yaml block based on REGEX passed.  NEXT-INDENT-LEVEL can be used to 
search outer blocks when necessary."
+  (back-to-indentation)
+  ;; make sure the cursor is set inside the block
+  (let ((next-indent-level
+         (or
+          ;; Use the given level
+          next-indent-level
+          ;; used to mark current block
+          ;; if true then at start of block and wanna mark itself
+          ;; else were are inside the block already and will mark it)))
+          ;; move up the code unti a parent code block is reached
+          (er--get-regex-indentation-level regex))))
+    (while (and (>= (current-indentation) next-indent-level)
+                (not (eq (current-indentation) 0)))
+      (re-search-backward regex (point-min) t)
+      (back-to-indentation))
+    ;; mark point at this higher code block
+    (set-mark (point))
+    ;; save level of this blocks indentation
+    (let ((block-indentation (current-indentation)))
+      (forward-line 1)
+      (while (and
+              ;; No need to go beyond the end of the buffer. Can't use
+              ;; eobp as the loop places the point at the beginning of
+              ;; line, but eob might be at the end of the line.
+              (not (= (point-max) (point-at-eol)))
+              ;; Proceed if: indentation is too deep
+              (or (> (current-indentation) block-indentation)
+                  ;; Looking at an empty line
+                  (looking-at (rx line-start (* whitespace) line-end))
+                  ;; We're not looking at the start of a Python block
+                  ;; and the indent is deeper than the block's indent
+                  (and (not (looking-at regex))
+                       (> (current-indentation) block-indentation))))
+        (forward-line 1)
+        (back-to-indentation))
+      ;; Find the end of the block by skipping comments backwards
+      (python-util-forward-comment -1)
+      (exchange-point-and-mark)))
+  (back-to-indentation))
+
+(defun er/mark-yaml-key-value ()
+  "Mark a yaml key-value pair."
+  (interactive)
+  (er/mark-yaml-line-base er--yaml-key-value-regex))
+
+(defun er/mark-yaml-list-item ()
+  "Mark a yaml list item."
+  (interactive)
+  (er/mark-yaml-line-base er--yaml-list-item-regex))
+
+(defun er/mark-yaml-block ()
+  "Mark the yaml block that surrounds the block around point.
+
+Command that wraps `er/mark-yaml-block-base'."
+  (interactive)
+  (er/mark-yaml-block-base er--yaml-block-regex))
+
+(defun er/mark-outer-yaml-block ()
+  "Mark the outer yaml block that surrounds the block around point.
+
+Command that wraps `er/mark-yaml-block-base'."
+  (interactive)
+  (er/mark-yaml-block-base er--yaml-block-regex (current-indentation)))
+
+(defun er/add-yaml-mode-expansions ()
+  "Add yaml-mode-specific expansions for buffers in yaml-mode."
+  (let ((try-expand-list-additions '(
+                                     er/mark-symbol
+                                     er/mark-outside-quotes
+                                     er/mark-yaml-list-item
+                                     er/mark-yaml-key-value
+                                     er/mark-yaml-block
+                                     er/mark-outer-yaml-block
+                                     mark-page)))
+    (set (make-local-variable 'expand-region-skip-whitespace) nil)
+    (set (make-local-variable 'er/try-expand-list)
+         (append try-expand-list-additions er/try-expand-list))))
+
+(er/enable-mode-expansions 'yaml-mode 'er/add-yaml-mode-expansions)
+
+(provide 'yaml-mode-expansions)
+
+;;; yaml-mode-expansions.el ends here



reply via email to

[Prev in Thread] Current Thread [Next in Thread]