-
Notifications
You must be signed in to change notification settings - Fork 41
/
sws-mode.el
151 lines (122 loc) · 4.1 KB
/
sws-mode.el
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
;;; sws-mode.el --- (S)ignificant (W)hite(S)pace mode -*- lexical-binding: t -*-
;; Copyright 2011-2021 Brian Carlson
;; Author: Brian M. Carlson and other contributors
;; Version: 1.0.1
;; Keywords: languages
;; URL: https://github.com/brianc/jade-mode
;;; Commentary:
;; Common code for the jade-mode and stylus-mode.
;;; Code:
(require 'font-lock)
(defvar sws-tab-width 2)
(defmacro sws-line-as-string ()
"Returns the current line as a string."
`(buffer-substring (point-at-bol) (point-at-eol)))
(defun sws-previous-indentation ()
"Gets indentation of previous line"
(save-excursion
(forward-line -1)
(if (bobp) 0
(progn
(while (and (looking-at "^[ \t]*$") (not (bobp))) (forward-line -1))
(current-indentation)))))
(defun sws-max-indent ()
"Calculates max indentation"
(+ (sws-previous-indentation) sws-tab-width))
(defun sws-empty-line-p ()
"If line is completely empty"
(= (point-at-bol) (point-at-eol)))
(defun sws-point-to-bot ()
"Moves point to beginning of text"
(beginning-of-line-text))
(defun sws-do-indent-line ()
"Performs line indentation"
;;if we are not tabbed out past max indent
(if (sws-empty-line-p)
(indent-to (sws-max-indent))
(if (< (current-indentation) (sws-max-indent))
(indent-to (+ (current-indentation) sws-tab-width))
;; if at max indent move text to beginning of line
(progn
(beginning-of-line)
(delete-horizontal-space)))))
(defun sws-indent-line ()
"Indents current line"
(interactive)
(if (eq this-command 'indent-for-tab-command)
(if mark-active
(sws-indent-region (region-beginning) (region-end))
(if (sws-at-bot-p)
(sws-do-indent-line)
(sws-point-to-bot)))
(indent-to (sws-previous-indentation))))
(defun sws-at-bol-p ()
"If point is at beginning of line"
(interactive)
(= (point) (point-at-bol)))
(defun sws-at-bot-p ()
"If point is at beginning of text"
(= (point) (+ (current-indentation) (point-at-bol))))
(defun sws-print-line-number ()
"Prints line number"
(sws-print-num (point)))
(defun sws-print-num (arg)
"Prints line number"
(message (number-to-string arg)))
(defun sws-indent-to (num)
"Force indentation to level including those below current level"
(save-excursion
(beginning-of-line)
(delete-horizontal-space)
(indent-to num)))
(defun sws-move-region (begin end prog)
"Moves left is dir is null, otherwise right. prog is '+ or '-"
(save-excursion
(let (first-indent indent-diff
(num-lines-indented (count-lines-region begin end))
)
(goto-char begin)
(setq first-indent (current-indentation))
(sws-indent-to
(funcall prog first-indent sws-tab-width))
(setq indent-diff (- (current-indentation) first-indent))
(forward-line 1)
;; move other lines based on movement of first line
(dotimes (i (- num-lines-indented 1))
(sws-indent-to (+ (current-indentation) indent-diff))
(forward-line 1)))))
(defun sws-indent-region (begin end)
"Indents the selected region"
(interactive)
(sws-move-region begin end '+))
(defun sws-dendent-line ()
"De-indents current line"
(interactive)
(if mark-active
(sws-move-region (region-beginning) (region-end) '-)
(if (sws-at-bol-p)
(progn
(message "at mother fucking bol")
(delete-horizontal-space)
(indent-to (sws-max-indent)))
(let ((ci (current-indentation)))
(beginning-of-line)
(delete-horizontal-space)
(indent-to (- ci sws-tab-width))))))
(defvar sws-mode-map (make-sparse-keymap))
(define-key sws-mode-map [S-tab] 'sws-dendent-line)
(define-key sws-mode-map [backtab] 'sws-dendent-line)
;;;###autoload
(define-derived-mode sws-mode text-mode
"sws"
"Major mode for editing significant whitespace files"
;; default tab width
(setq sws-tab-width 2)
(make-local-variable 'indent-line-function)
(setq indent-line-function 'sws-indent-line)
(make-local-variable 'indent-region-function)
(setq indent-region-function 'sws-indent-region)
;; TODO needed?
(setq indent-tabs-mode nil))
(provide 'sws-mode)
;;; sws-mode.el ends here