camlspotter avatar camlspotter committed 4ded14c

now something working

Comments (0)

Files changed (1)

 
 (eval-when-compile (require 'cl)) ; for `destructuring-bind'
 
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; basic things
+
+;; get the line string at the point
+(defun offside-trap-string-of-line ()
+  (buffer-substring-no-properties
+   (point-at-bol) (point-at-eol)))
+
+;; goto line
+(defun offside-trap-goto-line (line)
+  (goto-char (point-min))
+  (forward-line (1- line)))
+
+;; line positions
+(defun offside-trap-bol (line)
+  (save-excursion
+    (offside-trap-goto-line line)
+    (point-at-bol)))
+
+(defun offside-trap-eol (line)
+  (save-excursion
+    (offside-trap-goto-line line)
+    (point-at-eol)))
+
+;; move the point to the indent head of the line
+(defun offside-trap-move-to-indent-head ()
+  (goto-char (+ (point-at-bol) (current-indentation))))
+
+;; move the point to the first non space char from the current pos
+(defun offside-trap-move-to-non-space-char ()
+  (let ((found (search-forward-regexp "[^ ]" (point-at-eol) t)))
+    (if found (progn (backward-char) t) nil)))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; overlay
+
 ;; the overlay
 (defvar offside-trap-overlay (make-overlay 1 1))
 (defface offside-trap-face
   :group 'offside-trap)
 (overlay-put offside-trap-overlay 'face 'offside-trap-face)
 
-;; get the line string at the point
-(defun offside-trap-string-of-line ()
-  (buffer-substring-no-properties
-   (line-beginning-position) (line-end-position)))
+;; put the overlay for the sticky lines
+(defun offside-trap-overlay-sticky-lines (start end)
+    (move-overlay offside-trap-overlay
+		  start
+		  end
+		  (current-buffer)))
+
+(defun offside-trap-empty-line  ()
+  (string-match "^[ ]*$" (offside-trap-string-of-line)))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; sticky lines
+
+;; if the lines match with the following regexp, they are skipped
+;; in the sticky check.
+;; CR: It is not perfect. ex: {- "{-" -}. But who cares?
+(defconst offside-trap-sticky-skip-lines-regexp
+  (let ((empty-or-commented "[ \t]*\\(--.*\\)?\n")
+	(block-comment "[ \t]*{-\\([^-.]\\|-[^}]\\|\n\\)*-}.*\n"))
+    (format "\\(%s\\|%s\\)+" empty-or-commented block-comment)))
+
+(defun offside-trap-skip-sticky-skip-lines ()
+  (if (save-excursion
+	(move-beginning-of-line nil)
+	(looking-at offside-trap-sticky-skip-lines-regexp))
+      (progn
+	(move-beginning-of-line nil)
+	(re-search-forward offside-trap-sticky-skip-lines-regexp)
+	t)
+    nil))
 
 ;; check the line is "sticky"
 (defun offside-trap-is-sticky-line (chars)
-  (or (string-match "^[ ]*$" (offside-trap-string-of-line))
-      (<= chars (current-indentation))))
+  (<= chars (current-indentation)))
 
-;; goto line
-(defun offside-trap-goto-line (line)
-  (goto-char (point-min))
-  (forward-line (1- line)))
+;; find sticky lines and returns the end line number
+;; point must be at the place where the future head of the indentation
+(defun offside-trap-find-sticky-lines ()
+  (setq result (line-number-at-pos))
+  (let ((min-indent (current-column)))
+    ;; (message (format "min-indent %d" min-indent))
+    (save-excursion
+      ;; skip skippy lines at the head
+      (if (not (offside-trap-skip-sticky-skip-lines))
+	  ;; the first line is always sticky
+	  (forward-line 1))
+      (while
+	  (if (offside-trap-skip-sticky-skip-lines)
+	      (not (= (point-at-eol) (point-max)))
+	    (if (offside-trap-is-sticky-line min-indent)
+		(progn
+		  (setq result (line-number-at-pos))
+		  (if (= (point-at-eol) (point-max)) nil
+		    (forward-line 1)
+		    t))
+	      nil)))))
+  result)
 
-;; find sticky lines
-(defun offside-trap-find-sticky-lines ()
-  (let ((line (line-number-at-pos))
-	(char (current-column))
-	(indent (current-indentation))
-	(last-line (count-lines (point-min) (point-max))))
-    (let ((min-indent (max char indent)) ; CR: is it really useful ?
-	  (cur-line line))
-      ; (message (format "min-indent %d" min-indent))
-      (save-excursion
-	(while
-	    (if (= cur-line last-line) nil
-	      (offside-trap-goto-line (1+ cur-line))
-	      (if (offside-trap-is-sticky-line min-indent)
-		  (progn
-		    (setq cur-line (+ cur-line 1))
-		    t)
-		nil)))
-	cur-line))))
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; the trap
 
-;; the last char pos of the line
-(defun offside-trap-pos-of-end-of-line (line)
-  (save-excursion
-    (offside-trap-goto-line line)
-    (line-end-position)))
+;; the state
+(setq offside-trap-sticky-line-start nil)
+(setq offside-trap-sticky-line-end nil)
 
-;; put the overlay for the sticky lines
-(defun offside-trap-overlay-sticky-lines ()
+;; find the sticky lines and set offside-trap-sticky-line-{start,end}
+(defun offside-trap-set-sticky-lines ()
+  (let* ((sticky-end (offside-trap-find-sticky-lines))
+	 (sticky-start (line-number-at-pos)))
+    (setq offside-trap-sticky-line-start sticky-start)
+    (setq offside-trap-sticky-line-end sticky-end)
+    (offside-trap-overlay-sticky-lines (point) (offside-trap-eol offside-trap-sticky-line-end))))
+  
+;; point must be at the indent head
+;; the sticky lines must be registered in offside-trap-sticky-line-{start,end}
+(defun offside-trap-block-indent-gen (f)
+  (let ((old-lines (line-number-at-pos))
+	(old-chars (current-column)))
+    (apply f ()) ;; let the underlined function to indent the first line 
+    ;; Line might be changed. Rebind offside-trap-block.
+    (if offside-trap-sticky-line-start ;; if nil, do nothing
+	(save-excursion
+	  (let* ((new-lines (line-number-at-pos))
+		 (new-chars (current-column))
+		 (diff-lines (- new-lines old-lines))
+		 (diff-chars (- new-chars old-chars)))
+	    (progn 
+	      (setq offside-trap-sticky-line-start (+ diff-lines offside-trap-sticky-line-start))
+	      (setq offside-trap-sticky-line-end (+ diff-lines offside-trap-sticky-line-end))
+	      ;; the first line is already indented 
+	      (if (< offside-trap-sticky-line-start offside-trap-sticky-line-end)
+		  (indent-rigidly (offside-trap-bol (1+ offside-trap-sticky-line-start))
+				  (offside-trap-eol offside-trap-sticky-line-end)
+				  diff-chars))))))))
+
+;; step mode
+;; offside-trap-sticky-line-{start,end} must be set
+;; point must be already at the head of indentation 
+(defun offside-trap-block-indent-step ()
   (interactive)
-  (let ((line (line-number-at-pos))
-	(sticky-line-end (offside-trap-find-sticky-lines)))
-    (move-overlay offside-trap-overlay
-		  (point)
-		  (offside-trap-pos-of-end-of-line sticky-line-end)
-		  (current-buffer))
-    (if (= line sticky-line-end)
-	(progn
-	  ; (delete-overlay offside-trap-overlay)
-	  nil)
-      (list (1+ line) sticky-line-end))))
+  (offside-trap-block-indent-gen 'indent-for-tab-command))
 
-;; move the point to the indent head of the line
-(defun offside-trap-move-to-indent-head ()
-  (let ((indent (current-indentation)))
-    (goto-char (+ (line-beginning-position) indent))))
+;; starting block indent 
+(defun offside-trap-block-indent ()
+  (interactive)
+  (offside-trap-move-to-indent-head)
+  (offside-trap-set-sticky-lines)
+  (setq overriding-terminal-local-map offside-trap-sticky-mode-map) ;; go into the sticky mode 
+  (offside-trap-block-indent-step))
+
+;; CR: this function does not work pretty well for now. I prefer split-line+blockindent 
+;; when enter is pressed
+(defun offside-trap-newline-and-block-indent ()
+  (interactive)
+  ;; haskell-newline-and-indent first moves the point to the next non-empty char then insert a newline, 
+  ;; which is bizarre... So first we perform this cursor movement by ourselves first.
+  (offside-trap-move-to-non-space-char)
+  (offside-trap-set-sticky-lines)
+  (setq overriding-terminal-local-map offside-trap-sticky-mode-map) ;; go into the sticky mode 
+  (offside-trap-block-indent-gen 'haskell-newline-and-indent))
+
+(defun offside-trap-split-line-and-block-indent ()
+  (interactive)
+  (if (offside-trap-empty-line)
+      (newline)
+    (split-line)
+    (forward-line 1)
+    (offside-trap-block-indent)))
+ 
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; keymaps
 
 ;; push back the last event and exit from the offside trap mode
 (defun offside-trap-other-char ()
   (interactive)
   (delete-overlay offside-trap-overlay)
   (setq overriding-terminal-local-map nil)
-
   ;; push back the keypress
   (setq unread-command-events
 	(append (listify-key-sequence(this-command-keys))
 		unread-command-events)))
-
-;; offside trap mode keymap (borrowed from isearch.el)
+ 
 ;; offside trap mode keymap (borrowed from isearch.el)
 (defvar offside-trap-mode-map
   (let ((keymap (make-sparse-keymap)))
-    (define-key keymap (kbd "RET") 'offside-trap-newline-and-block-indent)
+    (define-key keymap (kbd "RET") 'offside-trap-newline-and-block-indent) ; does not work well
+    ;; (define-key keymap (kbd "RET") 'offside-trap-split-line-and-block-indent) ; does not work well
     (define-key keymap (kbd "TAB") 'offside-trap-block-indent)
+    (define-key keymap (kbd "<C-return>") 'haskell-newline-and-indent)
     (define-key keymap (kbd "<C-tab>") 'indent-for-tab-command)
     keymap))
 
 
     map)
   "Keymap for `offside-trap-sticky-mode'.")
+ 
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; minor mode
 
-;; current sticky block
-;; CR: should be buffer local ?
-(setq offside-trap-block nil)
-
-(defun offside-trap-beginning-position-of-line (line)
-  (save-excursion
-    (offside-trap-goto-line)
-    (line-beginning-position)))
-
-(defun offside-trap-end-position-of-line (line)
-  (save-excursion
-    (offside-trap-goto-line)
-    (line-end-position)))
-
-;; point must be at the indent head
-;; the sticky lines must be registered in offside-trap-block
-(defun offside-trap-block-indent-step-gen (f)
-  ; (offside-trap-move-to-indent-head) ; not required. point is at the head already
-  ; CR: check offside-trap-block is non nil
-  (let ((old-lines (line-number-at-pos))
-	(old-chars (current-column)))
-    (apply f ())
-    (save-excursion
-      (let* ((new-lines (line-number-at-pos))
-	     (new-chars (current-column))
-	     (diff-lines (- new-lines old-lines))
-	     (diff-chars (- new-chars old-chars)))
-        ; Line might be changed. Rebind offside-trap-block.
-	(destructuring-bind (line-start line-end) offside-trap-block
-	  (setq offside-trap-block (list (+ diff-lines line-start)
-					 (+ diff-lines line-end))))
-	(if offside-trap-block
-	    (destructuring-bind (line-start line-end) offside-trap-block
-	      (indent-rigidly (offside-trap-beginning-position-of-line line-start)
-			      (offside-trap-end-position-of-line line-end)
-			      diff-chars)))))))
-
-(defun offside-trap-block-indent-step ()
-  (interactive)
-  (offside-trap-block-indent-step-gen 'indent-for-tab-command))
-
-(defun offside-trap-block-indent ()
-  (interactive)
-  (offside-trap-move-to-indent-head)
-  (setq offside-trap-block (offside-trap-overlay-sticky-lines))
-  (setq overriding-terminal-local-map offside-trap-sticky-mode-map)
-  (offside-trap-block-indent-step))
-
-(defun offside-trap-newline-and-block-indent ()
-  (interactive)
-  (setq offside-trap-block (offside-trap-overlay-sticky-lines))
-  (setq overriding-terminal-local-map offside-trap-sticky-mode-map)
-  (offside-trap-block-indent-step-gen 'haskell-newline-and-indent))
-
-;;;###autoload
 (define-minor-mode offside-trap-mode
   "Offside trap mode."
   :lighter " OffsideTrap"
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.