[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/phps-mode b869339: Re-organization and improvements in
From: |
Christian Johansson |
Subject: |
[elpa] externals/phps-mode b869339: Re-organization and improvements in usability |
Date: |
Mon, 30 Sep 2019 11:48:36 -0400 (EDT) |
branch: externals/phps-mode
commit b869339c62d501190c5902bf275fbee163791248
Author: Christian Johansson <address@hidden>
Commit: Christian Johansson <address@hidden>
Re-organization and improvements in usability
---
Makefile | 14 +-
README.md | 17 +-
.../phps-mode-automation-header.wy | 0
.../phps-mode-automation.el | 0
.../alternative-control-structure.php | 0
.../sample-php-files}/class.php | 0
.../sample-php-files}/functions.php | 0
.../inline-control-structures.php | 0
.../sample-php-files}/interfaces.php | 0
.../sample-php-files}/namespace.php | 0
.../sample-php-files}/namespaces.php | 0
.../sample-php-files}/navigation.php | 0
docs/development.md | 71 +
docs/heuristics.md | 23 +-
docs/todo.md | 3 +-
phps-mode-lexer.el => phps-mode-analyzer.el | 1406 +++++++++++++++++++-
phps-mode-flymake.el | 2 -
phps-mode-functions.el | 1379 -------------------
phps-mode.el | 100 +-
.../phps-mode-test-functions.el | 44 +-
.../phps-mode-test-integration.el | 3 +-
.../phps-mode-test-lexer.el | 1 -
.../phps-mode-test-parser.el | 0
.../phps-mode-test-syntax-table.el | 2 +-
phps-mode-test.el => test/phps-mode-test.el | 6 +-
25 files changed, 1542 insertions(+), 1529 deletions(-)
diff --git a/Makefile b/Makefile
index 6a0d0c9..f1baa3d 100644
--- a/Makefile
+++ b/Makefile
@@ -2,9 +2,9 @@ EMACS = emacs
ifdef emacs
EMACS = $(emacs)
endif
-EMACS_CMD := $(EMACS) -Q -batch -L .
+EMACS_CMD := $(EMACS) -Q -batch -L . -L test/
-EL := phps-mode-automation.el phps-mode-flymake.el phps-mode-functions.el
phps-mode-lexer.el phps-mode-semantic.el phps-mode-syntax-table.el
phps-mode-tags.el phps-mode-test-functions.el phps-mode-test-integration.el
phps-mode-test-lexer.el phps-mode-test-parser.el phps-mode-test-syntax-table.el
phps-mode-test.el phps-mode.el
+EL := admin/phps-mode-automation.el phps-mode-analyzer.el
phps-mode-flymake.el phps-mode-semantic.el phps-mode-syntax-table.el
phps-mode-tags.el test/phps-mode-test-functions.el
test/phps-mode-test-integration.el test/phps-mode-test-lexer.el
test/phps-mode-test-parser.el test/phps-mode-test-syntax-table.el
test/phps-mode-test.el phps-mode.el
ELC := $(EL:.el=.elc)
.PHONY: clean
@@ -20,20 +20,20 @@ tests: test-functions test-integration test-lexer
test-parser test-syntax-table
.PHONY: test-functions
test-functions:
- $(EMACS_CMD) -l phps-mode-test-functions.el
+ $(EMACS_CMD) -l test/phps-mode-test-functions.el
.PHONY: test-integration
test-integration:
- $(EMACS_CMD) -l phps-mode-test-integration.el
+ $(EMACS_CMD) -l test/phps-mode-test-integration.el
.PHONY: test-lexer
test-lexer:
- $(EMACS_CMD) -l phps-mode-test-lexer.el
+ $(EMACS_CMD) -l test/phps-mode-test-lexer.el
.PHONY: test-parser
test-parser:
- $(EMACS_CMD) -l phps-mode-test-parser.el
+ $(EMACS_CMD) -l test/phps-mode-test-parser.el
.PHONY: test-syntax-table
test-syntax-table:
- $(EMACS_CMD) -l phps-mode-test-syntax-table.el
+ $(EMACS_CMD) -l test/phps-mode-test-syntax-table.el
diff --git a/README.md b/README.md
index 4f5fe70..7066415 100644
--- a/README.md
+++ b/README.md
@@ -10,9 +10,9 @@ This mode does not require PHP installed on your computer
because it has a built
## Features
* GPLv3 license
-* Flycheck support
+* Flycheck support with `(phps-mode-flycheck-setup)`
* Semantic lexer based on official PHP re2c lexer
-* Syntax coloring based on lexer tokens, make it easier to spot invalid code
+* Syntax coloring based on lexer tokens, makes it easier to spot invalid code
* PSR-1 and PSR-2 indentation based on lexer tokens
* Integration with `(electric-pair)`
* Incremental lexer and syntax coloring after buffer changes
@@ -28,12 +28,8 @@ This mode does not require PHP installed on your computer
because it has a built
## Keymap
-* `C-c /` Comment region
-* `C-c DEL` Uncomment region
* `C-c C-r` Rescan buffer
* `C-c C-f` Format buffer
-* `C-c C-r` Lex buffer
-* `C-c C-p` Process buffer
## Installation
@@ -55,7 +51,9 @@ You can install via ELPA (`M-x package-install` + `RET` +
`phps-mode` + `RET`),
(use-package phps-mode
:after flycheck
:ensure t
- :mode ("\\.php\\'" "\\.phtml\\'"))
+ :mode ("\\.php\\'" "\\.phtml\\'")
+ :config
+ (phps-mode-flycheck-setup))
```
### Load and configure using use-package
@@ -63,13 +61,16 @@ You can install via ELPA (`M-x package-install` + `RET` +
`phps-mode` + `RET`),
``` emacs-lisp
(use-package phps-mode
:after flycheck
- :mode ("\\.php\\'" "\\.phtml\\'"))
+ :mode ("\\.php\\'" "\\.phtml\\'")
+ :config
+ (phps-mode-flycheck-setup))
```
### Load and configure using regular emacs-lisp
``` emacs-lisp
(require 'phps-mode)
(add-to-list 'auto-mode-alist '("\\.\\(php\\|phtml\\)\\'" . phps-mode))
+(phps-mode-flycheck-setup)
```
## Read more
diff --git a/phps-mode-automation-header.wy
b/admin/phps-mode-automation-header.wy
similarity index 100%
rename from phps-mode-automation-header.wy
rename to admin/phps-mode-automation-header.wy
diff --git a/phps-mode-automation.el b/admin/phps-mode-automation.el
similarity index 100%
rename from phps-mode-automation.el
rename to admin/phps-mode-automation.el
diff --git a/sample-php-files/alternative-control-structure.php
b/admin/sample-php-files/alternative-control-structure.php
similarity index 100%
rename from sample-php-files/alternative-control-structure.php
rename to admin/sample-php-files/alternative-control-structure.php
diff --git a/sample-php-files/class.php b/admin/sample-php-files/class.php
similarity index 100%
rename from sample-php-files/class.php
rename to admin/sample-php-files/class.php
diff --git a/sample-php-files/functions.php
b/admin/sample-php-files/functions.php
similarity index 100%
rename from sample-php-files/functions.php
rename to admin/sample-php-files/functions.php
diff --git a/sample-php-files/inline-control-structures.php
b/admin/sample-php-files/inline-control-structures.php
similarity index 100%
rename from sample-php-files/inline-control-structures.php
rename to admin/sample-php-files/inline-control-structures.php
diff --git a/sample-php-files/interfaces.php
b/admin/sample-php-files/interfaces.php
similarity index 100%
rename from sample-php-files/interfaces.php
rename to admin/sample-php-files/interfaces.php
diff --git a/sample-php-files/namespace.php
b/admin/sample-php-files/namespace.php
similarity index 100%
rename from sample-php-files/namespace.php
rename to admin/sample-php-files/namespace.php
diff --git a/sample-php-files/namespaces.php
b/admin/sample-php-files/namespaces.php
similarity index 100%
rename from sample-php-files/namespaces.php
rename to admin/sample-php-files/namespaces.php
diff --git a/sample-php-files/navigation.php
b/admin/sample-php-files/navigation.php
similarity index 100%
rename from sample-php-files/navigation.php
rename to admin/sample-php-files/navigation.php
diff --git a/docs/development.md b/docs/development.md
new file mode 100644
index 0000000..ea2df5e
--- /dev/null
+++ b/docs/development.md
@@ -0,0 +1,71 @@
+# Development
+
+Make pull requests to `develop` branch or branches forked from develop branch.
Tested changes that are considered improvements are merged to master. Make sure
to sign the FSF-papers as well.
+
+## Tests
+
+If you have emacs at a customized location prefix the commands with your path,
i.e.
+
+`export emacs="~/Documents/emacs/src/emacs" && make tests`
+
+Run all tests with `make tests`.
+
+### Functions
+
+Indentations, incremental processes, Imenu-support.
+
+``` bash
+make test-functions
+```
+
+### Integration
+
+This should test all other parts in collaboration.
+
+``` bash
+make test-integration
+```
+
+### Lexer
+
+Lexer token generation.
+
+``` bash
+make test-lexer
+```
+
+### Parser
+
+Semantic grammar. Not ready yet.
+
+``` bash
+make test-parser
+```
+
+### Syntax-table
+
+Basic point and region behaviour.
+
+``` bash
+make test-syntax-table
+```
+
+## Byte-compilation
+
+Plug-in should support byte-compilation and it is recommended.
+
+### Compile
+
+``` bash
+make compile
+```
+
+### Clean
+
+``` bash
+make clean
+```
+
+
+
+[Back to start](../../../)
diff --git a/docs/heuristics.md b/docs/heuristics.md
index bbfab08..7a75ecc 100644
--- a/docs/heuristics.md
+++ b/docs/heuristics.md
@@ -1,19 +1,22 @@
-## Heuristics
+# Heuristics
-These should solve the problem of freezing editor for too long when making
white-space changes to code in large files. Otherwise a full incremental
re-parse would be triggered more often than necessary.
+These should solve the problem of freezing editor for too long when making
small changes to large files. Otherwise a full incremental re-parse would be
triggered more often than necessary.
-### Return
-When pressing return when the rest of the current line after cursor is only
white-space, move indexes of tokens, lexer states, indentation and imenu
forward one point
+## Indenting
+When indenting a line, calculate difference in white-space and change indexes
of buffer after point correspondingly.
-### Backspace
-When pressing backspace when the rest of the current line before cursor is
only white-space, move indexes of tokens, lexer states, indentation and imenu
backward one pint
+## Incremental
-### Indenting
-When indenting a line, calculate difference in white-space and change indexes
of buffer after point correspondingly
+When user has done other changes, determine unchanged previous position R,
determine changed maximum position X, determine new buffer length L. Do
incremental lex from R to X.
-### Other changes
-When user has done none-whitespace changes, determine unchanged previous
position R, determine changed maximum position X, determine new buffer length
L. Do incremental lex from R to X, if new states at X equals old states at X
just move indexes with delta X, otherwise do incremental lex of rest of buffer.
+### State preserving changes
+
+If new states at X equals old states at X just move all indexes with delta X,
otherwise do incremental lex of rest of buffer.
+
+### State disrupting changes
+
+Otherwise continue with incremental lex of rest of buffer.
[Back to start](../../../)
diff --git a/docs/todo.md b/docs/todo.md
index 81e042a..d69500b 100644
--- a/docs/todo.md
+++ b/docs/todo.md
@@ -2,8 +2,9 @@
*With current progress estimates:*
+* Got imenu items were there are only a namespace, namespace class, or class
+
* Add to MELPA package archive (50%)
-* A set of heuristics to improve large-file incremental change handling (75%)
* Wisent LALR parser based on official PHP yacc parser automatically converted
grammar (50%)
* mmm-mode support (50%)
* Full integration with Emacs Semantic subsystem (30%)
diff --git a/phps-mode-lexer.el b/phps-mode-analyzer.el
similarity index 54%
rename from phps-mode-lexer.el
rename to phps-mode-analyzer.el
index a922012..cc0ef26 100644
--- a/phps-mode-lexer.el
+++ b/phps-mode-analyzer.el
@@ -1,4 +1,4 @@
-;;; phps-mode-lexer.el -- Lexer for PHPs -*- lexical-binding: t -*-
+;;; phps-mode-analyzer.el -- Lexer and helper functions for PHPs -*-
lexical-binding: t -*-
;; Copyright (C) 2018-2019 Free Software Foundation, Inc.
@@ -20,40 +20,25 @@
;;; Commentary:
-;; Based on the Zend PHP Lexer and Parser
https://github.com/php/php-src/blob/master/Zend/zend_language_scanner.l
+;; *Define the lexer for this grammar
+;; based on the Zend PHP Lexer at
+;; `https://github.com/php/php-src/blob/master/Zend/zend_language_scanner.l'
;; which is using re2c.
;;
-;; NOTE Files of interest:
-;; - zend_language_scanner.l
-
+;; * Also supply logic for indentation and imenu-handling
+;; Change detection and incremental lexer
+;;
+;; * Syntax coloring based on lexer tokens
;;; Code:
-;; NOTE We use autoload here to circumvent recursive require
-(autoload 'phps-mode-functions--reset-changes "phps-mode-functions")
-(autoload 'phps-mode-functions--cancel-idle-timer "phps-mode-functions")
-(autoload 'phps-mode-functions--get-changes "phps-mode-functions")
-(autoload 'phps-mode-get-syntax-table "phps-mode")
-(autoload 'phps-mode-functions-processed-buffer "phps-mode-functions")
-(autoload 'phps-mode-functions-reset-processed-buffer "phps-mode-functions")
-(autoload 'phps-mode-runtime-debug-message "phps-mode")
+
+(require 'phps-mode-macros)
(require 'semantic)
(require 'semantic/lex)
-
-;; NOTE This line is required to pass byte-compilation
(require 'semantic/wisent)
-(require 'phps-mode-macros)
-
-
-;; Fix for byte-compilation warnings
-
-
-;; Define the lexer for this grammar
-
-;; Make sure `semantic-lex-syntax-modifications' is correct since lexer is
dependent on Emacs syntax-table
-
(defvar phps-mode-lexer-tokens nil
"Last lexer tokens.")
@@ -385,8 +370,10 @@
"Push TOKEN to list with START and END."
;; Colourize token
- (when-let (token-syntax-color (phps-mode-lexer-get-token-syntax-color token))
- (phps-mode-lexer-set-region-syntax-color start end token-syntax-color))
+ (let ((token-syntax-color (phps-mode-lexer-get-token-syntax-color token)))
+ (if token-syntax-color
+ (phps-mode-lexer-set-region-syntax-color start end token-syntax-color)
+ (phps-mode-lexer-clear-region-syntax-color start end)))
;; Push token start, end, lexer state and state stack to variable
(push
@@ -444,7 +431,12 @@
(if phps-mode-lexer-tokens
(progn
;; Add all updated tokens to semantic
- (phps-mode-debug-message (message "Updating semantic lexer tokens
from point %s, tokens: %s, point-max: %s" old-start phps-mode-lexer-tokens
(point-max)))
+ (phps-mode-debug-message
+ (message
+ "Updating semantic lexer tokens from point %s, tokens: %s,
point-max: %s"
+ old-start
+ phps-mode-lexer-tokens
+ (point-max)))
(dolist (token phps-mode-lexer-tokens)
(let ((start (car (cdr token)))
(end (cdr (cdr token)))
@@ -1669,7 +1661,6 @@
(defun phps-mode-lexer-run-incremental (buffer)
"Run incremental lexer on BUFFER."
(phps-mode-debug-message (message "Run incremental lexer on buffer '%s'"
buffer))
- (phps-mode-runtime-debug-message (format "Run incremental lexer on buffer
'%s'" buffer))
(with-current-buffer buffer
(let ((changes (phps-mode-functions--get-changes))
(run-full-lexer nil)
@@ -1698,7 +1689,6 @@
(setq-local phps-mode-lexer-STATE nil)
(setq-local phps-mode-lexer-state_stack nil)
- (phps-mode-runtime-debug-message "Processing incremental changes")
(phps-mode-debug-message (message "Processing incremental changes:
%s" changes))
(setq run-full-lexer t)
@@ -1707,10 +1697,6 @@
(change-stop (nth 1 change))
(buffer-length-new (1- (nth 3 change)))
(buffer-contents-new (nth 4 change)))
- (phps-mode-runtime-debug-message
- (format "Running incremental lexer %s - %s" change-start
change-stop))
- (phps-mode-debug-message
- (message "Running incremental lexer %s - %s" change-start
change-stop))
(when (and change-start
change-stop)
@@ -1825,7 +1811,6 @@
(if head-states
(progn
- (phps-mode-runtime-debug-message "Found
head states")
(phps-mode-debug-message (message "Found
head states"))
;; Flag that we should not run ful lexer
@@ -1850,8 +1835,10 @@
(setq-local
phps-mode-lexer-state_stack incremental-state-stack)
;; Setup lexer
- (setq-local semantic-lex-analyzer
#'phps-mode-lexer-lex)
- (setq-local semantic-lex-syntax-table
(phps-mode-get-syntax-table))
+ (when (fboundp 'phps-mode-lexer-lex)
+ (setq-local semantic-lex-analyzer
#'phps-mode-lexer-lex))
+ (when (boundp 'phps-mode-syntax-table)
+ (setq-local
semantic-lex-syntax-table phps-mode-syntax-table))
(phps-mode-debug-message
(message "Incremental buffer
contents: \n%s" (buffer-substring-no-properties (point-min) (point-max)))
@@ -1869,7 +1856,6 @@
(equal
phps-mode-lexer-state_stack incremental-state-stack))
(progn
- (phps-mode-runtime-debug-message
"Found matching state and state-stack, copying old state and tokens")
(phps-mode-debug-message (message
"Found matching state and state-stack, copying old state and tokens"))
(unless (= buffer-length-delta 0)
@@ -1899,7 +1885,6 @@
(setq appended-tokens (append
appended-tokens tail-tokens))
(phps-mode-debug-message (message
"New tokens from incremental lex are: %s" appended-tokens)))
- (phps-mode-runtime-debug-message "Did
not find matching state and state-stack, lexing rest of buffer")
(phps-mode-debug-message (message "Did
not find matching state and state-stack, lexing rest of buffer"))
(phps-mode-debug-message
@@ -1915,10 +1900,8 @@
(phps-mode-debug-message (message "New
states from full lex are: %s" phps-mode-lexer-states))
(phps-mode-debug-message (message "New
tokens from full lex are: %s" appended-tokens)))
- (phps-mode-runtime-debug-message (format
"Final tokens: %s" appended-tokens))
(phps-mode-debug-message (message "Final
tokens: %s" appended-tokens))
(setq-local phps-mode-lexer-tokens
appended-tokens))
- (phps-mode-runtime-debug-message "Did not find
head states")
(phps-mode-debug-message (message "Did not
find head states"))))
(phps-mode-debug-message (message "Did not find
positive incremental-start or head-tokens"))))
(phps-mode-debug-message (message "Change start not above
one or lacking tokens or states"))))
@@ -1927,11 +1910,9 @@
(setq-local phps-mode-lexer-buffer-length (1- (point-max)))
(setq-local phps-mode-lexer-buffer-contents
(buffer-substring-no-properties (point-min) (point-max))))
- (phps-mode-runtime-debug-message "Found no changes")
(phps-mode-debug-message (message "Found no changes")))
(when run-full-lexer
- (phps-mode-runtime-debug-message "Running full lexer")
(phps-mode-debug-message (message "Running full lexer"))
(phps-mode-lexer-run)))))
@@ -1940,6 +1921,1341 @@
phps-mode-lexer-lex-analyzer
semantic-lex-default-action)
-(provide 'phps-mode-lexer)
+(require 'subr-x)
+
+(defvar phps-mode-functions-allow-after-change t
+ "Flag to tell us whether after change detection is enabled or not.")
+
+(defvar phps-mode-functions-buffer-changes nil
+ "A stack of buffer changes.")
+
+(defvar phps-mode-functions-idle-timer nil
+ "Timer object of idle timer.")
+
+(defvar phps-mode-functions-imenu nil
+ "The Imenu alist for current buffer, nil if none.")
+
+(defvar phps-mode-functions-lines-indent nil
+ "The indentation of each line in buffer, nil if none.")
+
+(defvar phps-mode-functions-processed-buffer nil
+ "Flag whether current buffer is processed or not.")
+
+(defun phps-mode-functions-get-processed-buffer ()
+ "Get flag for whether buffer is processed or not."
+ phps-mode-functions-processed-buffer)
+
+(defun phps-mode-functions-reset-processed-buffer ()
+ "Reset flag for whether buffer is processed or not."
+ (setq-local phps-mode-functions-processed-buffer nil))
+
+(defun phps-mode-functions-process-current-buffer ()
+ "Process current buffer, generate indentations and Imenu, trigger
incremental lexer if we have change."
+ (interactive)
+ (phps-mode-debug-message (message "Process current buffer"))
+ (when phps-mode-functions-idle-timer
+ (phps-mode-debug-message (message "Trigger incremental lexer"))
+ (phps-mode-lexer-run-incremental (current-buffer))
+ (setq-local phps-mode-functions-processed-buffer nil))
+ (if (not phps-mode-functions-processed-buffer)
+ (progn
+ (phps-mode-debug-message (message "Buffer is not processed"))
+ (let ((processed (phps-mode-functions--process-tokens-in-string
phps-mode-lexer-tokens (buffer-substring-no-properties (point-min)
(point-max)))))
+ (phps-mode-debug-message (message "Processed result: %s" processed))
+ (setq-local phps-mode-functions-imenu (nth 0 processed))
+ (setq-local phps-mode-functions-lines-indent (nth 1 processed)))
+ (setq-local phps-mode-functions-processed-buffer t))
+ (phps-mode-debug-message (message "Buffer is already processed"))))
+
+(defun phps-mode-functions-get-moved-lines-indent (old-lines-indents
start-line-number diff)
+ "Move OLD-LINES-INDENTS from START-LINE-NUMBER with DIFF points."
+ (let ((lines-indents (make-hash-table :test 'equal))
+ (line-number 1))
+ (when old-lines-indents
+ (let ((line-indent (gethash line-number old-lines-indents))
+ (new-line-number))
+ (while line-indent
+
+ (when (< line-number start-line-number)
+ ;; (message "Added new indent 3 %s from %s to %s" line-indent
line-number line-number)
+ (puthash line-number line-indent lines-indents))
+
+ (when (and (> diff 0)
+ (>= line-number start-line-number)
+ (< line-number (+ start-line-number diff)))
+ ;; (message "Added new indent 2 %s from %s to %s" line-indent
line-number line-number)
+ (puthash line-number (gethash start-line-number old-lines-indents)
lines-indents))
+
+ (when (>= line-number start-line-number)
+ (setq new-line-number (+ line-number diff))
+ ;; (message "Added new indent %s from %s to %s" line-indent
line-number new-line-number)
+ (puthash new-line-number line-indent lines-indents))
+
+ (setq line-number (1+ line-number))
+ (setq line-indent (gethash line-number old-lines-indents))))
+ lines-indents)))
+
+(defun phps-mode-functions-move-imenu-index (start diff)
+ "Moved imenu from START by DIFF points."
+ (when phps-mode-functions-imenu
+ (setq-local phps-mode-functions-imenu (phps-mode-functions-get-moved-imenu
phps-mode-functions-imenu start diff))))
+
+(defun phps-mode-functions-move-lines-indent (start-line-number diff)
+ "Move lines indent from START-LINE-NUMBER with DIFF points."
+ (when phps-mode-functions-lines-indent
+ ;; (message "Moving line-indent index from %s with %s" start-line-number
diff)
+ (setq-local phps-mode-functions-lines-indent
(phps-mode-functions-get-moved-lines-indent phps-mode-functions-lines-indent
start-line-number diff))))
+
+(defun phps-mode-functions-get-lines-indent ()
+ "Return lines indent, process buffer if not done already."
+ (phps-mode-functions-process-current-buffer)
+ phps-mode-functions-lines-indent)
+
+(defun phps-mode-functions-get-imenu ()
+ "Return Imenu, process buffer if not done already."
+ (phps-mode-functions-process-current-buffer)
+ phps-mode-functions-imenu)
+
+(defun phps-mode-functions-get-moved-imenu (old-index start diff)
+ "Move imenu-index OLD-INDEX beginning from START with DIFF."
+ (let ((new-index '()))
+
+ (when old-index
+ (if (and (listp old-index)
+ (listp (car old-index)))
+ (dolist (item old-index)
+ (let ((sub-item (phps-mode-functions-get-moved-imenu item start
diff)))
+ (push (car sub-item) new-index)))
+ (let ((item old-index))
+ (let ((item-label (car item)))
+ (if (listp (cdr item))
+ (let ((sub-item (phps-mode-functions-get-moved-imenu (cdr
item) start diff)))
+ (push `(,item-label . ,sub-item) new-index))
+ (let ((item-start (cdr item)))
+ (when (>= item-start start)
+ (setq item-start (+ item-start diff)))
+ (push `(,item-label . ,item-start) new-index)))))))
+
+ (nreverse new-index)))
+
+(defun phps-mode-functions--get-lines-in-buffer (beg end)
+ "Return the number of lines in buffer between BEG and END."
+ (phps-mode-functions--get-lines-in-string (buffer-substring-no-properties
beg end)))
+
+(defun phps-mode-functions--get-lines-in-string (string)
+ "Return the number of lines in STRING."
+ (let ((lines-in-string 0)
+ (start 0))
+ (while (string-match "[\n\C-m]" string start)
+ (setq start (match-end 0))
+ (setq lines-in-string (1+ lines-in-string)))
+ lines-in-string))
+
+(defun phps-mode-functions--get-inline-html-indentation (inline-html indent
tag-level curly-bracket-level square-bracket-level round-bracket-level)
+ "Generate a list of indentation for each line in INLINE-HTML, working
incrementally on INDENT, TAG-LEVEL, CURLY-BRACKET-LEVEL, SQUARE-BRACKET-LEVEL
and ROUND-BRACKET-LEVEL."
+ (phps-mode-debug-message
+ (message "Calculating HTML indent for: '%s'" inline-html))
+
+ ;; Add trailing newline if missing
+ (unless (string-match "\n$" inline-html)
+ (setq inline-html (concat inline-html "\n")))
+
+ (let ((start 0)
+ (indent-start indent)
+ (indent-end indent)
+ (line-indents nil)
+ (first-object-on-line t)
+ (first-object-is-nesting-decrease nil))
+ (while (string-match
"\\([\n\C-m]\\)\\|\\(<[a-zA-Z]+\\)\\|\\(</[a-zA-Z]+\\)\\|\\(/>\\)\\|\\(\\[\\)\\|\\()\\)\\|\\((\\)"
inline-html start)
+ (let* ((end (match-end 0))
+ (string (substring inline-html (match-beginning 0) end)))
+
+ (cond
+
+ ((string= string "\n")
+
+ (let ((temp-indent indent))
+ (when first-object-is-nesting-decrease
+ (phps-mode-debug-message
+ (message "Decreasing indent with one since first object was a
nesting decrease"))
+ (setq temp-indent (1- indent))
+ (when (< temp-indent 0)
+ (setq temp-indent 0)))
+ (push temp-indent line-indents))
+
+ (setq indent-end (+ tag-level curly-bracket-level
square-bracket-level round-bracket-level))
+ (phps-mode-debug-message "Encountered a new-line")
+ (if (> indent-end indent-start)
+ (progn
+ (phps-mode-debug-message
+ (message "Increasing indent since %s is above %s" indent-end
indent-start))
+ (setq indent (1+ indent)))
+ (when (< indent-end indent-start)
+ (phps-mode-debug-message
+ (message "Decreasing indent since %s is below %s" indent-end
indent-start))
+ (setq indent (1- indent))
+ (when (< indent 0)
+ (setq indent 0))))
+
+ (setq indent-start indent-end)
+ (setq first-object-on-line t)
+ (setq first-object-is-nesting-decrease nil))
+
+ ((string= string "(")
+ (setq round-bracket-level (1+ round-bracket-level)))
+ ((string= string ")")
+ (setq round-bracket-level (1- round-bracket-level)))
+
+ ((string= string "[")
+ (setq square-bracket-level (1+ square-bracket-level)))
+ ((string= string "]")
+ (setq square-bracket-level (1- square-bracket-level)))
+
+ ((string= string "{")
+ (setq curly-bracket-level (1+ curly-bracket-level)))
+ ((string= string "}")
+ (setq curly-bracket-level (1- curly-bracket-level)))
+
+ ((string-match "<[a-zA-Z]+" string)
+ (setq tag-level (1+ tag-level)))
+
+ ((string-match "\\(</[a-zA-Z]+\\)\\|\\(/>\\)" string)
+ (setq tag-level (1- tag-level)))
+
+ )
+
+ (when first-object-on-line
+ (unless (string= string "\n")
+ (setq first-object-on-line nil)
+ (setq indent-end (+ tag-level curly-bracket-level
square-bracket-level round-bracket-level))
+ (when (< indent-end indent-start)
+ (phps-mode-debug-message "First object was nesting decrease")
+ (setq first-object-is-nesting-decrease t))))
+
+ (setq start end)))
+ (list (nreverse line-indents) indent tag-level curly-bracket-level
square-bracket-level round-bracket-level)))
+
+(defun phps-mode-functions--process-tokens-in-string (tokens string)
+ "Generate indexes for imenu and indentation for TOKENS and STRING one pass.
Complexity: O(n)."
+ (if tokens
+ (progn
+ (phps-mode-debug-message (message "\nCalculation indentation and imenu
for all lines in buffer:\n\n%s" string))
+ (let ((in-heredoc nil)
+ (in-heredoc-started-this-line nil)
+ (in-heredoc-ended-this-line nil)
+ (in-inline-control-structure nil)
+ (inline-html-indent 0)
+ (inline-html-indent-start 0)
+ (inline-html-tag-level 0)
+ (inline-html-curly-bracket-level 0)
+ (inline-html-square-bracket-level 0)
+ (inline-html-round-bracket-level 0)
+ (inline-html-is-whitespace nil)
+ (first-token-is-inline-html nil)
+ (after-special-control-structure nil)
+ (after-special-control-structure-token nil)
+ (after-extra-special-control-structure nil)
+ (after-extra-special-control-structure-first-on-line nil)
+ (switch-curly-stack nil)
+ (switch-alternative-stack nil)
+ (switch-case-alternative-stack nil)
+ (curly-bracket-level 0)
+ (round-bracket-level 0)
+ (square-bracket-level 0)
+ (alternative-control-structure-level 0)
+ (in-concatenation nil)
+ (in-concatenation-round-bracket-level nil)
+ (in-concatenation-square-bracket-level nil)
+ (in-concatenation-level 0)
+ (column-level 0)
+ (column-level-start 0)
+ (tuning-level 0)
+ (nesting-start 0)
+ (nesting-end 0)
+ (last-line-number 0)
+ (first-token-on-line t)
+ (line-indents (make-hash-table :test 'equal))
+ (first-token-is-nesting-decrease nil)
+ (token-number 1)
+ (allow-custom-column-increment nil)
+ (allow-custom-column-decrement nil)
+ (in-assignment nil)
+ (in-assignment-round-bracket-level nil)
+ (in-assignment-square-bracket-level nil)
+ (in-assignment-level 0)
+ (in-object-operator nil)
+ (in-object-operator-round-bracket-level nil)
+ (in-object-operator-square-bracket-level nil)
+ (after-object-operator nil)
+ (in-object-operator-level 0)
+ (in-class-declaration nil)
+ (in-class-declaration-level 0)
+ (in-return nil)
+ (in-return-curly-bracket-level nil)
+ (in-return-level 0)
+ (previous-token nil)
+ (token nil)
+ (token-start nil)
+ (token-end nil)
+ (token-start-line-number 0)
+ (token-end-line-number 0)
+ (tokens (nreverse (copy-sequence tokens)))
+ (nesting-stack nil)
+ (nesting-key nil)
+ (class-declaration-started-this-line nil)
+ (special-control-structure-started-this-line nil)
+ (temp-pre-indent nil)
+ (temp-post-indent nil)
+ (imenu-index '())
+ (imenu-namespace-index '())
+ (imenu-namespace-definition nil)
+ (imenu-class-index '())
+ (imenu-class-definition nil)
+ (imenu-in-namespace-declaration nil)
+ (imenu-in-namespace-name nil)
+ (imenu-in-namespace-with-brackets nil)
+ (imenu-open-namespace-level nil)
+ (imenu-in-class-declaration nil)
+ (imenu-open-class-level nil)
+ (imenu-in-class-name nil)
+ (imenu-in-function-declaration nil)
+ (imenu-in-function-name nil)
+ (imenu-in-function-index nil)
+ (imenu-nesting-level 0)
+ (incremental-line-number 1))
+
+ (push `(END_PARSE ,(length string) . ,(length string)) tokens)
+
+ ;; Iterate through all buffer tokens from beginning to end
+ (dolist (item (nreverse tokens))
+ ;; (message "Items: %s %s" item phps-mode-lexer-tokens)
+ (let ((next-token (car item))
+ (next-token-start (car (cdr item)))
+ (next-token-end (cdr (cdr item)))
+ (next-token-start-line-number nil)
+ (next-token-end-line-number nil))
+
+ (when (and token
+ (< token-end next-token-start))
+ ;; NOTE We use a incremental-line-number calculation because
`line-at-pos' takes a lot of time
+ (setq incremental-line-number (+ incremental-line-number
(phps-mode-functions--get-lines-in-string (substring string (1- token-end) (1-
next-token-start))))))
+
+ ;; Handle the pseudo-token for last-line
+ (if (equal next-token 'END_PARSE)
+ (progn
+ (setq next-token-start-line-number (1+
token-start-line-number))
+ (setq next-token-end-line-number (1+
token-end-line-number)))
+ (setq next-token-start-line-number incremental-line-number)
+
+ ;; NOTE We use a incremental-line-number calculation because
`line-at-pos' takes a lot of time
+ ;; (message "Lines for %s '%s'" next-token (substring string
(1- next-token-start) (1- next-token-end)))
+ (setq incremental-line-number (+ incremental-line-number
(phps-mode-functions--get-lines-in-string (substring string (1-
next-token-start) (1- next-token-end)))))
+ (setq next-token-end-line-number incremental-line-number)
+ (phps-mode-debug-message
+ (message "Token '%s' pos: %s-%s lines: %s-%s" next-token
next-token-start next-token-end next-token-start-line-number
next-token-end-line-number)))
+
+ ;; Token logic - we have one-two token look-ahead at this point
+ ;; `token' is previous token
+ ;; `next-token' is current token
+ ;; `previous-token' is maybe two tokens back
+ (when token
+
+
+ ;; IMENU LOGIC
+
+ (cond
+
+ ((or (string= token "{")
+ (equal token 'T_CURLY_OPEN)
+ (equal token 'T_DOLLAR_OPEN_CURLY_BRACES))
+ (setq imenu-nesting-level (1+ imenu-nesting-level)))
+
+ ((string= token "}")
+
+ (when (and imenu-open-namespace-level
+ (= imenu-open-namespace-level imenu-nesting-level)
+ imenu-in-namespace-name)
+ (let ((imenu-add-list (nreverse imenu-namespace-index)))
+ (push `(,imenu-in-namespace-name . ,imenu-add-list)
imenu-index))
+ (setq imenu-in-namespace-name nil))
+
+ (when (and imenu-open-class-level
+ (= imenu-open-class-level imenu-nesting-level)
+ imenu-in-class-name)
+ (let ((imenu-add-list (nreverse imenu-class-index)))
+ (if imenu-in-namespace-name
+ (push `(,imenu-in-class-name . ,imenu-add-list)
imenu-namespace-index)
+ (push `(,imenu-in-class-name . ,imenu-add-list)
imenu-index)))
+ (setq imenu-in-class-name nil))
+
+ (setq imenu-nesting-level (1- imenu-nesting-level))))
+
+ (cond
+
+ (imenu-in-namespace-declaration
+ (cond
+
+ ((or (string= token "{")
+ (string= token ";"))
+ (setq imenu-in-namespace-with-brackets (string= token "{"))
+ (setq imenu-open-namespace-level imenu-nesting-level)
+ (setq imenu-namespace-index '())
+ (push `("*definition*" . ,imenu-namespace-definition)
imenu-namespace-index)
+ (setq imenu-in-namespace-declaration nil))
+
+ ((and (or (equal token 'T_STRING)
+ (equal token 'T_NS_SEPARATOR))
+ (setq imenu-namespace-definition token-start)
+ (setq imenu-in-namespace-name (concat
imenu-in-namespace-name (substring string (1- token-start) (1- token-end))))))))
+
+ (imenu-in-class-declaration
+ (cond
+
+ ((string= token "{")
+ (setq imenu-open-class-level imenu-nesting-level)
+ (setq imenu-in-class-declaration nil)
+ (setq imenu-class-index '())
+ (push `("*definition*" . ,imenu-class-definition)
imenu-class-index))
+
+ ((and (equal token 'T_STRING)
+ (not imenu-in-class-name))
+ (setq imenu-class-definition token-start)
+ (setq imenu-in-class-name (substring string (1-
token-start) (1- token-end))))))
+
+ (imenu-in-function-declaration
+ (cond
+
+ ((or (string= token "{")
+ (string= token ";"))
+ (when imenu-in-function-name
+ (if imenu-in-class-name
+ (push `(,imenu-in-function-name .
,imenu-in-function-index) imenu-class-index)
+ (if imenu-in-namespace-name
+ (push `(,imenu-in-function-name .
,imenu-in-function-index) imenu-namespace-index)
+ (push `(,imenu-in-function-name .
,imenu-in-function-index) imenu-index))))
+ (setq imenu-in-function-name nil)
+ (setq imenu-in-function-declaration nil))
+
+ ((and (equal token 'T_STRING)
+ (not imenu-in-function-name))
+ (setq imenu-in-function-name (substring string (1-
token-start) (1- token-end)))
+ (setq imenu-in-function-index token-start))))
+
+ (t (cond
+
+ ((and (not imenu-in-namespace-name)
+ (equal token 'T_NAMESPACE))
+ (setq imenu-in-namespace-name nil)
+ (setq imenu-in-namespace-declaration t))
+
+ ((and (not imenu-in-class-name)
+ (or (equal token 'T_CLASS)
+ (equal token 'T_INTERFACE)))
+ (setq imenu-in-class-name nil)
+ (setq imenu-in-class-declaration t))
+
+ ((and (not imenu-in-function-name)
+ (equal token 'T_FUNCTION))
+ (setq imenu-in-function-name nil)
+ (setq imenu-in-function-declaration t)))))
+
+ (when (and (equal next-token 'END_PARSE)
+ imenu-in-namespace-name
+ (not imenu-in-namespace-with-brackets))
+ (let ((imenu-add-list (nreverse imenu-namespace-index)))
+ (push `(,imenu-in-namespace-name . ,imenu-add-list)
imenu-index))
+ (setq imenu-in-namespace-name nil))
+
+
+ ;; INDENTATION LOGIC
+
+ ;; Keep track of round bracket level
+ (when (string= token "(")
+ (setq round-bracket-level (1+ round-bracket-level)))
+ (when (string= token ")")
+ (setq round-bracket-level (1- round-bracket-level))
+ (when first-token-on-line
+ (setq first-token-is-nesting-decrease t)))
+
+ ;; Keep track of square bracket level
+ (when (string= token "[")
+ (setq square-bracket-level (1+ square-bracket-level)))
+ (when (string= token "]")
+ (setq square-bracket-level (1- square-bracket-level))
+ (when first-token-on-line
+ (setq first-token-is-nesting-decrease t)))
+
+ ;; Handle INLINE_HTML blocks
+ (when (equal token 'T_INLINE_HTML)
+
+ ;; Flag whether inline-html is whitespace or not
+ (setq inline-html-is-whitespace (string= (string-trim
(substring string (1- token-start) (1- token-end))) ""))
+
+ (when first-token-on-line
+ (setq first-token-is-inline-html t))
+
+ (let ((inline-html-indents
(phps-mode-functions--get-inline-html-indentation (substring string (1-
token-start) (1- token-end)) inline-html-indent inline-html-tag-level
inline-html-curly-bracket-level inline-html-square-bracket-level
inline-html-round-bracket-level)))
+
+ (phps-mode-debug-message
+ (message "Received inline html indent: %s from inline
HTML: '%s'" inline-html-indents (substring string (1- token-start) (1-
token-end))))
+
+ ;; Update indexes
+ (setq inline-html-indent (nth 1 inline-html-indents))
+ (setq inline-html-tag-level (nth 2 inline-html-indents))
+ (setq inline-html-curly-bracket-level (nth 3
inline-html-indents))
+ (setq inline-html-square-bracket-level (nth 4
inline-html-indents))
+ (setq inline-html-round-bracket-level (nth 5
inline-html-indents))
+
+ (phps-mode-debug-message
+ (message "First token is inline html: %s"
first-token-is-inline-html))
+
+ ;; Does inline html span several lines or starts a new
line?
+ (when (or (> token-end-line-number token-start-line-number)
+ first-token-is-inline-html)
+
+ ;; Token does not only contain white-space?
+ (unless inline-html-is-whitespace
+ (let ((token-line-number-diff token-start-line-number))
+ ;; Iterate lines here and add indents
+ (dolist (item (nth 0 inline-html-indents))
+ ;; Skip first line unless first token on line was
inline-html
+ (when (or (not (= token-line-number-diff
token-start-line-number))
+ first-token-is-inline-html)
+ (unless (gethash token-line-number-diff
line-indents)
+ (puthash token-line-number-diff (list item 0)
line-indents)
+ (phps-mode-debug-message
+ (message "Putting indent at line %s to %s
from inline HTML" token-line-number-diff item))))
+ (setq token-line-number-diff (1+
token-line-number-diff))))))))
+
+ ;; Keep track of when we are inside a class definition
+ (if in-class-declaration
+ (if (string= token "{")
+ (progn
+ (setq in-class-declaration nil)
+ (setq in-class-declaration-level 0)
+
+ (unless class-declaration-started-this-line
+ (setq column-level (1- column-level))
+ (pop nesting-stack))
+
+ (when first-token-on-line
+ (setq first-token-is-nesting-decrease t))
+
+ )
+ (when first-token-on-line
+ (setq in-class-declaration-level 1)))
+
+ ;; If ::class is used as a magical class constant it should
not be considered start of a class declaration
+ (when (and (equal token 'T_CLASS)
+ (or (not previous-token)
+ (not (equal previous-token
'T_PAAMAYIM_NEKUDOTAYIM))))
+ (setq in-class-declaration t)
+ (setq in-class-declaration-level 1)
+ (setq class-declaration-started-this-line t)))
+
+ ;; Keep track of curly bracket level
+ (when (or (equal token 'T_CURLY_OPEN)
+ (equal token 'T_DOLLAR_OPEN_CURLY_BRACES)
+ (string= token "{"))
+ (setq curly-bracket-level (1+ curly-bracket-level)))
+ (when (string= token "}")
+ (setq curly-bracket-level (1- curly-bracket-level))
+
+ (when (and switch-curly-stack
+ (= (1+ curly-bracket-level) (car
switch-curly-stack)))
+
+ (phps-mode-debug-message
+ (message "Ended switch curly stack at %s"
curly-bracket-level))
+
+ (setq allow-custom-column-decrement t)
+ (pop nesting-stack)
+ (setq alternative-control-structure-level (1-
alternative-control-structure-level))
+ (pop switch-curly-stack))
+
+ (when first-token-on-line
+ (setq first-token-is-nesting-decrease t)))
+
+ ;; Keep track of ending alternative control structure level
+ (when (or (equal token 'T_ENDIF)
+ (equal token 'T_ENDWHILE)
+ (equal token 'T_ENDFOR)
+ (equal token 'T_ENDFOREACH)
+ (equal token 'T_ENDSWITCH))
+ (setq alternative-control-structure-level (1-
alternative-control-structure-level))
+ ;; (message "Found ending alternative token %s %s" token
alternative-control-structure-level)
+
+ (when (and (equal token 'T_ENDSWITCH)
+ switch-case-alternative-stack)
+
+ (phps-mode-debug-message
+ (message "Ended alternative switch stack at %s"
alternative-control-structure-level))
+
+ (pop switch-alternative-stack)
+ (pop switch-case-alternative-stack)
+ (setq allow-custom-column-decrement t)
+ (pop nesting-stack)
+ (setq alternative-control-structure-level (1-
alternative-control-structure-level)))
+
+ (when first-token-on-line
+ (setq first-token-is-nesting-decrease t)))
+
+ ;; When we encounter a token except () after a
control-structure
+ (when (and after-special-control-structure
+ (= after-special-control-structure
round-bracket-level)
+ (not (string= token ")"))
+ (not (string= token "(")))
+
+ ;; Handle the else if case
+ (if (equal 'T_IF token)
+ (setq after-special-control-structure-token token)
+
+ ;; Is token not a curly bracket - because that is a
ordinary control structure syntax
+ (if (string= token "{")
+
+ ;; Save curly bracket level when switch starts
+ (when (equal after-special-control-structure-token
'T_SWITCH)
+
+ (phps-mode-debug-message
+ (message "Started switch curly stack at %s"
curly-bracket-level))
+
+ (push curly-bracket-level switch-curly-stack))
+
+ ;; Is it the start of an alternative control structure?
+ (if (string= token ":")
+
+ (progn
+
+ ;; Save alternative nesting level for switch
+ (when (equal after-special-control-structure-token
'T_SWITCH)
+
+ (phps-mode-debug-message
+ (message "Started switch alternative stack at
%s" alternative-control-structure-level))
+
+ (push alternative-control-structure-level
switch-alternative-stack))
+
+ (setq alternative-control-structure-level (1+
alternative-control-structure-level))
+
+ (phps-mode-debug-message
+ (message "\nIncreasing
alternative-control-structure after %s %s to %s\n"
after-special-control-structure-token token
alternative-control-structure-level))
+ )
+
+ ;; Don't start inline control structures after a while
($condition); expression
+ (unless (string= token ";")
+ (phps-mode-debug-message
+ (message "\nStarted inline control-structure after
%s at %s\n" after-special-control-structure-token token))
+
+ (setq in-inline-control-structure t)
+ (setq temp-pre-indent (1+ column-level)))))
+
+ (setq after-special-control-structure nil)
+ (setq after-special-control-structure-token nil)))
+
+ ;; Support extra special control structures (CASE)
+ (when (and after-extra-special-control-structure
+ (string= token ":"))
+ (setq alternative-control-structure-level (1+
alternative-control-structure-level))
+ (when after-extra-special-control-structure-first-on-line
+ (setq first-token-is-nesting-decrease t))
+ (setq after-extra-special-control-structure nil))
+
+ ;; Keep track of concatenation
+ (if in-concatenation
+ (when (or (string= token ";")
+ (and (string= token ")")
+ (< round-bracket-level (car
in-concatenation-round-bracket-level)))
+ (and (string= token ",")
+ (= round-bracket-level (car
in-concatenation-round-bracket-level))
+ (= square-bracket-level (car
in-concatenation-square-bracket-level)))
+ (and (string= token"]")
+ (< square-bracket-level (car
in-concatenation-square-bracket-level))))
+ (phps-mode-debug-message "Ended concatenation")
+ (pop in-concatenation-round-bracket-level)
+ (pop in-concatenation-square-bracket-level)
+ (unless in-concatenation-round-bracket-level
+ (setq in-concatenation nil))
+ (setq in-concatenation-level (1-
in-concatenation-level)))
+ (when (and (> next-token-start-line-number
token-end-line-number)
+ (or (string= token ".")
+ (string= next-token ".")))
+ (phps-mode-debug-message "Started concatenation")
+ (setq in-concatenation t)
+ (push round-bracket-level
in-concatenation-round-bracket-level)
+ (push square-bracket-level
in-concatenation-square-bracket-level)
+ (setq in-concatenation-level (1+ in-concatenation-level))))
+
+ ;; Did we reach a semicolon inside a inline block? Close the
inline block
+ (when (and in-inline-control-structure
+ (string= token ";")
+ (not special-control-structure-started-this-line))
+ (setq in-inline-control-structure nil))
+
+ ;; Did we encounter a token that supports alternative and
inline control structures?
+ (when (or (equal token 'T_IF)
+ (equal token 'T_WHILE)
+ (equal token 'T_FOR)
+ (equal token 'T_FOREACH)
+ (equal token 'T_SWITCH)
+ (equal token 'T_ELSE)
+ (equal token 'T_ELSEIF)
+ (equal token 'T_DEFAULT))
+ (setq after-special-control-structure round-bracket-level)
+ (setq after-special-control-structure-token token)
+ (setq nesting-key token)
+ (setq special-control-structure-started-this-line t)
+
+ ;; ELSE and ELSEIF after a IF, ELSE, ELESIF
+ ;; and DEFAULT after a CASE
+ ;; should decrease alternative control structure level
+ (when (and nesting-stack
+ (string= (car (cdr (cdr (cdr (car
nesting-stack))))) ":")
+ (or
+ (and (or (equal token 'T_ELSE)
+ (equal token 'T_ELSEIF))
+ (or (equal (car (cdr (cdr (car
nesting-stack)))) 'T_IF)
+ (equal (car (cdr (cdr (car
nesting-stack)))) 'T_ELSEIF)
+ (equal (car (cdr (cdr (car
nesting-stack)))) 'T_ELSE)))
+ (and (equal token 'T_DEFAULT)
+ (equal (car (cdr (cdr (car
nesting-stack)))) 'T_CASE))))
+ (setq alternative-control-structure-level (1-
alternative-control-structure-level))
+
+ (when first-token-on-line
+ (setq first-token-is-nesting-decrease t))
+
+ (phps-mode-debug-message
+ (message "\nDecreasing alternative control structure
nesting at %s to %s\n" token alternative-control-structure-level)))
+
+ )
+
+ ;; Keep track of assignments
+ (when in-assignment
+ (when (or (string= token ";")
+ (and (string= token ")")
+ (or (< round-bracket-level (car
in-assignment-round-bracket-level))
+ (and
+ (= round-bracket-level (car
in-assignment-round-bracket-level))
+ (= square-bracket-level (car
in-assignment-square-bracket-level))
+ (or (string= next-token ")")
+ (string= next-token "]")))))
+ (and (string= token ",")
+ (= round-bracket-level (car
in-assignment-round-bracket-level))
+ (= square-bracket-level (car
in-assignment-square-bracket-level)))
+ (and (string= token "]")
+ (or (< square-bracket-level (car
in-assignment-square-bracket-level))
+ (and
+ (= square-bracket-level (car
in-assignment-square-bracket-level))
+ (= round-bracket-level (car
in-assignment-round-bracket-level))
+ (or (string= next-token "]")
+ (string= next-token ")")))))
+ (and (equal token 'T_FUNCTION)
+ (= round-bracket-level (car
in-assignment-round-bracket-level))))
+
+ ;; NOTE Ending an assignment because of a T_FUNCTION token
is to support PSR-2 Closures
+
+ (phps-mode-debug-message
+ (message "Ended assignment %s at %s %s"
in-assignment-level token next-token))
+ (pop in-assignment-square-bracket-level)
+ (pop in-assignment-round-bracket-level)
+ (unless in-assignment-round-bracket-level
+ (setq in-assignment nil))
+ (setq in-assignment-level (1- in-assignment-level))
+
+ ;; Did we end two assignment at once?
+ (when (and
+ in-assignment-round-bracket-level
+ in-assignment-square-bracket-level
+ (= round-bracket-level (car
in-assignment-round-bracket-level))
+ (= square-bracket-level (car
in-assignment-square-bracket-level))
+ (or (string= next-token ")")
+ (string= next-token "]")))
+ (phps-mode-debug-message
+ (message "Ended another assignment %s at %s %s"
in-assignment-level token next-token))
+ (pop in-assignment-square-bracket-level)
+ (pop in-assignment-round-bracket-level)
+ (unless in-assignment-round-bracket-level
+ (setq in-assignment nil))
+ (setq in-assignment-level (1- in-assignment-level)))
+
+ ))
+
+ (when (and (not after-special-control-structure)
+ (or (string= token "=")
+ (equal token 'T_DOUBLE_ARROW)
+ (equal token 'T_CONCAT_EQUAL)
+ (equal token 'T_POW_EQUAL)
+ (equal token 'T_DIV_EQUAL)
+ (equal token 'T_PLUS_EQUAL)
+ (equal token 'T_MINUS_EQUAL)
+ (equal token 'T_MUL_EQUAL)
+ (equal token 'T_MOD_EQUAL)
+ (equal token 'T_SL_EQUAL)
+ (equal token 'T_SR_EQUAL)
+ (equal token 'T_AND_EQUAL)
+ (equal token 'T_OR_EQUAL)
+ (equal token 'T_XOR_EQUAL)
+ (equal token 'T_COALESCE_EQUAL)))
+ (phps-mode-debug-message "Started assignment")
+ (setq in-assignment t)
+ (push round-bracket-level in-assignment-round-bracket-level)
+ (push square-bracket-level
in-assignment-square-bracket-level)
+ (setq in-assignment-level (1+ in-assignment-level)))
+
+ ;; Second token after a object-operator
+ (when (and
+ in-object-operator
+ in-object-operator-round-bracket-level
+ in-object-operator-square-bracket-level
+ (<= round-bracket-level (car
in-object-operator-round-bracket-level))
+ (<= square-bracket-level (car
in-object-operator-square-bracket-level))
+ (not (or
+ (equal next-token 'T_OBJECT_OPERATOR)
+ (equal next-token 'T_PAAMAYIM_NEKUDOTAYIM))))
+ (phps-mode-debug-message
+ (message "Ended object-operator at %s %s at level %s" token
next-token in-object-operator-level))
+ (pop in-object-operator-round-bracket-level)
+ (pop in-object-operator-square-bracket-level)
+ (setq in-object-operator-level (1- in-object-operator-level))
+ (when (= in-object-operator-level 0)
+ (setq in-object-operator nil)))
+
+ ;; First token after a object-operator
+ (when after-object-operator
+ (when (or (equal next-token 'T_STRING)
+ (string= next-token "("))
+ (progn
+ (phps-mode-debug-message
+ (message "Started object-operator at %s %s on level %s"
token next-token in-object-operator-level))
+ (push round-bracket-level
in-object-operator-round-bracket-level)
+ (push square-bracket-level
in-object-operator-square-bracket-level)
+ (setq in-object-operator t)
+ (setq in-object-operator-level (1+
in-object-operator-level))))
+ (setq after-object-operator nil))
+
+ ;; Starting object-operator?
+ (when (and (or (equal token 'T_OBJECT_OPERATOR)
+ (equal token 'T_PAAMAYIM_NEKUDOTAYIM))
+ (equal next-token 'T_STRING))
+ (phps-mode-debug-message
+ (message "After object-operator at %s level %s" token
in-object-operator-level))
+ (setq after-object-operator t))
+
+ ;; Keep track of return expressions
+ (when in-return
+ (when (and (string= token ";")
+ (= curly-bracket-level (car
in-return-curly-bracket-level)))
+
+ (phps-mode-debug-message (message "Ended return at %s"
token))
+ (pop in-return-curly-bracket-level)
+ (unless in-return-curly-bracket-level
+ (setq in-return nil))
+ (setq in-return-level (1- in-return-level))))
+ (when (equal token 'T_RETURN)
+ (phps-mode-debug-message "Started return")
+ (setq in-return t)
+ (push curly-bracket-level in-return-curly-bracket-level)
+ (setq in-return-level (1+ in-return-level)))
+
+ ;; Did we encounter a token that supports extra special
alternative control structures?
+ (when (equal token 'T_CASE)
+ (setq after-extra-special-control-structure t)
+ (setq nesting-key token)
+ (setq after-extra-special-control-structure-first-on-line
first-token-on-line)
+
+ (when (and switch-case-alternative-stack
+ (= (1- alternative-control-structure-level) (car
switch-case-alternative-stack)))
+
+ (phps-mode-debug-message
+ (message "Found CASE %s vs %s" (1-
alternative-control-structure-level) (car switch-case-alternative-stack)))
+
+ (setq alternative-control-structure-level (1-
alternative-control-structure-level))
+ (when first-token-on-line
+ (setq first-token-is-nesting-decrease t))
+ (pop switch-case-alternative-stack))
+
+ (push alternative-control-structure-level
switch-case-alternative-stack)))
+
+ ;; Do we have one token look-ahead?
+ (when token
+
+ (phps-mode-debug-message (message "Processing token: %s"
token))
+
+ ;; Calculate nesting
+ (setq nesting-end (+ round-bracket-level square-bracket-level
curly-bracket-level alternative-control-structure-level in-assignment-level
in-class-declaration-level in-concatenation-level in-return-level
in-object-operator-level))
+
+ ;; Keep track of whether we are inside a HEREDOC or NOWDOC
+ (when (equal token 'T_START_HEREDOC)
+ (setq in-heredoc t)
+ (setq in-heredoc-started-this-line t))
+ (when (equal token 'T_END_HEREDOC)
+ (setq in-heredoc nil)
+ (setq in-heredoc-ended-this-line t))
+
+ ;; Has nesting increased?
+ (when (and nesting-stack
+ (<= nesting-end (car (car nesting-stack))))
+ (let ((nesting-decrement 0))
+
+ ;; Handle case were nesting has decreased less than next
as well
+ (while (and nesting-stack
+ (<= nesting-end (car (car nesting-stack))))
+ (phps-mode-debug-message
+ (message "\nPopping %s from nesting-stack since %s is
lesser or equal to %s, next value is: %s\n" (car nesting-stack) nesting-end
(car (car nesting-stack)) (nth 1 nesting-stack)))
+ (pop nesting-stack)
+ (setq nesting-decrement (1+ nesting-decrement)))
+
+ (if first-token-is-nesting-decrease
+
+ (progn
+ ;; Decrement column
+ (if allow-custom-column-decrement
+ (progn
+ (phps-mode-debug-message
+ (message "Doing custom decrement 1 from %s to
%s" column-level (- column-level (- nesting-start nesting-end))))
+ (setq column-level (- column-level (-
nesting-start nesting-end)))
+ (setq allow-custom-column-decrement nil))
+ (phps-mode-debug-message
+ (message "Doing regular decrement 1 from %s to
%s" column-level (1- column-level)))
+ (setq column-level (- column-level
nesting-decrement)))
+
+ ;; Prevent negative column-values
+ (when (< column-level 0)
+ (setq column-level 0)))
+
+ (unless temp-post-indent
+ (phps-mode-debug-message
+ (message "Temporary setting post indent %s"
column-level))
+ (setq temp-post-indent column-level))
+
+ ;; Decrement column
+ (if allow-custom-column-decrement
+ (progn
+ (phps-mode-debug-message
+ (message "Doing custom decrement 2 from %s to %s"
column-level (- column-level (- nesting-start nesting-end))))
+ (setq temp-post-indent (- temp-post-indent (-
nesting-start nesting-end)))
+ (setq allow-custom-column-decrement nil))
+ (setq temp-post-indent (- temp-post-indent
nesting-decrement)))
+
+ ;; Prevent negative column-values
+ (when (< temp-post-indent 0)
+ (setq temp-post-indent 0))
+
+ )))
+
+ ;; Are we on a new line or is it the last token of the buffer?
+ (if (> next-token-start-line-number token-start-line-number)
+ (progn
+
+
+ ;; ;; Start indentation might differ from ending
indentation in cases like } else {
+ (setq column-level-start column-level)
+
+ ;; Support temporarily pre-indent
+ (when temp-pre-indent
+ (setq column-level-start temp-pre-indent)
+ (setq temp-pre-indent nil))
+
+ ;; HEREDOC lines should have zero indent
+ (when (or (and in-heredoc
+ (not in-heredoc-started-this-line))
+ in-heredoc-ended-this-line)
+ (setq column-level-start 0))
+
+ ;; Inline HTML should have zero indent
+ (when (and first-token-is-inline-html
+ (not inline-html-is-whitespace))
+ (phps-mode-debug-message
+ (message "Setting column-level to inline HTML indent:
%s" inline-html-indent-start))
+ (setq column-level-start inline-html-indent-start))
+
+ ;; Save line indent
+ (phps-mode-debug-message
+ (message "Process line ending. nesting: %s-%s,
line-number: %s-%s, indent: %s.%s, token: %s" nesting-start nesting-end
token-start-line-number token-end-line-number column-level-start tuning-level
token))
+
+ (when (and (> token-start-line-number 0)
+ (or
+ (not first-token-is-inline-html)
+ inline-html-is-whitespace))
+ (phps-mode-debug-message
+ (message "Putting indent on line %s to %s at #C"
token-start-line-number column-level-start))
+ (puthash token-start-line-number `(,column-level-start
,tuning-level) line-indents))
+
+ ;; Support trailing indent decrements
+ (when temp-post-indent
+ (setq column-level temp-post-indent)
+ (setq temp-post-indent nil))
+
+ ;; Increase indentation
+ (when (and (> nesting-end 0)
+ (or (not nesting-stack)
+ (> nesting-end (car (cdr (car
nesting-stack))))))
+ (let ((nesting-stack-end 0))
+ (when nesting-stack
+ (setq nesting-stack-end (car (cdr (car
nesting-stack)))))
+
+ (if allow-custom-column-increment
+ (progn
+ (setq column-level (+ column-level (-
nesting-end nesting-start)))
+ (setq allow-custom-column-increment nil))
+ (setq column-level (1+ column-level)))
+
+ (phps-mode-debug-message
+ (message "\nPushing (%s %s %s %s) to nesting-stack
since %s is greater than %s or stack is empty\n" nesting-start nesting-end
nesting-key token nesting-end (car (cdr (car nesting-stack))))
+ )
+ (push `(,nesting-stack-end ,nesting-end ,nesting-key
,token) nesting-stack)))
+
+
+ ;; Does token span over several lines and is it not a
INLINE_HTML token?
+ (when (and (> token-end-line-number
token-start-line-number)
+ (not (equal token 'T_INLINE_HTML)))
+ (let ((column-level-end column-level))
+
+ ;; HEREDOC lines should have zero indent
+ (when (or (and in-heredoc
+ (not in-heredoc-started-this-line))
+ in-heredoc-ended-this-line)
+ (setq column-level-end 0))
+
+ ;; (message "Token %s starts at %s and ends at %s
indent %s %s" next-token token-start-line-number token-end-line-number
column-level-end tuning-level)
+
+ ;; Indent doc-comment lines with 1 tuning
+ (when (equal token 'T_DOC_COMMENT)
+ (setq tuning-level 1))
+
+ (let ((token-line-number-diff (1- (-
token-end-line-number token-start-line-number))))
+ (while (>= token-line-number-diff 0)
+ (phps-mode-debug-message
+ (message "Putting indent on line %s to %s at
#A" (- token-end-line-number token-line-number-diff) column-level-end))
+ (puthash (- token-end-line-number
token-line-number-diff) `(,column-level-end ,tuning-level) line-indents)
+ ;; (message "Saved line %s indent %s %s" (-
token-end-line-number token-line-number-diff) column-level tuning-level)
+ (setq token-line-number-diff (1-
token-line-number-diff))))
+
+ ;; Rest tuning-level used for comments
+ (setq tuning-level 0)))
+
+ ;; Indent token-less lines here in between last tokens
if distance is more than 1 line
+ (when (and (> next-token-start-line-number (1+
token-end-line-number))
+ (not (equal token 'T_CLOSE_TAG)))
+
+ (phps-mode-debug-message
+ (message "\nDetected token-less lines between %s and
%s, should have indent: %s\n" token-end-line-number
next-token-start-line-number column-level))
+
+ (let ((token-line-number-diff (1- (-
next-token-start-line-number token-end-line-number))))
+ (while (> token-line-number-diff 0)
+ (phps-mode-debug-message
+ (message "Putting indent at line %s indent %s at
#B" (- next-token-start-line-number token-line-number-diff) column-level))
+ (puthash (- next-token-start-line-number
token-line-number-diff) `(,column-level ,tuning-level) line-indents)
+ (setq token-line-number-diff (1-
token-line-number-diff)))))
+
+
+ ;; Calculate indentation level at start of line
+ (setq nesting-start (+ round-bracket-level
square-bracket-level curly-bracket-level alternative-control-structure-level
in-assignment-level in-class-declaration-level in-concatenation-level
in-return-level in-object-operator-level))
+
+ ;; Set initial values for tracking first token
+ (when (> token-start-line-number last-line-number)
+ (setq inline-html-indent-start inline-html-indent)
+ (setq first-token-on-line t)
+ (setq first-token-is-nesting-decrease nil)
+ (setq first-token-is-inline-html nil)
+ (setq in-class-declaration-level 0)
+ (setq class-declaration-started-this-line nil)
+ (setq in-heredoc-started-this-line nil)
+ (setq special-control-structure-started-this-line nil)
+
+ ;; When line ends with multi-line inline-html flag
first token as inline-html
+ (when (and
+ (equal token 'T_INLINE_HTML)
+ (not inline-html-is-whitespace)
+ (> token-end-line-number
token-start-line-number))
+
+ (setq inline-html-is-whitespace
+ (not (null
+ (string-match "[\n\C-m][ \t]+$"
(substring string (1- token-start) (1- token-end))))))
+ (phps-mode-debug-message
+ (message "Trailing inline html line is whitespace:
%s" inline-html-is-whitespace))
+ (phps-mode-debug-message
+ (message "Setting first-token-is-inline-html to
true since last token on line is inline-html and spans several lines"))
+ (setq first-token-is-inline-html t))))
+
+ ;; Current token is not first if it's not <?php or <?=
+ (unless (or (equal token 'T_OPEN_TAG)
+ (equal token 'T_OPEN_TAG_WITH_ECHO))
+ (setq first-token-on-line nil))
+
+ (when (> token-end-line-number token-start-line-number)
+ ;; (message "Token not first on line %s starts at %s and
ends at %s" token token-start-line-number token-end-line-number)
+ (when (equal token 'T_DOC_COMMENT)
+ (setq tuning-level 1))
+
+ (let ((token-line-number-diff (1- (- token-end-line-number
token-start-line-number))))
+ (while (>= token-line-number-diff 0)
+ (phps-mode-debug-message
+ (message "Putting indent on line %s to %s at #E" (-
token-end-line-number token-line-number-diff) column-level))
+ (puthash (- token-end-line-number
token-line-number-diff) `(,column-level ,tuning-level) line-indents)
+ (setq token-line-number-diff (1-
token-line-number-diff))))
+ (setq tuning-level 0))))
+
+ ;; Update current token
+ (setq previous-token token)
+ (setq token next-token)
+ (setq token-start next-token-start)
+ (setq token-end next-token-end)
+ (setq token-start-line-number next-token-start-line-number)
+ (setq token-end-line-number next-token-end-line-number)
+ (setq token-number (1+ token-number))))
+ (list (nreverse imenu-index) line-indents)))
+ (list nil nil)))
+
+(defun phps-mode-functions-indent-line ()
+ "Indent line."
+ (phps-mode-debug-message (message "Indent line"))
+ (phps-mode-functions-process-current-buffer)
+ (if phps-mode-functions-lines-indent
+ (let ((line-number (line-number-at-pos (point))))
+ (phps-mode-debug-message (message "Found lines indent index,
indenting.."))
+ (let ((indent (gethash line-number phps-mode-functions-lines-indent)))
+ (if indent
+ (progn
+ (let ((indent-sum (+ (* (car indent) tab-width) (car (cdr
indent))))
+ (old-indentation (current-indentation))
+ (line-start (line-beginning-position)))
+
+ (unless old-indentation
+ (setq old-indentation 0))
+
+ ;; Only continue if current indentation is wrong
+ (if (not (equal indent-sum old-indentation))
+ (progn
+
+ (setq-local phps-mode-functions-allow-after-change nil)
+ (indent-line-to indent-sum)
+ (setq-local phps-mode-functions-allow-after-change t)
+
+ (let ((indent-diff (- (current-indentation)
old-indentation)))
+
+
+ ;; When indent is changed the trailing tokens and
states just need to adjust their positions, this will improve speed of
indent-region a lot
+ (phps-mode-lexer-move-tokens line-start indent-diff)
+ (phps-mode-lexer-move-states line-start indent-diff)
+ (phps-mode-functions-move-imenu-index line-start
indent-diff)
+
+ (phps-mode-debug-message
+ (message "Lexer tokens after move: %s"
phps-mode-lexer-tokens)
+ (message "Lexer states after move: %s"
phps-mode-lexer-states))
+
+ ;; Reset change flag
+ (phps-mode-functions--reset-changes)
+ (phps-mode-functions--cancel-idle-timer)
+
+ ;; Update last buffer states
+ (setq-local phps-mode-lexer-buffer-length (1-
(point-max)))
+ (setq-local phps-mode-lexer-buffer-contents
(buffer-substring-no-properties (point-min) (point-max)))
+
+ ))))))))
+ (phps-mode-debug-message "Did not find lines indent index, skipping
indenting..")
+ (message "Did not find lines indent index, skipping indenting..")))
+
+(defun phps-mode-functions--reset-changes ()
+ "Reset change stack."
+ (setq-local phps-mode-functions-buffer-changes nil))
+
+(defun phps-mode-functions--get-changes ()
+ "Get change stack."
+ phps-mode-functions-buffer-changes)
+
+(defun phps-mode-functions--cancel-idle-timer ()
+ "Cancel idle timer."
+ (phps-mode-debug-message (message "Cancelled idle timer"))
+ (when phps-mode-functions-idle-timer
+ (cancel-timer phps-mode-functions-idle-timer)
+ (setq-local phps-mode-functions-idle-timer nil)))
+
+(defun phps-mode-functions--start-idle-timer ()
+ "Start idle timer."
+ (phps-mode-debug-message (message "Enqueued idle timer"))
+ (when (boundp 'phps-mode-idle-interval)
+ (setq-local phps-mode-functions-idle-timer (run-with-idle-timer
phps-mode-idle-interval nil #'phps-mode-lexer-run-incremental
(current-buffer)))))
+
+(defun phps-mode-functions-after-change (start stop length)
+ "Track buffer change from START to STOP with LENGTH."
+ (phps-mode-debug-message
+ (message "After change %s - %s, length: %s" start stop length))
+
+ (if phps-mode-functions-allow-after-change
+ (progn
+ (phps-mode-debug-message (message "After change registration is
enabled"))
+
+ ;; If we haven't scheduled incremental lexer before - do it
+ (when (and (boundp 'phps-mode-idle-interval)
+ phps-mode-idle-interval
+ (not phps-mode-functions-idle-timer))
+
+ ;; Reset imenu
+ (when (and (boundp 'imenu--index-alist)
+ imenu--index-alist)
+ (setq-local imenu--index-alist nil)
+ (phps-mode-debug-message (message "Cleared Imenu index")))
+
+ (phps-mode-functions--start-idle-timer))
+
+ ;; Save change in changes stack
+ (push `(,start ,stop ,length ,(point-max)
,(buffer-substring-no-properties (point-min) (point-max)))
phps-mode-functions-buffer-changes))
+ (phps-mode-debug-message (message "After change registration is
disabled"))))
+
+(defun phps-mode-functions-imenu-create-index ()
+ "Get Imenu for current buffer."
+ (phps-mode-functions-process-current-buffer)
+ phps-mode-functions-imenu)
+
+(defun phps-mode-functions-comment-region (beg end &optional _arg)
+ "Comment region from BEG to END with optional ARG."
+ ;; Iterate tokens from beginning to end and comment out all PHP code
+ (when-let ((tokens phps-mode-lexer-tokens))
+ (let ((token-comment-start nil)
+ (token-comment-end nil)
+ (in-token-comment nil)
+ (offset 0))
+ (dolist (token tokens)
+ (let ((token-label (car token))
+ (token-start (car (cdr token)))
+ (token-end (cdr (cdr token))))
+ (when (and (>= token-start beg)
+ (<= token-end end))
+
+ (if in-token-comment
+ (cond
+ ((or
+ (equal token-label 'T_COMMENT)
+ (equal token-label 'T_DOC_COMMENT)
+ (equal token-label 'T_CLOSE_TAG))
+ (setq in-token-comment nil))
+ (t (setq token-comment-end token-end)))
+
+ ;; When we have a start and end of comment, comment it out
+ (when (and
+ token-comment-start
+ token-comment-end)
+ (let ((offset-comment-start (+ token-comment-start offset))
+ (offset-comment-end))
+ (save-excursion
+ (goto-char offset-comment-start)
+ (insert "/* "))
+ (setq offset (+ offset 3))
+ (setq offset-comment-end (+ token-comment-end offset))
+ (save-excursion
+ (goto-char offset-comment-end)
+ (insert " */"))
+ (setq offset (+ offset 3))
+ (phps-mode-debug-message
+ (message "Commented out %s-%s" offset-comment-start
offset-comment-end)))
+ (setq token-comment-start nil)
+ (setq token-comment-end nil))
+
+ (cond
+ ((or
+ (equal token-label 'T_INLINE_HTML)
+ (equal token-label 'T_OPEN_TAG)
+ (equal token-label 'T_OPEN_TAG_WITH_ECHO)))
+ (t
+ (phps-mode-debug-message
+ (message "Comment should start at %s %s" token-label
token-start))
+ (setq token-comment-start token-start)
+ (setq in-token-comment t)))))))
+
+ ;; When we have a start and end of comment, comment it out
+ (when (and
+ in-token-comment
+ token-comment-start
+ token-comment-end)
+ (let ((offset-comment-start (+ token-comment-start offset))
+ (offset-comment-end))
+ (save-excursion
+ (goto-char offset-comment-start)
+ (insert "/* "))
+ (setq offset (+ offset 3))
+ (setq offset-comment-end (+ token-comment-end offset))
+ (save-excursion
+ (goto-char offset-comment-end)
+ (insert " */"))
+ (setq offset (+ offset 3))
+ (phps-mode-debug-message
+ (message "Commented out trailing %s-%s" offset-comment-start
offset-comment-end)))
+ (setq token-comment-start nil)
+ (setq token-comment-end nil)))))
+
+(defun phps-mode-functions-uncomment-region (beg end &optional _arg)
+ "Un-comment region from BEG to END with optional ARG."
+ ;; Iterate tokens from beginning to end and uncomment out all commented PHP
code
+ (when-let ((tokens phps-mode-lexer-tokens))
+ (let ((offset 0))
+ (dolist (token tokens)
+ (let ((token-label (car token))
+ (token-start (car (cdr token)))
+ (token-end (cdr (cdr token))))
+ (when (and (>= token-start beg)
+ (<= token-end end))
+ (when (or
+ (equal token-label 'T_COMMENT)
+ (equal token-label 'T_DOC_COMMENT))
+
+ (phps-mode-debug-message
+ (message "Un-comment comment at %s %s" token-label token-start
token-end))
+
+ (let ((offset-comment-start (+ token-start offset))
+ (offset-comment-end))
+
+ (if (equal token-label 'T_DOC_COMMENT)
+ (progn
+ (phps-mode-debug-message
+ (message "Un-comment doc comment at %s-%s" token-start
token-end))
+ (save-excursion
+ (goto-char offset-comment-start)
+ (delete-char 4))
+ (setq offset (- offset 4))
+ (setq offset-comment-end (+ token-end offset))
+ (save-excursion
+ (goto-char offset-comment-end)
+ (delete-char -4))
+ (setq offset (- offset 4)))
+
+ (phps-mode-debug-message
+ (message "Un-comment comment starting at %s" token-start))
+
+ (cond
+
+ ((string=
+ (buffer-substring-no-properties offset-comment-start (+
offset-comment-start 1))
+ "#")
+ (save-excursion
+ (goto-char offset-comment-start)
+ (delete-char 1))
+ (setq offset (- offset 1)))
+ ((string=
+ (buffer-substring-no-properties offset-comment-start (+
offset-comment-start 2))
+ "//")
+ (save-excursion
+ (goto-char offset-comment-start)
+ (delete-char 2))
+ (setq offset (- offset 2)))
+ (t
+ (save-excursion
+ (goto-char offset-comment-start)
+ (delete-char 3))
+ (setq offset (- offset 3))))
+
+
+ (setq offset-comment-end (+ token-end offset))
+ (if (string=
+ (buffer-substring-no-properties (- offset-comment-end
3) offset-comment-end)
+ " */")
+ (progn
+ (phps-mode-debug-message
+ (message "Un-comment comment ending at %s" token-end))
+ (save-excursion
+ (goto-char offset-comment-end)
+ (delete-char -3))
+ (setq offset (- offset 3)))
+ (phps-mode-debug-message
+ (message "Do not un-comment comment ending at %s"
token-end))))))))))))
+
+(provide 'phps-mode-analyzer)
-;;; phps-mode-lexer.el ends here
+;;; phps-mode-analyzer.el ends here
diff --git a/phps-mode-flymake.el b/phps-mode-flymake.el
index ead108d..b1d1078 100644
--- a/phps-mode-flymake.el
+++ b/phps-mode-flymake.el
@@ -27,8 +27,6 @@
(require 'flymake)
-;; TODO Implement this
-
(defun phps-mode-flymake-init ()
"PHP specific init-cleanup routines.
diff --git a/phps-mode-functions.el b/phps-mode-functions.el
deleted file mode 100644
index 9466f17..0000000
--- a/phps-mode-functions.el
+++ /dev/null
@@ -1,1379 +0,0 @@
-;;; phps-mode-functions.el --- Mode functions for PHPs -*- lexical-binding: t
-*-
-
-;; Copyright (C) 2018-2019 Free Software Foundation, Inc.
-
-;; This file is not part of GNU Emacs.
-
-;; 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 2, 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 GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
-
-
-;;; Commentary:
-
-
-;;; Code:
-
-(require 'subr-x)
-(require 'phps-mode-lexer)
-
-(autoload 'phps-mode-runtime-debug-message "phps-mode")
-
-(require 'phps-mode-macros)
-
-(defvar phps-mode-functions-allow-after-change t
- "Flag to tell us whether after change detection is enabled or not.")
-
-(defvar phps-mode-functions-buffer-changes nil
- "A stack of buffer changes.")
-
-(defvar phps-mode-functions-idle-timer nil
- "Timer object of idle timer.")
-
-(defvar phps-mode-functions-imenu nil
- "The Imenu alist for current buffer, nil if none.")
-
-(defvar phps-mode-functions-lines-indent nil
- "The indentation of each line in buffer, nil if none.")
-
-(defvar phps-mode-functions-processed-buffer nil
- "Flag whether current buffer is processed or not.")
-
-(defun phps-mode-functions-get-processed-buffer ()
- "Get flag for whether buffer is processed or not."
- phps-mode-functions-processed-buffer)
-
-(defun phps-mode-functions-reset-processed-buffer ()
- "Reset flag for whether buffer is processed or not."
- (setq-local phps-mode-functions-processed-buffer nil))
-
-(defun phps-mode-functions-process-current-buffer ()
- "Process current buffer, generate indentations and Imenu, trigger
incremental lexer if we have change."
- (interactive)
- (phps-mode-debug-message (message "Process current buffer"))
- (when phps-mode-functions-idle-timer
- (phps-mode-debug-message (message "Trigger incremental lexer"))
- (phps-mode-lexer-run-incremental (current-buffer))
- (setq-local phps-mode-functions-processed-buffer nil))
- (if (not phps-mode-functions-processed-buffer)
- (progn
- (phps-mode-debug-message (message "Buffer is not processed"))
- (let ((processed (phps-mode-functions--process-tokens-in-string
phps-mode-lexer-tokens (buffer-substring-no-properties (point-min)
(point-max)))))
- (phps-mode-debug-message (message "Processed result: %s" processed))
- (setq-local phps-mode-functions-imenu (nth 0 processed))
- (setq-local phps-mode-functions-lines-indent (nth 1 processed)))
- (setq-local phps-mode-functions-processed-buffer t))
- (phps-mode-debug-message (message "Buffer is already processed"))))
-
-(defun phps-mode-functions-get-moved-lines-indent (old-lines-indents
start-line-number diff)
- "Move OLD-LINES-INDENTS from START-LINE-NUMBER with DIFF points."
- (let ((lines-indents (make-hash-table :test 'equal))
- (line-number 1))
- (when old-lines-indents
- (let ((line-indent (gethash line-number old-lines-indents))
- (new-line-number))
- (while line-indent
-
- (when (< line-number start-line-number)
- ;; (message "Added new indent 3 %s from %s to %s" line-indent
line-number line-number)
- (puthash line-number line-indent lines-indents))
-
- (when (and (> diff 0)
- (>= line-number start-line-number)
- (< line-number (+ start-line-number diff)))
- ;; (message "Added new indent 2 %s from %s to %s" line-indent
line-number line-number)
- (puthash line-number (gethash start-line-number old-lines-indents)
lines-indents))
-
- (when (>= line-number start-line-number)
- (setq new-line-number (+ line-number diff))
- ;; (message "Added new indent %s from %s to %s" line-indent
line-number new-line-number)
- (puthash new-line-number line-indent lines-indents))
-
- (setq line-number (1+ line-number))
- (setq line-indent (gethash line-number old-lines-indents))))
- lines-indents)))
-
-(defun phps-mode-functions-move-imenu-index (start diff)
- "Moved imenu from START by DIFF points."
- (when phps-mode-functions-imenu
- (setq-local phps-mode-functions-imenu (phps-mode-functions-get-moved-imenu
phps-mode-functions-imenu start diff))))
-
-(defun phps-mode-functions-move-lines-indent (start-line-number diff)
- "Move lines indent from START-LINE-NUMBER with DIFF points."
- (when phps-mode-functions-lines-indent
- ;; (message "Moving line-indent index from %s with %s" start-line-number
diff)
- (setq-local phps-mode-functions-lines-indent
(phps-mode-functions-get-moved-lines-indent phps-mode-functions-lines-indent
start-line-number diff))))
-
-(defun phps-mode-functions-get-lines-indent ()
- "Return lines indent, process buffer if not done already."
- (phps-mode-functions-process-current-buffer)
- phps-mode-functions-lines-indent)
-
-(defun phps-mode-functions-get-imenu ()
- "Return Imenu, process buffer if not done already."
- (phps-mode-functions-process-current-buffer)
- phps-mode-functions-imenu)
-
-(defun phps-mode-functions-get-moved-imenu (old-index start diff)
- "Move imenu-index OLD-INDEX beginning from START with DIFF."
- (let ((new-index '()))
-
- (when old-index
- (if (and (listp old-index)
- (listp (car old-index)))
- (dolist (item old-index)
- (let ((sub-item (phps-mode-functions-get-moved-imenu item start
diff)))
- (push (car sub-item) new-index)))
- (let ((item old-index))
- (let ((item-label (car item)))
- (if (listp (cdr item))
- (let ((sub-item (phps-mode-functions-get-moved-imenu (cdr
item) start diff)))
- (push `(,item-label . ,sub-item) new-index))
- (let ((item-start (cdr item)))
- (when (>= item-start start)
- (setq item-start (+ item-start diff)))
- (push `(,item-label . ,item-start) new-index)))))))
-
- (nreverse new-index)))
-
-(defun phps-mode-functions--get-lines-in-buffer (beg end)
- "Return the number of lines in buffer between BEG and END."
- (phps-mode-functions--get-lines-in-string (buffer-substring-no-properties
beg end)))
-
-(defun phps-mode-functions--get-lines-in-string (string)
- "Return the number of lines in STRING."
- (let ((lines-in-string 0)
- (start 0))
- (while (string-match "[\n\C-m]" string start)
- (setq start (match-end 0))
- (setq lines-in-string (1+ lines-in-string)))
- lines-in-string))
-
-(defun phps-mode-functions--get-inline-html-indentation (inline-html indent
tag-level curly-bracket-level square-bracket-level round-bracket-level)
- "Generate a list of indentation for each line in INLINE-HTML, working
incrementally on INDENT, TAG-LEVEL, CURLY-BRACKET-LEVEL, SQUARE-BRACKET-LEVEL
and ROUND-BRACKET-LEVEL."
- (phps-mode-debug-message
- (message "Calculating HTML indent for: '%s'" inline-html))
-
- ;; Add trailing newline if missing
- (unless (string-match "\n$" inline-html)
- (setq inline-html (concat inline-html "\n")))
-
- (let ((start 0)
- (indent-start indent)
- (indent-end indent)
- (line-indents nil)
- (first-object-on-line t)
- (first-object-is-nesting-decrease nil))
- (while (string-match
"\\([\n\C-m]\\)\\|\\(<[a-zA-Z]+\\)\\|\\(</[a-zA-Z]+\\)\\|\\(/>\\)\\|\\(\\[\\)\\|\\()\\)\\|\\((\\)"
inline-html start)
- (let* ((end (match-end 0))
- (string (substring inline-html (match-beginning 0) end)))
-
- (cond
-
- ((string= string "\n")
-
- (let ((temp-indent indent))
- (when first-object-is-nesting-decrease
- (phps-mode-debug-message
- (message "Decreasing indent with one since first object was a
nesting decrease"))
- (setq temp-indent (1- indent))
- (when (< temp-indent 0)
- (setq temp-indent 0)))
- (push temp-indent line-indents))
-
- (setq indent-end (+ tag-level curly-bracket-level
square-bracket-level round-bracket-level))
- (phps-mode-debug-message "Encountered a new-line")
- (if (> indent-end indent-start)
- (progn
- (phps-mode-debug-message
- (message "Increasing indent since %s is above %s" indent-end
indent-start))
- (setq indent (1+ indent)))
- (when (< indent-end indent-start)
- (phps-mode-debug-message
- (message "Decreasing indent since %s is below %s" indent-end
indent-start))
- (setq indent (1- indent))
- (when (< indent 0)
- (setq indent 0))))
-
- (setq indent-start indent-end)
- (setq first-object-on-line t)
- (setq first-object-is-nesting-decrease nil))
-
- ((string= string "(")
- (setq round-bracket-level (1+ round-bracket-level)))
- ((string= string ")")
- (setq round-bracket-level (1- round-bracket-level)))
-
- ((string= string "[")
- (setq square-bracket-level (1+ square-bracket-level)))
- ((string= string "]")
- (setq square-bracket-level (1- square-bracket-level)))
-
- ((string= string "{")
- (setq curly-bracket-level (1+ curly-bracket-level)))
- ((string= string "}")
- (setq curly-bracket-level (1- curly-bracket-level)))
-
- ((string-match "<[a-zA-Z]+" string)
- (setq tag-level (1+ tag-level)))
-
- ((string-match "\\(</[a-zA-Z]+\\)\\|\\(/>\\)" string)
- (setq tag-level (1- tag-level)))
-
- )
-
- (when first-object-on-line
- (unless (string= string "\n")
- (setq first-object-on-line nil)
- (setq indent-end (+ tag-level curly-bracket-level
square-bracket-level round-bracket-level))
- (when (< indent-end indent-start)
- (phps-mode-debug-message "First object was nesting decrease")
- (setq first-object-is-nesting-decrease t))))
-
- (setq start end)))
- (list (nreverse line-indents) indent tag-level curly-bracket-level
square-bracket-level round-bracket-level)))
-
-(defun phps-mode-functions--process-tokens-in-string (tokens string)
- "Generate indexes for imenu and indentation for TOKENS and STRING one pass.
Complexity: O(n)."
- (if tokens
- (progn
- (phps-mode-debug-message (message "\nCalculation indentation and imenu
for all lines in buffer:\n\n%s" string))
- (let ((in-heredoc nil)
- (in-heredoc-started-this-line nil)
- (in-heredoc-ended-this-line nil)
- (in-inline-control-structure nil)
- (inline-html-indent 0)
- (inline-html-indent-start 0)
- (inline-html-tag-level 0)
- (inline-html-curly-bracket-level 0)
- (inline-html-square-bracket-level 0)
- (inline-html-round-bracket-level 0)
- (inline-html-is-whitespace nil)
- (first-token-is-inline-html nil)
- (after-special-control-structure nil)
- (after-special-control-structure-token nil)
- (after-extra-special-control-structure nil)
- (after-extra-special-control-structure-first-on-line nil)
- (switch-curly-stack nil)
- (switch-alternative-stack nil)
- (switch-case-alternative-stack nil)
- (curly-bracket-level 0)
- (round-bracket-level 0)
- (square-bracket-level 0)
- (alternative-control-structure-level 0)
- (in-concatenation nil)
- (in-concatenation-round-bracket-level nil)
- (in-concatenation-square-bracket-level nil)
- (in-concatenation-level 0)
- (column-level 0)
- (column-level-start 0)
- (tuning-level 0)
- (nesting-start 0)
- (nesting-end 0)
- (last-line-number 0)
- (first-token-on-line t)
- (line-indents (make-hash-table :test 'equal))
- (first-token-is-nesting-decrease nil)
- (token-number 1)
- (allow-custom-column-increment nil)
- (allow-custom-column-decrement nil)
- (in-assignment nil)
- (in-assignment-round-bracket-level nil)
- (in-assignment-square-bracket-level nil)
- (in-assignment-level 0)
- (in-object-operator nil)
- (in-object-operator-round-bracket-level nil)
- (in-object-operator-square-bracket-level nil)
- (after-object-operator nil)
- (in-object-operator-level 0)
- (in-class-declaration nil)
- (in-class-declaration-level 0)
- (in-return nil)
- (in-return-curly-bracket-level nil)
- (in-return-level 0)
- (previous-token nil)
- (token nil)
- (token-start nil)
- (token-end nil)
- (token-start-line-number 0)
- (token-end-line-number 0)
- (tokens (nreverse (copy-sequence tokens)))
- (nesting-stack nil)
- (nesting-key nil)
- (class-declaration-started-this-line nil)
- (special-control-structure-started-this-line nil)
- (temp-pre-indent nil)
- (temp-post-indent nil)
- (imenu-index '())
- (imenu-namespace-index '())
- (imenu-class-index '())
- (imenu-in-namespace-declaration nil)
- (imenu-in-namespace-name nil)
- (imenu-in-namespace-with-brackets nil)
- (imenu-open-namespace-level nil)
- (imenu-in-class-declaration nil)
- (imenu-open-class-level nil)
- (imenu-in-class-name nil)
- (imenu-in-function-declaration nil)
- (imenu-in-function-name nil)
- (imenu-in-function-index nil)
- (imenu-nesting-level 0)
- (incremental-line-number 1))
-
- (push `(END_PARSE ,(length string) . ,(length string)) tokens)
-
- ;; Iterate through all buffer tokens from beginning to end
- (dolist (item (nreverse tokens))
- ;; (message "Items: %s %s" item phps-mode-lexer-tokens)
- (let ((next-token (car item))
- (next-token-start (car (cdr item)))
- (next-token-end (cdr (cdr item)))
- (next-token-start-line-number nil)
- (next-token-end-line-number nil))
-
- (when (and token
- (< token-end next-token-start))
- ;; NOTE We use a incremental-line-number calculation because
`line-at-pos' takes a lot of time
- (setq incremental-line-number (+ incremental-line-number
(phps-mode-functions--get-lines-in-string (substring string (1- token-end) (1-
next-token-start))))))
-
- ;; Handle the pseudo-token for last-line
- (if (equal next-token 'END_PARSE)
- (progn
- (setq next-token-start-line-number (1+
token-start-line-number))
- (setq next-token-end-line-number (1+
token-end-line-number)))
- (setq next-token-start-line-number incremental-line-number)
-
- ;; NOTE We use a incremental-line-number calculation because
`line-at-pos' takes a lot of time
- ;; (message "Lines for %s '%s'" next-token (substring string
(1- next-token-start) (1- next-token-end)))
- (setq incremental-line-number (+ incremental-line-number
(phps-mode-functions--get-lines-in-string (substring string (1-
next-token-start) (1- next-token-end)))))
- (setq next-token-end-line-number incremental-line-number)
- (phps-mode-debug-message
- (message "Token '%s' pos: %s-%s lines: %s-%s" next-token
next-token-start next-token-end next-token-start-line-number
next-token-end-line-number)))
-
- ;; Token logic - we have one-two token look-ahead at this point
- ;; `token' is previous token
- ;; `next-token' is current token
- ;; `previous-token' is maybe two tokens back
- (when token
-
-
- ;; IMENU LOGIC
-
- (cond
-
- ((or (string= token "{")
- (equal token 'T_CURLY_OPEN)
- (equal token 'T_DOLLAR_OPEN_CURLY_BRACES))
- (setq imenu-nesting-level (1+ imenu-nesting-level)))
-
- ((string= token "}")
-
- (when (and imenu-open-namespace-level
- (= imenu-open-namespace-level imenu-nesting-level)
- imenu-in-namespace-name)
- (let ((imenu-add-list (nreverse imenu-namespace-index)))
- (push `(,imenu-in-namespace-name . ,imenu-add-list)
imenu-index))
- (setq imenu-in-namespace-name nil))
-
- (when (and imenu-open-class-level
- (= imenu-open-class-level imenu-nesting-level)
- imenu-in-class-name)
- (let ((imenu-add-list (nreverse imenu-class-index)))
- (if imenu-in-namespace-name
- (push `(,imenu-in-class-name . ,imenu-add-list)
imenu-namespace-index)
- (push `(,imenu-in-class-name . ,imenu-add-list)
imenu-index)))
- (setq imenu-in-class-name nil))
-
- (setq imenu-nesting-level (1- imenu-nesting-level))))
-
- (when (and (equal next-token 'END_PARSE)
- imenu-in-namespace-name
- (not imenu-in-namespace-with-brackets))
- (let ((imenu-add-list (nreverse imenu-namespace-index)))
- (push `(,imenu-in-namespace-name . ,imenu-add-list)
imenu-index))
- (setq imenu-in-namespace-name nil))
-
- (cond
-
- (imenu-in-namespace-declaration
- (cond
-
- ((or (string= token "{")
- (string= token ";"))
- (setq imenu-in-namespace-with-brackets (string= token "{"))
- (setq imenu-open-namespace-level imenu-nesting-level)
- (setq imenu-namespace-index '())
- (setq imenu-in-namespace-declaration nil))
-
- ((and (or (equal token 'T_STRING)
- (equal token 'T_NS_SEPARATOR))
- (setq imenu-in-namespace-name (concat
imenu-in-namespace-name (substring string (1- token-start) (1- token-end))))))))
-
- (imenu-in-class-declaration
- (cond
-
- ((string= token "{")
- (setq imenu-open-class-level imenu-nesting-level)
- (setq imenu-in-class-declaration nil)
- (setq imenu-class-index '()))
-
- ((and (equal token 'T_STRING)
- (not imenu-in-class-name))
- (setq imenu-in-class-name (substring string (1-
token-start) (1- token-end))))))
-
- (imenu-in-function-declaration
- (cond
-
- ((or (string= token "{")
- (string= token ";"))
- (when imenu-in-function-name
- (if imenu-in-class-name
- (push `(,imenu-in-function-name .
,imenu-in-function-index) imenu-class-index)
- (if imenu-in-namespace-name
- (push `(,imenu-in-function-name .
,imenu-in-function-index) imenu-namespace-index)
- (push `(,imenu-in-function-name .
,imenu-in-function-index) imenu-index))))
- (setq imenu-in-function-name nil)
- (setq imenu-in-function-declaration nil))
-
- ((and (equal token 'T_STRING)
- (not imenu-in-function-name))
- (setq imenu-in-function-name (substring string (1-
token-start) (1- token-end)))
- (setq imenu-in-function-index token-start))))
-
- (t (cond
-
- ((and (not imenu-in-namespace-name)
- (equal token 'T_NAMESPACE))
- (setq imenu-in-namespace-name nil)
- (setq imenu-in-namespace-declaration t))
-
- ((and (not imenu-in-class-name)
- (or (equal token 'T_CLASS)
- (equal token 'T_INTERFACE)))
- (setq imenu-in-class-name nil)
- (setq imenu-in-class-declaration t))
-
- ((and (not imenu-in-function-name)
- (equal token 'T_FUNCTION))
- (setq imenu-in-function-name nil)
- (setq imenu-in-function-declaration t)))))
-
-
- ;; INDENTATION LOGIC
-
- ;; Keep track of round bracket level
- (when (string= token "(")
- (setq round-bracket-level (1+ round-bracket-level)))
- (when (string= token ")")
- (setq round-bracket-level (1- round-bracket-level))
- (when first-token-on-line
- (setq first-token-is-nesting-decrease t)))
-
- ;; Keep track of square bracket level
- (when (string= token "[")
- (setq square-bracket-level (1+ square-bracket-level)))
- (when (string= token "]")
- (setq square-bracket-level (1- square-bracket-level))
- (when first-token-on-line
- (setq first-token-is-nesting-decrease t)))
-
- ;; Handle INLINE_HTML blocks
- (when (equal token 'T_INLINE_HTML)
-
- ;; Flag whether inline-html is whitespace or not
- (setq inline-html-is-whitespace (string= (string-trim
(substring string (1- token-start) (1- token-end))) ""))
-
- (when first-token-on-line
- (setq first-token-is-inline-html t))
-
- (let ((inline-html-indents
(phps-mode-functions--get-inline-html-indentation (substring string (1-
token-start) (1- token-end)) inline-html-indent inline-html-tag-level
inline-html-curly-bracket-level inline-html-square-bracket-level
inline-html-round-bracket-level)))
-
- (phps-mode-debug-message
- (message "Received inline html indent: %s from inline
HTML: '%s'" inline-html-indents (substring string (1- token-start) (1-
token-end))))
-
- ;; Update indexes
- (setq inline-html-indent (nth 1 inline-html-indents))
- (setq inline-html-tag-level (nth 2 inline-html-indents))
- (setq inline-html-curly-bracket-level (nth 3
inline-html-indents))
- (setq inline-html-square-bracket-level (nth 4
inline-html-indents))
- (setq inline-html-round-bracket-level (nth 5
inline-html-indents))
-
- (phps-mode-debug-message
- (message "First token is inline html: %s"
first-token-is-inline-html))
-
- ;; Does inline html span several lines or starts a new
line?
- (when (or (> token-end-line-number token-start-line-number)
- first-token-is-inline-html)
-
- ;; Token does not only contain white-space?
- (unless inline-html-is-whitespace
- (let ((token-line-number-diff token-start-line-number))
- ;; Iterate lines here and add indents
- (dolist (item (nth 0 inline-html-indents))
- ;; Skip first line unless first token on line was
inline-html
- (when (or (not (= token-line-number-diff
token-start-line-number))
- first-token-is-inline-html)
- (puthash token-line-number-diff (list item 0)
line-indents)
- (phps-mode-debug-message
- (message "Putting indent at line %s to %s from
inline HTML" token-line-number-diff item)))
- (setq token-line-number-diff (1+
token-line-number-diff))))))))
-
- ;; Keep track of when we are inside a class definition
- (if in-class-declaration
- (if (string= token "{")
- (progn
- (setq in-class-declaration nil)
- (setq in-class-declaration-level 0)
-
- (unless class-declaration-started-this-line
- (setq column-level (1- column-level))
- (pop nesting-stack))
-
- (when first-token-on-line
- (setq first-token-is-nesting-decrease t))
-
- )
- (when first-token-on-line
- (setq in-class-declaration-level 1)))
-
- ;; If ::class is used as a magical class constant it should
not be considered start of a class declaration
- (when (and (equal token 'T_CLASS)
- (or (not previous-token)
- (not (equal previous-token
'T_PAAMAYIM_NEKUDOTAYIM))))
- (setq in-class-declaration t)
- (setq in-class-declaration-level 1)
- (setq class-declaration-started-this-line t)))
-
- ;; Keep track of curly bracket level
- (when (or (equal token 'T_CURLY_OPEN)
- (equal token 'T_DOLLAR_OPEN_CURLY_BRACES)
- (string= token "{"))
- (setq curly-bracket-level (1+ curly-bracket-level)))
- (when (string= token "}")
- (setq curly-bracket-level (1- curly-bracket-level))
-
- (when (and switch-curly-stack
- (= (1+ curly-bracket-level) (car
switch-curly-stack)))
-
- (phps-mode-debug-message
- (message "Ended switch curly stack at %s"
curly-bracket-level))
-
- (setq allow-custom-column-decrement t)
- (pop nesting-stack)
- (setq alternative-control-structure-level (1-
alternative-control-structure-level))
- (pop switch-curly-stack))
-
- (when first-token-on-line
- (setq first-token-is-nesting-decrease t)))
-
- ;; Keep track of ending alternative control structure level
- (when (or (equal token 'T_ENDIF)
- (equal token 'T_ENDWHILE)
- (equal token 'T_ENDFOR)
- (equal token 'T_ENDFOREACH)
- (equal token 'T_ENDSWITCH))
- (setq alternative-control-structure-level (1-
alternative-control-structure-level))
- ;; (message "Found ending alternative token %s %s" token
alternative-control-structure-level)
-
- (when (and (equal token 'T_ENDSWITCH)
- switch-case-alternative-stack)
-
- (phps-mode-debug-message
- (message "Ended alternative switch stack at %s"
alternative-control-structure-level))
-
- (pop switch-alternative-stack)
- (pop switch-case-alternative-stack)
- (setq allow-custom-column-decrement t)
- (pop nesting-stack)
- (setq alternative-control-structure-level (1-
alternative-control-structure-level)))
-
- (when first-token-on-line
- (setq first-token-is-nesting-decrease t)))
-
- ;; When we encounter a token except () after a
control-structure
- (when (and after-special-control-structure
- (= after-special-control-structure
round-bracket-level)
- (not (string= token ")"))
- (not (string= token "(")))
-
- ;; Handle the else if case
- (if (equal 'T_IF token)
- (setq after-special-control-structure-token token)
-
- ;; Is token not a curly bracket - because that is a
ordinary control structure syntax
- (if (string= token "{")
-
- ;; Save curly bracket level when switch starts
- (when (equal after-special-control-structure-token
'T_SWITCH)
-
- (phps-mode-debug-message
- (message "Started switch curly stack at %s"
curly-bracket-level))
-
- (push curly-bracket-level switch-curly-stack))
-
- ;; Is it the start of an alternative control structure?
- (if (string= token ":")
-
- (progn
-
- ;; Save alternative nesting level for switch
- (when (equal after-special-control-structure-token
'T_SWITCH)
-
- (phps-mode-debug-message
- (message "Started switch alternative stack at
%s" alternative-control-structure-level))
-
- (push alternative-control-structure-level
switch-alternative-stack))
-
- (setq alternative-control-structure-level (1+
alternative-control-structure-level))
-
- (phps-mode-debug-message
- (message "\nIncreasing
alternative-control-structure after %s %s to %s\n"
after-special-control-structure-token token
alternative-control-structure-level))
- )
-
- ;; Don't start inline control structures after a while
($condition); expression
- (unless (string= token ";")
- (phps-mode-debug-message
- (message "\nStarted inline control-structure after
%s at %s\n" after-special-control-structure-token token))
-
- (setq in-inline-control-structure t)
- (setq temp-pre-indent (1+ column-level)))))
-
- (setq after-special-control-structure nil)
- (setq after-special-control-structure-token nil)))
-
- ;; Support extra special control structures (CASE)
- (when (and after-extra-special-control-structure
- (string= token ":"))
- (setq alternative-control-structure-level (1+
alternative-control-structure-level))
- (when after-extra-special-control-structure-first-on-line
- (setq first-token-is-nesting-decrease t))
- (setq after-extra-special-control-structure nil))
-
- ;; Keep track of concatenation
- (if in-concatenation
- (when (or (string= token ";")
- (and (string= token ")")
- (< round-bracket-level (car
in-concatenation-round-bracket-level)))
- (and (string= token ",")
- (= round-bracket-level (car
in-concatenation-round-bracket-level))
- (= square-bracket-level (car
in-concatenation-square-bracket-level)))
- (and (string= token"]")
- (< square-bracket-level (car
in-concatenation-square-bracket-level))))
- (phps-mode-debug-message "Ended concatenation")
- (pop in-concatenation-round-bracket-level)
- (pop in-concatenation-square-bracket-level)
- (unless in-concatenation-round-bracket-level
- (setq in-concatenation nil))
- (setq in-concatenation-level (1-
in-concatenation-level)))
- (when (and (> next-token-start-line-number
token-end-line-number)
- (or (string= token ".")
- (string= next-token ".")))
- (phps-mode-debug-message "Started concatenation")
- (setq in-concatenation t)
- (push round-bracket-level
in-concatenation-round-bracket-level)
- (push square-bracket-level
in-concatenation-square-bracket-level)
- (setq in-concatenation-level (1+ in-concatenation-level))))
-
- ;; Did we reach a semicolon inside a inline block? Close the
inline block
- (when (and in-inline-control-structure
- (string= token ";")
- (not special-control-structure-started-this-line))
- (setq in-inline-control-structure nil))
-
- ;; Did we encounter a token that supports alternative and
inline control structures?
- (when (or (equal token 'T_IF)
- (equal token 'T_WHILE)
- (equal token 'T_FOR)
- (equal token 'T_FOREACH)
- (equal token 'T_SWITCH)
- (equal token 'T_ELSE)
- (equal token 'T_ELSEIF)
- (equal token 'T_DEFAULT))
- (setq after-special-control-structure round-bracket-level)
- (setq after-special-control-structure-token token)
- (setq nesting-key token)
- (setq special-control-structure-started-this-line t)
-
- ;; ELSE and ELSEIF after a IF, ELSE, ELESIF
- ;; and DEFAULT after a CASE
- ;; should decrease alternative control structure level
- (when (and nesting-stack
- (string= (car (cdr (cdr (cdr (car
nesting-stack))))) ":")
- (or
- (and (or (equal token 'T_ELSE)
- (equal token 'T_ELSEIF))
- (or (equal (car (cdr (cdr (car
nesting-stack)))) 'T_IF)
- (equal (car (cdr (cdr (car
nesting-stack)))) 'T_ELSEIF)
- (equal (car (cdr (cdr (car
nesting-stack)))) 'T_ELSE)))
- (and (equal token 'T_DEFAULT)
- (equal (car (cdr (cdr (car
nesting-stack)))) 'T_CASE))))
- (setq alternative-control-structure-level (1-
alternative-control-structure-level))
-
- (when first-token-on-line
- (setq first-token-is-nesting-decrease t))
-
- (phps-mode-debug-message
- (message "\nDecreasing alternative control structure
nesting at %s to %s\n" token alternative-control-structure-level)))
-
- )
-
- ;; Keep track of assignments
- (when in-assignment
- (when (or (string= token ";")
- (and (string= token ")")
- (or (< round-bracket-level (car
in-assignment-round-bracket-level))
- (and
- (= round-bracket-level (car
in-assignment-round-bracket-level))
- (= square-bracket-level (car
in-assignment-square-bracket-level))
- (or (string= next-token ")")
- (string= next-token "]")))))
- (and (string= token ",")
- (= round-bracket-level (car
in-assignment-round-bracket-level))
- (= square-bracket-level (car
in-assignment-square-bracket-level)))
- (and (string= token "]")
- (or (< square-bracket-level (car
in-assignment-square-bracket-level))
- (and
- (= square-bracket-level (car
in-assignment-square-bracket-level))
- (= round-bracket-level (car
in-assignment-round-bracket-level))
- (or (string= next-token "]")
- (string= next-token ")")))))
- (and (equal token 'T_FUNCTION)
- (= round-bracket-level (car
in-assignment-round-bracket-level))))
-
- ;; NOTE Ending an assignment because of a T_FUNCTION token
is to support PSR-2 Closures
-
- (phps-mode-debug-message
- (message "Ended assignment %s at %s %s"
in-assignment-level token next-token))
- (pop in-assignment-square-bracket-level)
- (pop in-assignment-round-bracket-level)
- (unless in-assignment-round-bracket-level
- (setq in-assignment nil))
- (setq in-assignment-level (1- in-assignment-level))
-
- ;; Did we end two assignment at once?
- (when (and
- in-assignment-round-bracket-level
- in-assignment-square-bracket-level
- (= round-bracket-level (car
in-assignment-round-bracket-level))
- (= square-bracket-level (car
in-assignment-square-bracket-level))
- (or (string= next-token ")")
- (string= next-token "]")))
- (phps-mode-debug-message
- (message "Ended another assignment %s at %s %s"
in-assignment-level token next-token))
- (pop in-assignment-square-bracket-level)
- (pop in-assignment-round-bracket-level)
- (unless in-assignment-round-bracket-level
- (setq in-assignment nil))
- (setq in-assignment-level (1- in-assignment-level)))
-
- ))
-
- (when (and (not after-special-control-structure)
- (or (string= token "=")
- (equal token 'T_DOUBLE_ARROW)
- (equal token 'T_CONCAT_EQUAL)
- (equal token 'T_POW_EQUAL)
- (equal token 'T_DIV_EQUAL)
- (equal token 'T_PLUS_EQUAL)
- (equal token 'T_MINUS_EQUAL)
- (equal token 'T_MUL_EQUAL)
- (equal token 'T_MOD_EQUAL)
- (equal token 'T_SL_EQUAL)
- (equal token 'T_SR_EQUAL)
- (equal token 'T_AND_EQUAL)
- (equal token 'T_OR_EQUAL)
- (equal token 'T_XOR_EQUAL)
- (equal token 'T_COALESCE_EQUAL)))
- (phps-mode-debug-message "Started assignment")
- (setq in-assignment t)
- (push round-bracket-level in-assignment-round-bracket-level)
- (push square-bracket-level
in-assignment-square-bracket-level)
- (setq in-assignment-level (1+ in-assignment-level)))
-
- ;; Second token after a object-operator
- (when (and
- in-object-operator
- in-object-operator-round-bracket-level
- in-object-operator-square-bracket-level
- (<= round-bracket-level (car
in-object-operator-round-bracket-level))
- (<= square-bracket-level (car
in-object-operator-square-bracket-level))
- (not (or
- (equal next-token 'T_OBJECT_OPERATOR)
- (equal next-token 'T_PAAMAYIM_NEKUDOTAYIM))))
- (phps-mode-debug-message
- (message "Ended object-operator at %s %s at level %s"
token next-token in-object-operator-level))
- (pop in-object-operator-round-bracket-level)
- (pop in-object-operator-square-bracket-level)
- (setq in-object-operator-level (1- in-object-operator-level))
- (when (= in-object-operator-level 0)
- (setq in-object-operator nil)))
-
- ;; First token after a object-operator
- (when after-object-operator
- (when (or (equal next-token 'T_STRING)
- (string= next-token "("))
- (progn
- (phps-mode-debug-message
- (message "Started object-operator at %s %s on level
%s" token next-token in-object-operator-level))
- (push round-bracket-level
in-object-operator-round-bracket-level)
- (push square-bracket-level
in-object-operator-square-bracket-level)
- (setq in-object-operator t)
- (setq in-object-operator-level (1+
in-object-operator-level))))
- (setq after-object-operator nil))
-
- ;; Starting object-operator?
- (when (and (or (equal token 'T_OBJECT_OPERATOR)
- (equal token 'T_PAAMAYIM_NEKUDOTAYIM))
- (equal next-token 'T_STRING))
- (phps-mode-debug-message
- (message "After object-operator at %s level %s" token
in-object-operator-level))
- (setq after-object-operator t))
-
- ;; Keep track of return expressions
- (when in-return
- (when (and (string= token ";")
- (= curly-bracket-level (car
in-return-curly-bracket-level)))
-
- (phps-mode-debug-message (message "Ended return at %s"
token))
- (pop in-return-curly-bracket-level)
- (unless in-return-curly-bracket-level
- (setq in-return nil))
- (setq in-return-level (1- in-return-level))))
- (when (equal token 'T_RETURN)
- (phps-mode-debug-message "Started return")
- (setq in-return t)
- (push curly-bracket-level in-return-curly-bracket-level)
- (setq in-return-level (1+ in-return-level)))
-
- ;; Did we encounter a token that supports extra special
alternative control structures?
- (when (equal token 'T_CASE)
- (setq after-extra-special-control-structure t)
- (setq nesting-key token)
- (setq after-extra-special-control-structure-first-on-line
first-token-on-line)
-
- (when (and switch-case-alternative-stack
- (= (1- alternative-control-structure-level) (car
switch-case-alternative-stack)))
-
- (phps-mode-debug-message
- (message "Found CASE %s vs %s" (1-
alternative-control-structure-level) (car switch-case-alternative-stack)))
-
- (setq alternative-control-structure-level (1-
alternative-control-structure-level))
- (when first-token-on-line
- (setq first-token-is-nesting-decrease t))
- (pop switch-case-alternative-stack))
-
- (push alternative-control-structure-level
switch-case-alternative-stack)))
-
- ;; Do we have one token look-ahead?
- (when token
-
- (phps-mode-debug-message (message "Processing token: %s"
token))
-
- ;; Calculate nesting
- (setq nesting-end (+ round-bracket-level square-bracket-level
curly-bracket-level alternative-control-structure-level in-assignment-level
in-class-declaration-level in-concatenation-level in-return-level
in-object-operator-level))
-
- ;; Keep track of whether we are inside a HEREDOC or NOWDOC
- (when (equal token 'T_START_HEREDOC)
- (setq in-heredoc t)
- (setq in-heredoc-started-this-line t))
- (when (equal token 'T_END_HEREDOC)
- (setq in-heredoc nil)
- (setq in-heredoc-ended-this-line t))
-
- ;; Has nesting increased?
- (when (and nesting-stack
- (<= nesting-end (car (car nesting-stack))))
- (let ((nesting-decrement 0))
-
- ;; Handle case were nesting has decreased less than next
as well
- (while (and nesting-stack
- (<= nesting-end (car (car nesting-stack))))
- (phps-mode-debug-message
- (message "\nPopping %s from nesting-stack since %s is
lesser or equal to %s, next value is: %s\n" (car nesting-stack) nesting-end
(car (car nesting-stack)) (nth 1 nesting-stack)))
- (pop nesting-stack)
- (setq nesting-decrement (1+ nesting-decrement)))
-
- (if first-token-is-nesting-decrease
-
- (progn
- ;; Decrement column
- (if allow-custom-column-decrement
- (progn
- (phps-mode-debug-message
- (message "Doing custom decrement 1 from %s
to %s" column-level (- column-level (- nesting-start nesting-end))))
- (setq column-level (- column-level (-
nesting-start nesting-end)))
- (setq allow-custom-column-decrement nil))
- (phps-mode-debug-message
- (message "Doing regular decrement 1 from %s to
%s" column-level (1- column-level)))
- (setq column-level (- column-level
nesting-decrement)))
-
- ;; Prevent negative column-values
- (when (< column-level 0)
- (setq column-level 0)))
-
- (unless temp-post-indent
- (phps-mode-debug-message
- (message "Temporary setting post indent %s"
column-level))
- (setq temp-post-indent column-level))
-
- ;; Decrement column
- (if allow-custom-column-decrement
- (progn
- (phps-mode-debug-message
- (message "Doing custom decrement 2 from %s to
%s" column-level (- column-level (- nesting-start nesting-end))))
- (setq temp-post-indent (- temp-post-indent (-
nesting-start nesting-end)))
- (setq allow-custom-column-decrement nil))
- (setq temp-post-indent (- temp-post-indent
nesting-decrement)))
-
- ;; Prevent negative column-values
- (when (< temp-post-indent 0)
- (setq temp-post-indent 0))
-
- )))
-
- ;; Are we on a new line or is it the last token of the buffer?
- (if (> next-token-start-line-number token-start-line-number)
- (progn
-
-
- ;; ;; Start indentation might differ from ending
indentation in cases like } else {
- (setq column-level-start column-level)
-
- ;; Support temporarily pre-indent
- (when temp-pre-indent
- (setq column-level-start temp-pre-indent)
- (setq temp-pre-indent nil))
-
- ;; HEREDOC lines should have zero indent
- (when (or (and in-heredoc
- (not in-heredoc-started-this-line))
- in-heredoc-ended-this-line)
- (setq column-level-start 0))
-
- ;; Inline HTML should have zero indent
- (when (and first-token-is-inline-html
- (not inline-html-is-whitespace))
- (phps-mode-debug-message
- (message "Setting column-level to inline HTML indent:
%s" inline-html-indent-start))
- (setq column-level-start inline-html-indent-start))
-
- ;; Save line indent
- (phps-mode-debug-message
- (message "Process line ending. nesting: %s-%s,
line-number: %s-%s, indent: %s.%s, token: %s" nesting-start nesting-end
token-start-line-number token-end-line-number column-level-start tuning-level
token))
-
- (when (and (> token-start-line-number 0)
- (or
- (not first-token-is-inline-html)
- inline-html-is-whitespace))
- (phps-mode-debug-message
- (message "Putting indent on line %s to %s at #C"
token-start-line-number column-level-start))
- (puthash token-start-line-number `(,column-level-start
,tuning-level) line-indents))
-
- ;; Support trailing indent decrements
- (when temp-post-indent
- (setq column-level temp-post-indent)
- (setq temp-post-indent nil))
-
- ;; Increase indentation
- (when (and (> nesting-end 0)
- (or (not nesting-stack)
- (> nesting-end (car (cdr (car
nesting-stack))))))
- (let ((nesting-stack-end 0))
- (when nesting-stack
- (setq nesting-stack-end (car (cdr (car
nesting-stack)))))
-
- (if allow-custom-column-increment
- (progn
- (setq column-level (+ column-level (-
nesting-end nesting-start)))
- (setq allow-custom-column-increment nil))
- (setq column-level (1+ column-level)))
-
- (phps-mode-debug-message
- (message "\nPushing (%s %s %s %s) to nesting-stack
since %s is greater than %s or stack is empty\n" nesting-start nesting-end
nesting-key token nesting-end (car (cdr (car nesting-stack))))
- )
- (push `(,nesting-stack-end ,nesting-end ,nesting-key
,token) nesting-stack)))
-
-
- ;; Does token span over several lines and is it not a
INLINE_HTML token?
- (when (and (> token-end-line-number
token-start-line-number)
- (not (equal token 'T_INLINE_HTML)))
- (let ((column-level-end column-level))
-
- ;; HEREDOC lines should have zero indent
- (when (or (and in-heredoc
- (not in-heredoc-started-this-line))
- in-heredoc-ended-this-line)
- (setq column-level-end 0))
-
- ;; (message "Token %s starts at %s and ends at %s
indent %s %s" next-token token-start-line-number token-end-line-number
column-level-end tuning-level)
-
- ;; Indent doc-comment lines with 1 tuning
- (when (equal token 'T_DOC_COMMENT)
- (setq tuning-level 1))
-
- (let ((token-line-number-diff (1- (-
token-end-line-number token-start-line-number))))
- (while (>= token-line-number-diff 0)
- (phps-mode-debug-message
- (message "Putting indent on line %s to %s at
#A" (- token-end-line-number token-line-number-diff) column-level-end))
- (puthash (- token-end-line-number
token-line-number-diff) `(,column-level-end ,tuning-level) line-indents)
- ;; (message "Saved line %s indent %s %s" (-
token-end-line-number token-line-number-diff) column-level tuning-level)
- (setq token-line-number-diff (1-
token-line-number-diff))))
-
- ;; Rest tuning-level used for comments
- (setq tuning-level 0)))
-
- ;; Indent token-less lines here in between last tokens
if distance is more than 1 line
- (when (and (> next-token-start-line-number (1+
token-end-line-number))
- (not (equal token 'T_CLOSE_TAG)))
-
- (phps-mode-debug-message
- (message "\nDetected token-less lines between %s and
%s, should have indent: %s\n" token-end-line-number
next-token-start-line-number column-level))
-
- (let ((token-line-number-diff (1- (-
next-token-start-line-number token-end-line-number))))
- (while (> token-line-number-diff 0)
- (phps-mode-debug-message
- (message "Putting indent at line %s indent %s at
#B" (- next-token-start-line-number token-line-number-diff) column-level))
- (puthash (- next-token-start-line-number
token-line-number-diff) `(,column-level ,tuning-level) line-indents)
- (setq token-line-number-diff (1-
token-line-number-diff)))))
-
-
- ;; Calculate indentation level at start of line
- (setq nesting-start (+ round-bracket-level
square-bracket-level curly-bracket-level alternative-control-structure-level
in-assignment-level in-class-declaration-level in-concatenation-level
in-return-level in-object-operator-level))
-
- ;; Set initial values for tracking first token
- (when (> token-start-line-number last-line-number)
- (setq inline-html-indent-start inline-html-indent)
- (setq first-token-on-line t)
- (setq first-token-is-nesting-decrease nil)
- (setq first-token-is-inline-html nil)
- (setq in-class-declaration-level 0)
- (setq class-declaration-started-this-line nil)
- (setq in-heredoc-started-this-line nil)
- (setq special-control-structure-started-this-line nil)
-
- ;; When line ends with multi-line inline-html flag
first token as inline-html
- (when (and
- (equal token 'T_INLINE_HTML)
- (not inline-html-is-whitespace)
- (> token-end-line-number
token-start-line-number))
-
- (setq inline-html-is-whitespace
- (not (null
- (string-match "[\n\C-m][ \t]+$"
(substring string (1- token-start) (1- token-end))))))
- (phps-mode-debug-message
- (message "Trailing inline html line is whitespace:
%s" inline-html-is-whitespace))
- (phps-mode-debug-message
- (message "Setting first-token-is-inline-html to
true since last token on line is inline-html and spans several lines"))
- (setq first-token-is-inline-html t))))
-
- ;; Current token is not first if it's not <?php or <?=
- (unless (or (equal token 'T_OPEN_TAG)
- (equal token 'T_OPEN_TAG_WITH_ECHO))
- (setq first-token-on-line nil))
-
- (when (> token-end-line-number token-start-line-number)
- ;; (message "Token not first on line %s starts at %s and
ends at %s" token token-start-line-number token-end-line-number)
- (when (equal token 'T_DOC_COMMENT)
- (setq tuning-level 1))
-
- (let ((token-line-number-diff (1- (- token-end-line-number
token-start-line-number))))
- (while (>= token-line-number-diff 0)
- (phps-mode-debug-message
- (message "Putting indent on line %s to %s at #E" (-
token-end-line-number token-line-number-diff) column-level))
- (puthash (- token-end-line-number
token-line-number-diff) `(,column-level ,tuning-level) line-indents)
- (setq token-line-number-diff (1-
token-line-number-diff))))
- (setq tuning-level 0))))
-
- ;; Update current token
- (setq previous-token token)
- (setq token next-token)
- (setq token-start next-token-start)
- (setq token-end next-token-end)
- (setq token-start-line-number next-token-start-line-number)
- (setq token-end-line-number next-token-end-line-number)
- (setq token-number (1+ token-number))))
- (list (nreverse imenu-index) line-indents)))
- (list nil nil)))
-
-;; TODO newline with electric mode not working
-(defun phps-mode-functions-indent-line ()
- "Indent line."
- (phps-mode-runtime-debug-message "Indent line")
- (phps-mode-debug-message (message "Indent line"))
- (phps-mode-functions-process-current-buffer)
- (if phps-mode-functions-lines-indent
- (let ((line-number (line-number-at-pos (point))))
- (phps-mode-runtime-debug-message "Found lines indent index,
indenting..")
- (phps-mode-debug-message (message "Found lines indent index,
indenting.."))
- (let ((indent (gethash line-number phps-mode-functions-lines-indent)))
- (if indent
- (progn
- (phps-mode-runtime-debug-message (format "Found indent for
line number %s = %s" line-number indent))
- (let ((indent-sum (+ (* (car indent) tab-width) (car (cdr
indent))))
- (old-indentation (current-indentation))
- (line-start (line-beginning-position)))
-
- (unless old-indentation
- (setq old-indentation 0))
-
- ;; Only continue if current indentation is wrong
- (if (not (equal indent-sum old-indentation))
- (progn
- (phps-mode-runtime-debug-message (format "Indenting
line since it's not already indented correctly %s vs %s" old-indentation
indent-sum))
-
- (setq-local phps-mode-functions-allow-after-change nil)
- (indent-line-to indent-sum)
- (setq-local phps-mode-functions-allow-after-change t)
-
- (let ((indent-diff (- (current-indentation)
old-indentation)))
-
- (phps-mode-runtime-debug-message (format "Moving
indexes by %s points from %s" indent-diff line-start))
- (phps-mode-runtime-debug-message (format "Lexer
tokens before move: %s" phps-mode-lexer-tokens))
-
- ;; When indent is changed the trailing tokens and
states just need to adjust their positions, this will improve speed of
indent-region a lot
- (phps-mode-lexer-move-tokens line-start indent-diff)
- (phps-mode-lexer-move-states line-start indent-diff)
- (phps-mode-functions-move-imenu-index line-start
indent-diff)
-
- (phps-mode-runtime-debug-message (format "Lexer
tokens after move: %s" phps-mode-lexer-tokens))
- (phps-mode-debug-message
- (message "Lexer tokens after move: %s"
phps-mode-lexer-tokens)
- (message "Lexer states after move: %s"
phps-mode-lexer-states))
-
- ;; Reset change flag
- (phps-mode-functions--reset-changes)
- (phps-mode-functions--cancel-idle-timer)
-
- ;; Update last buffer states
- (setq-local phps-mode-lexer-buffer-length (1-
(point-max)))
- (setq-local phps-mode-lexer-buffer-contents
(buffer-substring-no-properties (point-min) (point-max)))
-
- (phps-mode-runtime-debug-message (format "buffer
contents:\n%s" (buffer-substring-no-properties (point-min) (point-max))))
- ))
- (phps-mode-runtime-debug-message "Skipping indentation of
line since it's already indented correctly"))))
- (phps-mode-runtime-debug-message (format "Found no indent for line
number %s" line-number)))))
- (phps-mode-runtime-debug-message "Did not find lines indent index,
skipping indenting..")
- (phps-mode-debug-message "Did not find lines indent index, skipping
indenting..")
- (message "Did not find lines indent index, skipping indenting..")))
-
-(defun phps-mode-functions--reset-changes ()
- "Reset change stack."
- (setq-local phps-mode-functions-buffer-changes nil))
-
-(defun phps-mode-functions--get-changes ()
- "Get change stack."
- phps-mode-functions-buffer-changes)
-
-(defun phps-mode-functions--cancel-idle-timer ()
- "Cancel idle timer."
- (phps-mode-runtime-debug-message "Cancelled idle timer")
- (phps-mode-debug-message (message "Cancelled idle timer"))
- (when phps-mode-functions-idle-timer
- (cancel-timer phps-mode-functions-idle-timer)
- (setq-local phps-mode-functions-idle-timer nil)))
-
-(defun phps-mode-functions--start-idle-timer ()
- "Start idle timer."
- (phps-mode-runtime-debug-message "Enqueued idle timer")
- (phps-mode-debug-message (message "Enqueued idle timer"))
- (when (boundp 'phps-mode-idle-interval)
- (setq-local phps-mode-functions-idle-timer (run-with-idle-timer
phps-mode-idle-interval nil #'phps-mode-lexer-run-incremental
(current-buffer)))))
-
-(defun phps-mode-functions-after-change (start stop length)
- "Track buffer change from START to STOP with LENGTH."
- (phps-mode-runtime-debug-message
- (format "After change %s - %s, length: %s" start stop length))
- (phps-mode-debug-message
- (message "After change %s - %s, length: %s" start stop length))
-
- (if phps-mode-functions-allow-after-change
- (progn
- (phps-mode-debug-message (message "After change registration is
enabled"))
- (phps-mode-runtime-debug-message "After change registration is
enabled")
-
- ;; If we haven't scheduled incremental lexer before - do it
- (when (and (boundp 'phps-mode-idle-interval)
- phps-mode-idle-interval
- (not phps-mode-functions-idle-timer))
-
- ;; Reset imenu
- (when (and (boundp 'imenu--index-alist)
- imenu--index-alist)
- (setq-local imenu--index-alist nil)
- (phps-mode-debug-message (message "Cleared Imenu index")))
-
- (phps-mode-functions--start-idle-timer))
-
- ;; Save change in changes stack
- (push `(,start ,stop ,length ,(point-max)
,(buffer-substring-no-properties (point-min) (point-max)))
phps-mode-functions-buffer-changes))
- (phps-mode-debug-message (message "After change registration is disabled"))
- (phps-mode-runtime-debug-message "After change registration is disabled")))
-
-(defun phps-mode-functions-imenu-create-index ()
- "Get Imenu for current buffer."
- (phps-mode-functions-process-current-buffer)
- phps-mode-functions-imenu)
-
-(defun phps-mode-functions-comment-region (beg end &optional _arg)
- "Comment region from BEG to END with optional ARG."
- ;; Iterate tokens from beginning to end and comment out all PHP code
- (when-let ((tokens phps-mode-lexer-tokens))
- (let ((token-comment-start nil)
- (token-comment-end nil)
- (in-token-comment nil)
- (offset 0))
- (dolist (token tokens)
- (let ((token-label (car token))
- (token-start (car (cdr token)))
- (token-end (cdr (cdr token))))
- (when (and (>= token-start beg)
- (<= token-end end))
-
- (if in-token-comment
- (cond
- ((or
- (equal token-label 'T_COMMENT)
- (equal token-label 'T_DOC_COMMENT)
- (equal token-label 'T_CLOSE_TAG))
- (setq in-token-comment nil))
- (t (setq token-comment-end token-end)))
-
- ;; When we have a start and end of comment, comment it out
- (when (and
- token-comment-start
- token-comment-end)
- (let ((offset-comment-start (+ token-comment-start offset))
- (offset-comment-end))
- (save-excursion
- (goto-char offset-comment-start)
- (insert "/* "))
- (setq offset (+ offset 3))
- (setq offset-comment-end (+ token-comment-end offset))
- (save-excursion
- (goto-char offset-comment-end)
- (insert " */"))
- (setq offset (+ offset 3))
- (phps-mode-debug-message
- (message "Commented out %s-%s" offset-comment-start
offset-comment-end)))
- (setq token-comment-start nil)
- (setq token-comment-end nil))
-
- (cond
- ((or
- (equal token-label 'T_INLINE_HTML)
- (equal token-label 'T_OPEN_TAG)
- (equal token-label 'T_OPEN_TAG_WITH_ECHO)))
- (t
- (phps-mode-debug-message
- (message "Comment should start at %s %s" token-label
token-start))
- (setq token-comment-start token-start)
- (setq in-token-comment t)))))))
-
- ;; When we have a start and end of comment, comment it out
- (when (and
- in-token-comment
- token-comment-start
- token-comment-end)
- (let ((offset-comment-start (+ token-comment-start offset))
- (offset-comment-end))
- (save-excursion
- (goto-char offset-comment-start)
- (insert "/* "))
- (setq offset (+ offset 3))
- (setq offset-comment-end (+ token-comment-end offset))
- (save-excursion
- (goto-char offset-comment-end)
- (insert " */"))
- (setq offset (+ offset 3))
- (phps-mode-debug-message
- (message "Commented out trailing %s-%s" offset-comment-start
offset-comment-end)))
- (setq token-comment-start nil)
- (setq token-comment-end nil)))))
-
-(defun phps-mode-functions-uncomment-region (beg end &optional _arg)
- "Un-comment region from BEG to END with optional ARG."
- ;; Iterate tokens from beginning to end and uncomment out all commented PHP
code
- (when-let ((tokens phps-mode-lexer-tokens))
- (let ((offset 0))
- (dolist (token tokens)
- (let ((token-label (car token))
- (token-start (car (cdr token)))
- (token-end (cdr (cdr token))))
- (when (and (>= token-start beg)
- (<= token-end end))
- (when (or
- (equal token-label 'T_COMMENT)
- (equal token-label 'T_DOC_COMMENT))
-
- (phps-mode-debug-message
- (message "Un-comment comment at %s %s" token-label token-start
token-end))
-
- (let ((offset-comment-start (+ token-start offset))
- (offset-comment-end))
-
- (if (equal token-label 'T_DOC_COMMENT)
- (progn
- (phps-mode-debug-message
- (message "Un-comment doc comment at %s-%s" token-start
token-end))
- (save-excursion
- (goto-char offset-comment-start)
- (delete-char 4))
- (setq offset (- offset 4))
- (setq offset-comment-end (+ token-end offset))
- (save-excursion
- (goto-char offset-comment-end)
- (delete-char -4))
- (setq offset (- offset 4)))
-
- (phps-mode-debug-message
- (message "Un-comment comment starting at %s" token-start))
-
- (cond
-
- ((string=
- (buffer-substring-no-properties offset-comment-start (+
offset-comment-start 1))
- "#")
- (save-excursion
- (goto-char offset-comment-start)
- (delete-char 1))
- (setq offset (- offset 1)))
- ((string=
- (buffer-substring-no-properties offset-comment-start (+
offset-comment-start 2))
- "//")
- (save-excursion
- (goto-char offset-comment-start)
- (delete-char 2))
- (setq offset (- offset 2)))
- (t
- (save-excursion
- (goto-char offset-comment-start)
- (delete-char 3))
- (setq offset (- offset 3))))
-
-
- (setq offset-comment-end (+ token-end offset))
- (if (string=
- (buffer-substring-no-properties (- offset-comment-end
3) offset-comment-end)
- " */")
- (progn
- (phps-mode-debug-message
- (message "Un-comment comment ending at %s" token-end))
- (save-excursion
- (goto-char offset-comment-end)
- (delete-char -3))
- (setq offset (- offset 3)))
- (phps-mode-debug-message
- (message "Do not un-comment comment ending at %s"
token-end))))))))))))
-
-(provide 'phps-mode-functions)
-
-;;; phps-mode-functions.el ends here
diff --git a/phps-mode.el b/phps-mode.el
index 943ad11..9ce64e8 100644
--- a/phps-mode.el
+++ b/phps-mode.el
@@ -5,8 +5,8 @@
;; Author: Christian Johansson <address@hidden>
;; Maintainer: Christian Johansson <address@hidden>
;; Created: 3 Mar 2018
-;; Modified: 26 Sep 2019
-;; Version: 0.3.2
+;; Modified: 30 Sep 2019
+;; Version: 0.3.4
;; Keywords: tools, convenience
;; URL: https://github.com/cjohansson/emacs-phps-mode
@@ -30,7 +30,13 @@
;;; Commentary:
-;; A major-mode that uses original PHP lexer tokens for syntax coloring and
indentation making it easier to spot errors in syntax. Also includes full
support for PSR-1 and PSR-2 indentation, imenu. Improved syntax table in
comparison with old PHP major-mode.
+;; A major-mode that uses original PHP lexer tokens for syntax coloring and
indentation
+;; making it easier to spot errors in syntax.
+;;
+;; Also includes full support for PSR-1 and PSR-2 indentation and imenu.
+;; Improved syntax table in comparison with old PHP major-mode.
+;;
+;; For flycheck support run `(phps-mode-flycheck-setup)'.
;; Please see README.md from the same repository for extended documentation.
@@ -40,29 +46,19 @@
;; NOTE use wisent-parse-toggle-verbose-flag and (semantic-debug) to debug
parsing
+(require 'phps-mode-analyzer)
(require 'phps-mode-flymake)
-(require 'phps-mode-functions)
-(require 'phps-mode-lexer)
(require 'phps-mode-semantic)
(require 'phps-mode-syntax-table)
(require 'phps-mode-tags)
(require 'semantic)
-(defvar phps-mode-use-electric-pair-mode t
- "Whether or not we want to use electric pair mode.")
-
-(defvar phps-mode-use-transient-mark-mode t
- "Whether or not we want to use transient mark mode.")
-
(defvar phps-mode-use-psr-2 t
"Whether to use PSR-2 guidelines for white-space or not.")
(defvar phps-mode-idle-interval 1
"Idle seconds before running the incremental lexer.")
-(defvar phps-mode-flycheck-applied nil
- "Boolean flag whether flycheck configuration has been applied or not.")
-
(defvar phps-mode-inline-mmm-submode nil
"Symbol declaring what mmm-mode to use as submode in inline areas.")
@@ -79,38 +75,48 @@
(insert message)
(insert "\n"))))))
-(defun phps-mode-get-syntax-table ()
- "Get syntax table."
- phps-mode-syntax-table)
-
(defvar phps-mode-map
(let ((map (make-sparse-keymap)))
- (define-key map (kbd "C-c /") #'comment-region)
- (define-key map (kbd "C-c DEL") #'uncomment-region)
(define-key map (kbd "C-c C-r") #'phps-mode-lexer-run)
(define-key map (kbd "C-c C-f") #'phps-mode-format-buffer)
- (define-key map (kbd "C-c C-p")
#'phps-mode-functions-process-current-buffer)
map)
"Keymap for `phps-mode'.")
;;;###autoload
+(defun phps-mode-flycheck-setup ()
+ "Setup `flycheck' for `phps-mode'."
+ ;; Add support for flycheck PHP checkers: PHP, PHPMD and PHPCS here
+ ;; Do it only if flycheck is available
+ (when (fboundp 'flycheck-add-mode)
+ (flycheck-add-mode 'php 'phps-mode)
+ (flycheck-add-mode 'php-phpmd 'phps-mode)
+ (flycheck-add-mode 'php-phpcs 'phps-mode)))
+
+;;;###autoload
(defun phps-mode-format-buffer ()
"Format current buffer according to PHPs mode."
(interactive)
- (let ((old-buffer-contents (buffer-substring-no-properties (point-min)
(point-max)))
- (old-buffer (current-buffer))
- (temp-buffer (generate-new-buffer "*PHPs Formatting*"))
- (new-buffer-contents ""))
- (save-excursion
- (switch-to-buffer temp-buffer)
- (insert old-buffer-contents)
- (phps-mode)
- (indent-region (point-min) (point-max))
- (setq new-buffer-contents (buffer-substring-no-properties (point-min)
(point-max)))
- (kill-buffer)
- (switch-to-buffer old-buffer)
- (delete-region (point-min) (point-max))
- (insert new-buffer-contents))))
+ (if (derived-mode-p 'phps-mode)
+ (progn
+ (when phps-mode-use-psr-2
+ (untabify (point-min) (point-max)))
+ (indent-region (point-min) (point-max)))
+ (let ((old-buffer-contents (buffer-substring-no-properties (point-min)
(point-max)))
+ (old-buffer (current-buffer))
+ (temp-buffer (generate-new-buffer "*PHPs Formatting*"))
+ (new-buffer-contents ""))
+ (save-excursion
+ (switch-to-buffer temp-buffer)
+ (insert old-buffer-contents)
+ (phps-mode)
+ (when phps-mode-use-psr-2
+ (untabify (point-min) (point-max)))
+ (indent-region (point-min) (point-max))
+ (setq new-buffer-contents (buffer-substring-no-properties (point-min)
(point-max)))
+ (kill-buffer)
+ (switch-to-buffer old-buffer)
+ (delete-region (point-min) (point-max))
+ (insert new-buffer-contents)))))
(define-derived-mode phps-mode prog-mode "PHPs"
"Major mode for PHP with Semantic integration."
@@ -118,20 +124,6 @@
;; Skip comments when navigating via syntax-table
(setq-local parse-sexp-ignore-comments t)
- ;; Key-map
- (use-local-map phps-mode-map)
-
- ;; Syntax table
- (set-syntax-table phps-mode-syntax-table)
-
- (when phps-mode-use-transient-mark-mode
- ;; NOTE: These are required for wrapping region functionality
- (transient-mark-mode))
-
- ;; TODO Add this as a menu setting similar to php-mode?
- (when phps-mode-use-electric-pair-mode
- (electric-pair-local-mode))
-
;; Font lock
;; This makes it possible to have full control over syntax coloring from the
lexer
(setq-local font-lock-keywords-only nil)
@@ -140,16 +132,6 @@
;; Flymake TODO
;; (phps-mode-flymake-init)
- ;; Flycheck
- ;; Add support for flycheck PHP checkers: PHP, PHPMD and PHPCS here
- ;; Do it once but only if flycheck is available
- (when (and (fboundp 'flycheck-add-mode)
- (not phps-mode-flycheck-applied))
- (flycheck-add-mode 'php 'phps-mode)
- (flycheck-add-mode 'php-phpmd 'phps-mode)
- (flycheck-add-mode 'php-phpcs 'phps-mode)
- (setq phps-mode-flycheck-applied t))
-
;; Custom indentation
;; Indent-region will call this on each line of selected region
(setq-local indent-line-function #'phps-mode-functions-indent-line)
diff --git a/phps-mode-test-functions.el b/test/phps-mode-test-functions.el
similarity index 96%
rename from phps-mode-test-functions.el
rename to test/phps-mode-test-functions.el
index b30eb8d..53d2c83 100644
--- a/phps-mode-test-functions.el
+++ b/test/phps-mode-test-functions.el
@@ -27,8 +27,6 @@
(require 'ert)
(require 'phps-mode)
-(require 'phps-mode-functions)
-(require 'phps-mode-lexer)
(require 'phps-mode-test)
(defun phps-mode-test-functions-move-lines-indent ()
@@ -851,6 +849,13 @@
(let ((buffer-contents (buffer-substring-no-properties (point-min)
(point-max))))
(should (equal buffer-contents "<html>\n <head>\n <title><?php
echo $title; ?></title>\n </head>\n <body>\n <div
class=\"contents\"><?php echo $body; ?></div>\n </body>\n</html>"))))
+ (phps-mode-test-with-buffer
+ "<html>\n<head>\n<title><?php echo $title; ?></title>\n</head>\n<body
class=\"<?php echo $class; ?>\">\n<div class=\"contents\"><?php echo $body;
?></div>\n</body>\n</html>"
+ "A mixed HTML and PHP file, each PHP command is inside HTML markup, one PHP
inside markup tag"
+ (indent-region (point-min) (point-max))
+ (let ((buffer-contents (buffer-substring-no-properties (point-min)
(point-max))))
+ (should (equal buffer-contents "<html>\n <head>\n <title><?php
echo $title; ?></title>\n </head>\n <body class=\"<?php echo $class;
?>\">\n <div class=\"contents\"><?php echo $body; ?></div>\n
</body>\n</html>"))))
+
)
(defun phps-mode-test-functions-imenu ()
@@ -869,52 +874,67 @@
(phps-mode-test-with-buffer
"<?php\nclass myClass {\n public function myFunctionA() {}\n
protected function myFunctionB() {}\n}\n"
"Imenu object-oriented file"
- (should (equal (phps-mode-functions-get-imenu) '(("myClass" .
(("myFunctionA" . 43) ("myFunctionB" . 83)))))))
+ (should (equal (phps-mode-functions-get-imenu) '(("myClass" .
(("*definition*" . 13) ("myFunctionA" . 43) ("myFunctionB" . 83)))))))
(phps-mode-test-with-buffer
"<?php\ninterface myInterface {\n public function myFunctionA() {}\n
protected function myFunctionB() {}\n}\n"
"Imenu object-oriented file with interface"
- (should (equal (phps-mode-functions-get-imenu) '(("myInterface" .
(("myFunctionA" . 51) ("myFunctionB" . 91)))))))
+ (should (equal (phps-mode-functions-get-imenu) '(("myInterface" .
(("*definition*" . 17) ("myFunctionA" . 51) ("myFunctionB" . 91)))))))
(phps-mode-test-with-buffer
"<?php\nnamespace myNamespace {\n class myClass {\n public
function myFunctionA() {}\n protected function myFunctionB() {}\n
}\n}\n"
"Imenu object-oriented file with namespace, class and function"
- (should (equal (phps-mode-functions-get-imenu) '(("myNamespace" ("myClass"
("myFunctionA" . 75) ("myFunctionB" . 119)))))))
+ (should (equal (phps-mode-functions-get-imenu) '(("myNamespace"
("*definition*" . 17) ("myClass" ("*definition*" . 41) ("myFunctionA" . 75)
("myFunctionB" . 119)))))))
(phps-mode-test-with-buffer
"<?php\nnamespace myNamespace;\nclass myClass {\n public function
myFunctionA() {}\n protected function myFunctionB() {}\n}\n"
"Imenu object-oriented file with bracket-less namespace, class and function"
- (should (equal (phps-mode-functions-get-imenu) '(("myNamespace" ("myClass"
("myFunctionA" . 66) ("myFunctionB" . 106)))))))
+ (should (equal (phps-mode-functions-get-imenu) '(("myNamespace"
("*definition*" . 17) ("myClass" ("*definition*" . 36) ("myFunctionA" . 66)
("myFunctionB" . 106)))))))
(phps-mode-test-with-buffer
"<?php\nnamespace myNamespace {\n class myClass extends myAbstract {\n
public function myFunctionA() {}\n protected function myFunctionB()
{}\n }\n}\n"
"Imenu object-oriented file with namespace, class that extends and
functions"
- (should (equal (phps-mode-functions-get-imenu) '(("myNamespace" ("myClass"
("myFunctionA" . 94) ("myFunctionB" . 138)))))))
+ (should (equal (phps-mode-functions-get-imenu) '(("myNamespace"
("*definition*" . 17) ("myClass" ("*definition*" . 41) ("myFunctionA" . 94)
("myFunctionB" . 138)))))))
(phps-mode-test-with-buffer
"<?php\nnamespace myNamespace;\nclass myClass extends myAbstract implements
myInterface {\n public function myFunctionA() {}\n protected function
myFunctionB() {}\n}\n"
"Imenu object-oriented file with bracket-less namespace, class that extends
and implements and functions"
- (should (equal (phps-mode-functions-get-imenu) '(("myNamespace" ("myClass"
("myFunctionA" . 108) ("myFunctionB" . 148)))))))
+ (should (equal (phps-mode-functions-get-imenu) '(("myNamespace"
("*definition*" . 17) ("myClass" ("*definition*" . 36) ("myFunctionA" . 108)
("myFunctionB" . 148)))))))
(phps-mode-test-with-buffer
"<?php\nnamespace myNamespace;\nclass myClass extends myAbstract implements
myInterface {\n public function myFunctionA($myArg = null) {}\n protected
function myFunctionB($myArg = 'abc') {}\n}\n"
"Imenu object-oriented file with bracket-less namespace, class that extends
and implements and functions with optional arguments"
- (should (equal (phps-mode-functions-get-imenu) '(("myNamespace" ("myClass"
("myFunctionA" . 108) ("myFunctionB" . 161)))))))
+ (should (equal (phps-mode-functions-get-imenu) '(("myNamespace"
("*definition*" . 17) ("myClass" ("*definition*" . 36) ("myFunctionA" . 108)
("myFunctionB" . 161)))))))
(phps-mode-test-with-buffer
"<?php\nnamespace myNamespace\\myNamespace2;\nclass myClass extends
myAbstract implements myInterface {\n public function myFunctionA($myArg =
null) {}\n protected function myFunctionB($myArg = 'abc') {}\n}\n"
"Imenu object-oriented file with bracket-less namespace with multiple
levels, class that extends and implements and functions with optional arguments"
- (should (equal (phps-mode-functions-get-imenu)
'(("myNamespace\\myNamespace2" ("myClass" ("myFunctionA" . 121) ("myFunctionB"
. 174)))))))
+ (should (equal (phps-mode-functions-get-imenu)
'(("myNamespace\\myNamespace2" ("*definition*" . 29) ("myClass" ("*definition*"
. 49) ("myFunctionA" . 121) ("myFunctionB" . 174)))))))
(phps-mode-test-with-buffer
"<?php\nclass myClass\n{\n\n public function myFunction1()\n {\n
echo \"my string with variable {$variable} inside it\";\n }\n\n public
function myFunction2()\n {\n }\n\n}"
"Imenu with double quoted string with variable inside it"
- (should (equal (phps-mode-functions-get-imenu) '(("myClass" ("myFunction1"
. 44) ("myFunction2" . 153))))))
+ (should (equal (phps-mode-functions-get-imenu) '(("myClass" ("*definition*"
. 13) ("myFunction1" . 44) ("myFunction2" . 153))))))
(phps-mode-test-with-buffer
"<?php\n\nnamespace MyNamespace;\n\nclass MyClass\n{\n\n /**\n *\n
*/\n public function __construct()\n {\n if ($test) {\n
}\n }\n\n /**\n *\n */\n public function myFunction1()\n
{\n $this->addMessage(\"My random {$message} here\" . ($random > 1 ?
\"A\" : \"\") . \" was here.\");\n }\n \n /**\n *\n */\n
public function myFunction2()\n {\n }\n\n /**\n * It's good\n
*/\n public function my [...]
"Imenu with double quoted string with variable inside it and concatenated
string"
- (should (equal (phps-mode-functions-get-imenu) '(("MyNamespace" ("MyClass"
("__construct" . 92) ("myFunction1" . 193) ("myFunction2" . 365) ("myFunction3"
. 445) ("myFunction4" . 515)))))))
+ (should (equal (phps-mode-functions-get-imenu) '(("MyNamespace"
("*definition*" . 18) ("MyClass" ("*definition*" . 38) ("__construct" . 92)
("myFunction1" . 193) ("myFunction2" . 365) ("myFunction3" . 445)
("myFunction4" . 515)))))))
+
+ (phps-mode-test-with-buffer
+ "<?php\nclass myClass {}"
+ "Imenu empty class"
+ (should (equal (phps-mode-functions-get-imenu) '(("myClass" ("*definition*"
. 13))))))
+
+ (phps-mode-test-with-buffer
+ "<?php\nnamespace myNamespace {}"
+ "Imenu empty bracketed namespace"
+ (should (equal (phps-mode-functions-get-imenu) '(("myNamespace"
("*definition*" . 17))))))
+
+ (phps-mode-test-with-buffer
+ "<?php\nnamespace myNamespace;"
+ "Imenu empty namespace without brackets"
+ (should (equal (phps-mode-functions-get-imenu) '(("myNamespace"
("*definition*" . 17))))))
)
diff --git a/phps-mode-test-integration.el b/test/phps-mode-test-integration.el
similarity index 99%
rename from phps-mode-test-integration.el
rename to test/phps-mode-test-integration.el
index bc572e8..0f7e522 100644
--- a/phps-mode-test-integration.el
+++ b/test/phps-mode-test-integration.el
@@ -26,8 +26,7 @@
;;; Code:
(require 'ert)
-(require 'phps-mode-functions)
-(require 'phps-mode-lexer)
+(require 'phps-mode)
(require 'phps-mode-test)
(eval-when-compile
diff --git a/phps-mode-test-lexer.el b/test/phps-mode-test-lexer.el
similarity index 99%
rename from phps-mode-test-lexer.el
rename to test/phps-mode-test-lexer.el
index 0b3b05b..1abf3ce 100644
--- a/phps-mode-test-lexer.el
+++ b/test/phps-mode-test-lexer.el
@@ -27,7 +27,6 @@
(require 'ert)
(require 'phps-mode)
-(require 'phps-mode-lexer)
(require 'phps-mode-test)
(defun phps-mode-test-lexer-script-boundaries ()
diff --git a/phps-mode-test-parser.el b/test/phps-mode-test-parser.el
similarity index 100%
rename from phps-mode-test-parser.el
rename to test/phps-mode-test-parser.el
diff --git a/phps-mode-test-syntax-table.el
b/test/phps-mode-test-syntax-table.el
similarity index 99%
rename from phps-mode-test-syntax-table.el
rename to test/phps-mode-test-syntax-table.el
index 84305bd..d9c9eab 100644
--- a/phps-mode-test-syntax-table.el
+++ b/test/phps-mode-test-syntax-table.el
@@ -26,7 +26,7 @@
;;; Code:
(require 'ert)
-(require 'phps-mode-functions)
+(require 'phps-mode)
(require 'phps-mode-test)
;; TODO Should test `backward-sexp', `forward-sexp', `backward-word',
`forward-word', `backward-list', `forward-list' as well
diff --git a/phps-mode-test.el b/test/phps-mode-test.el
similarity index 98%
rename from phps-mode-test.el
rename to test/phps-mode-test.el
index 8050594..54c9c80 100644
--- a/phps-mode-test.el
+++ b/test/phps-mode-test.el
@@ -25,8 +25,7 @@
(require 'ert)
(require 'phps-mode)
-(require 'phps-mode-functions)
-(require 'phps-mode-lexer)
+(require 'phps-mode-macros)
(defmacro phps-mode-test-incremental-vs-intial-buffer (source &optional title
&rest change)
"Set up test buffer with SOURCE, TITLE, apply CHANGE and compare incremental
values with initial values."
@@ -118,6 +117,9 @@
(sort (nreverse result) (lambda (a b) (< (car a) (car b)))))
nil)))
+(transient-mark-mode t)
+(electric-pair-mode t)
+
(provide 'phps-mode-test)
;;; phps-mode-test.el ends here
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [elpa] externals/phps-mode b869339: Re-organization and improvements in usability,
Christian Johansson <=