terdon

terdon's web-mode.el

Jan 12th, 2015
262
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lisp 240.72 KB | None | 0 0
  1. ;;; web-mode.el --- major mode for editing html templates -*- coding: utf-8 -*-
  2.  
  3. ;; Copyright 2011-2013 François-Xavier Bois
  4.  
  5. ;; Version: 7.0.25
  6. ;; Author: François-Xavier Bois <fxbois AT Google Mail Service>
  7. ;; Maintainer: François-Xavier Bois
  8. ;; Created: July 2011
  9. ;; Keywords: html template php javascript js css web
  10. ;;           django jsp asp erb twig jinja blade dust closure
  11. ;;           freemarker mustache velocity cheetah smarty
  12. ;; URL: http://web-mode.org
  13. ;; Repository: http://github.com/fxbois/web-mode
  14.  
  15. ;; =========================================================================
  16. ;; This work is sponsored by Kernix : Digital Agency (Web & Mobile) in Paris
  17. ;; =========================================================================
  18.  
  19. ;; This file is not part of Emacs
  20.  
  21. ;; This file is free software; you can redistribute it and/or modify
  22. ;; it under the terms of the GNU General Public License as published by
  23. ;; the Free Software Foundation; either version 2, or (at your option)
  24. ;; any later version.
  25.  
  26. ;; This file is distributed in the hope that it will be useful,
  27. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  28. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  29. ;; GNU General Public License for more details.
  30.  
  31. ;; You should have received a copy of the GNU General Public License
  32. ;; along with GNU Emacs; see the file COPYING.  If not, write to
  33. ;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  34. ;; Boston, MA 02111-1307, USA.
  35.  
  36. ;; Code goes here
  37.  
  38. ;;todo : auto-pairs deviennent spécifiques à un engine
  39. ;;todo : reduction des css rules div { ... }
  40. ;;todo : passer les content-types en symboles
  41. ;;todo : tester shortcut A -> pour pomme
  42. ;;todo : commentaire d'une ligne ruby ou d'une ligne asp
  43. ;;todo : ne mettre tag-type et tag-name que sur le '<'
  44. ;;todo : créer tag-token pour différentier de part-token : tag-token=attr,comment ???
  45.  
  46. (defgroup web-mode nil
  47.   "Major mode for editing web templates:
  48.   HTML files embedding parts (CSS/JavaScript)
  49.   and blocks (PHP, Erb, Django/Twig, Smarty, JSP, ASP, etc.)."
  50.   :version "7.0.25"
  51.   :group 'languages)
  52.  
  53. (defgroup web-mode-faces nil
  54.   "Faces for syntax highlighting."
  55.   :group 'web-mode
  56.   :group 'faces)
  57.  
  58. (defcustom web-mode-script-padding 1
  59.   "Script element left padding."
  60.   :type 'integer
  61.   :group 'web-mode)
  62.  
  63. (defcustom web-mode-style-padding 1
  64.   "Style element left padding."
  65.   :type 'integer
  66.   :group 'web-mode)
  67.  
  68. (defcustom web-mode-block-padding 0
  69.   "Multi-line block (PHP, Ruby, Java, etc.) left padding."
  70.   :type 'integer
  71.   :group 'web-mode)
  72.  
  73. (defcustom web-mode-markup-indent-offset 2
  74.   "HTML indentation level."
  75.   :type 'integer
  76.   :group 'web-mode)
  77.  
  78. (defcustom web-mode-css-indent-offset 2
  79.   "CSS indentation level."
  80.   :type 'integer
  81.   :group 'web-mode)
  82.  
  83. (defcustom web-mode-code-indent-offset 2
  84.   "Code (JavaScript, PHP, etc.) indentation level."
  85.   :type 'integer
  86.   :group 'web-mode)
  87.  
  88. (defcustom web-mode-disable-css-colorization (not (display-graphic-p))
  89.   "In a CSS block, do not set background according to the color: #xxx, rgb(x,x,x)."
  90.   :type 'boolean
  91.   :group 'web-mode)
  92.  
  93. (defcustom web-mode-disable-auto-indentation (not (display-graphic-p))
  94.   "Disable auto-indentation."
  95.   :type 'boolean
  96.   :group 'web-mode)
  97.  
  98. (defcustom web-mode-disable-auto-pairing (not (display-graphic-p))
  99.   "Disable auto-pairing."
  100.   :type 'boolean
  101.   :group 'web-mode)
  102.  
  103. (defcustom web-mode-enable-current-element-highlight nil
  104.   "Disable element highlight."
  105.   :type 'boolean
  106.   :group 'web-mode)
  107.  
  108. (defcustom web-mode-enable-whitespaces nil
  109.   "Enable whitespaces."
  110.   :type 'boolean
  111.   :group 'web-mode)
  112.  
  113. (defcustom web-mode-enable-block-face nil
  114.   "Enable block face (useful for setting a background for example).
  115. See web-mode-block-face."
  116.   :type 'boolean
  117.   :group 'web-mode)
  118.  
  119. (defcustom web-mode-enable-part-face nil
  120.   "Enable part face (useful for setting a background for example).
  121. See web-mode-part-face."
  122.   :type 'boolean
  123.   :group 'web-mode)
  124.  
  125. (defcustom web-mode-enable-heredoc-fontification nil
  126.   "Enable heredoc fontification. The identifier should contain JS, JAVASCRIPT or HTML."
  127.   :type 'boolean
  128.   :group 'web-mode)
  129.  
  130. (defcustom web-mode-enable-comment-keywords nil
  131.   "Enable highlight of keywords like FIXME, TODO, etc. in comments."
  132.   :type 'list
  133.   :group 'web-mode)
  134.  
  135. (defcustom web-mode-comment-style 1
  136.   "Comment style : 2 = server comments."
  137.   :type 'integer
  138.   :group 'web-mode)
  139.  
  140. (defcustom web-mode-indent-style 2
  141.   "Indentation style.
  142. with value 2, HTML lines beginning text are also indented (do not forget side effects, ie. content of a textarea)."
  143.   :type 'integer
  144.   :group 'web-mode)
  145.  
  146. (defcustom web-mode-tag-auto-close-style 1
  147.   "Tag auto-close style:
  148. 0=no auto-closing
  149. 1=auto-close with </
  150. 2=auto-close with > and </."
  151.   :type 'integer
  152.   :group 'web-mode)
  153.  
  154. (defcustom web-mode-extra-php-constants '()
  155.   "A list of additional strings to treat as PHP constants."
  156.   :type 'list
  157.   :group 'web-mode)
  158.  
  159. (defcustom web-mode-extra-php-keywords '()
  160.   "A list of additional strings to treat as PHP keywords."
  161.   :type 'list
  162.   :group 'web-mode)
  163.  
  164. (defcustom web-mode-extra-jsp-keywords '()
  165.   "A list of additional strings to treat as JSP keywords."
  166.   :type 'list
  167.   :group 'web-mode)
  168.  
  169. (defcustom web-mode-extra-python-keywords '()
  170.   "A list of additional strings to treat as Python keywords."
  171.   :type 'list
  172.   :group 'web-mode)
  173.  
  174. (defcustom web-mode-extra-erb-keywords '()
  175.   "A list of additional strings to treat as ERB keywords."
  176.   :type 'list
  177.   :group 'web-mode)
  178.  
  179. (defcustom web-mode-extra-asp-constants '()
  180.   "A list of additional strings to treat as ASP constants."
  181.   :type 'list
  182.   :group 'web-mode)
  183.  
  184. (defcustom web-mode-extra-asp-keywords '()
  185.   "A list of additional strings to treat as ASP keywords."
  186.   :type 'list
  187.   :group 'web-mode)
  188.  
  189. (defcustom web-mode-extra-asp-types '()
  190.   "A list of additional strings to treat as ASP types."
  191.   :type 'list
  192.   :group 'web-mode)
  193.  
  194. (defcustom web-mode-extra-aspx-keywords '()
  195.   "A list of additional strings to treat as ASPX keywords."
  196.   :type 'list
  197.   :group 'web-mode)
  198.  
  199. (defcustom web-mode-extra-javascript-keywords '()
  200.   "A list of additional strings to treat as JS keywords."
  201.   :type 'list
  202.   :group 'web-mode)
  203.  
  204. (defcustom web-mode-extra-razor-keywords '()
  205.   "A list of additional strings to treat as Razor keywords."
  206.   :type 'list
  207.   :group 'web-mode)
  208.  
  209. (defcustom web-mode-extra-comment-keywords '()
  210.   "A list of additional strings to treat as comment keywords."
  211.   :type 'list
  212.   :group 'web-mode)
  213.  
  214. (defface web-mode-warning-face
  215.   '((t :inherit font-lock-warning-face))
  216.   "Face for warning."
  217.   :group 'web-mode-faces)
  218.  
  219. (defface web-mode-preprocessor-face
  220.   '((t :inherit font-lock-preprocessor-face))
  221.   "Face for preprocessor."
  222.   :group 'web-mode-faces)
  223.  
  224. (defface web-mode-block-control-face
  225.   '((t :inherit font-lock-preprocessor-face))
  226.   "Face for preprocessor."
  227.   :group 'web-mode-faces)
  228.  
  229. (defface web-mode-builtin-face
  230.   '((t :inherit font-lock-builtin-face))
  231.   "Face for builtins."
  232.   :group 'web-mode-faces)
  233.  
  234. (defface web-mode-symbol-face
  235.   '((t :foreground "gold"))
  236.   "Face for symbols."
  237.   :group 'web-mode-faces)
  238.  
  239. (defface web-mode-doctype-face
  240.   '((t :foreground "Grey"))
  241.   "Face for HTML doctype."
  242.   :group 'web-mode-faces)
  243.  
  244. (defface web-mode-html-tag-face
  245.   '((t :foreground "Snow4"))
  246.   "Face for HTML tags."
  247.   :group 'web-mode-faces)
  248.  
  249. (defface web-mode-html-attr-name-face
  250.   '((t :foreground "Snow3"))
  251.   "Face for HTML attribute names (including =)."
  252.   :group 'web-mode-faces)
  253.  
  254. (defface web-mode-html-attr-value-face
  255.   '((t :inherit font-lock-string-face))
  256.   "Face for HTML attribute values."
  257.   :group 'web-mode-faces)
  258.  
  259. (defface web-mode-block-attr-name-face
  260.   '((t :inherit web-mode-html-attr-name-face))
  261.   "Face for block attribute names."
  262.   :group 'web-mode-faces)
  263.  
  264. (defface web-mode-block-attr-value-face
  265.   '((t :inherit web-mode-html-attr-value-face))
  266.   "Face for block attribute values."
  267.   :group 'web-mode-faces)
  268.  
  269. (defface web-mode-css-selector-face
  270.   '((t :inherit font-lock-keyword-face))
  271.   "Face for CSS rules."
  272.   :group 'web-mode-faces)
  273.  
  274. (defface web-mode-css-pseudo-class-face
  275.   '((t :inherit font-lock-builtin-face))
  276.   "Face for CSS pseudo-classes."
  277.   :group 'web-mode-faces)
  278.  
  279. (defface web-mode-css-at-rule-face
  280.   '((t :inherit font-lock-constant-face))
  281.   "Face for CSS at-rules."
  282.   :group 'web-mode-faces)
  283.  
  284. (defface web-mode-css-property-name-face
  285.   '((t :inherit font-lock-variable-name-face))
  286.   "Face for CSS props."
  287.   :group 'web-mode-faces)
  288.  
  289. (defface web-mode-css-color-face
  290.   '((t :inherit font-lock-builtin-face))
  291.   "Face for CSS colors (#xxx)."
  292.   :group 'web-mode-faces)
  293.  
  294. (defface web-mode-css-priority-face
  295.   '((t :inherit font-lock-builtin-face))
  296.   "Face for CSS priority (!important)."
  297.   :group 'web-mode-faces)
  298.  
  299. (defface web-mode-css-function-face
  300.   '((t :inherit font-lock-builtin-face))
  301.   "Face for CSS functions."
  302.   :group 'web-mode-faces)
  303.  
  304. (defface web-mode-variable-name-face
  305.   '((t :inherit font-lock-variable-name-face))
  306.   "Face for variable names."
  307.   :group 'web-mode-faces)
  308.  
  309. (defface web-mode-function-name-face
  310.   '((t :inherit font-lock-function-name-face))
  311.   "Face for function names."
  312.   :group 'web-mode-faces)
  313.  
  314. (defface web-mode-string-face
  315.   '((t :inherit font-lock-string-face))
  316.   "Face for strings."
  317.   :group 'web-mode-faces)
  318.  
  319. (defface web-mode-block-string-face
  320.   '((t :inherit web-mode-string-face))
  321.   "Face for block strings."
  322.   :group 'web-mode-faces)
  323.  
  324. (defface web-mode-part-string-face
  325.   '((t :inherit web-mode-string-face))
  326.   "Face for part strings."
  327.   :group 'web-mode-faces)
  328.  
  329. (defface web-mode-javascript-string-face
  330.   '((t :inherit web-mode-string-face))
  331.   "Face for javascript strings."
  332.   :group 'web-mode-faces)
  333.  
  334. (defface web-mode-css-string-face
  335.   '((t :inherit web-mode-string-face))
  336.   "Face for css strings."
  337.   :group 'web-mode-faces)
  338.  
  339. (defface web-mode-json-key-face
  340.   '((t :foreground "plum"))
  341.   "Face for json key strings."
  342.   :group 'web-mode-faces)
  343.  
  344. (defface web-mode-json-context-face
  345.   '((t :foreground "orchid3"))
  346.   "Face for json context strings."
  347.   :group 'web-mode-faces)
  348.  
  349. (defface web-mode-json-string-face
  350.   '((t :inherit web-mode-string-face))
  351.   "Face for json strings."
  352.   :group 'web-mode-faces)
  353.  
  354. (defface web-mode-comment-face
  355.   '((t :inherit font-lock-comment-face))
  356.   "Face for comments."
  357.   :group 'web-mode-faces)
  358.  
  359. (defface web-mode-block-comment-face
  360.   '((t :inherit web-mode-comment-face))
  361.   "Face for server comments."
  362.   :group 'web-mode-faces)
  363.  
  364. (defface web-mode-part-comment-face
  365.   '((t :inherit web-mode-comment-face))
  366.   "Face for part comments."
  367.   :group 'web-mode-faces)
  368.  
  369. (defface web-mode-constant-face
  370.   '((t :inherit font-lock-constant-face))
  371.   "Face for language constants."
  372.   :group 'web-mode-faces)
  373.  
  374. (defface web-mode-type-face
  375.   '((t :inherit font-lock-type-face))
  376.   "Face for language types."
  377.   :group 'web-mode-faces)
  378.  
  379. (defface web-mode-keyword-face
  380.   '((t :inherit font-lock-keyword-face))
  381.   "Face for language keywords."
  382.   :group 'web-mode-faces)
  383.  
  384. (defface web-mode-param-name-face
  385.   '((t :foreground "Snow3"))
  386.   "Face for server attribute names."
  387.   :group 'web-mode-faces)
  388.  
  389. (defface web-mode-whitespace-face
  390.   '((t :background "DarkOrchid4"))
  391.   "Face for whitespaces."
  392.   :group 'web-mode-faces)
  393.  
  394. (defface web-mode-block-face
  395.   '((((class color) (min-colors 88) (background dark))
  396.      :background "grey18")
  397.     (((class color) (min-colors 88) (background light))
  398.      :background "LightYellow1")
  399.     (((class color) (min-colors 16) (background dark))
  400.      :background "grey18")
  401.     (((class color) (min-colors 16) (background light))
  402.      :background "LightYellow1")
  403.     (((class color) (min-colors 8))
  404.      :background "Black")
  405.     (((type tty) (class mono))
  406.      :inverse-video t)
  407.     (t :background "grey"))
  408.   "Face for blocks (useful for setting a background for example).
  409. Must be used in conjunction with web-mode-enable-block-face."
  410.   :group 'web-mode-faces)
  411.  
  412. (defface web-mode-part-face
  413.   '((t :inherit web-mode-block-face))
  414.   "Face for parts."
  415.   :group 'web-mode-faces)
  416.  
  417. (defface web-mode-folded-face
  418.   '((t :underline t))
  419.   "Overlay face for folded."
  420.   :group 'web-mode-faces)
  421.  
  422. (defface web-mode-current-element-highlight-face
  423.   '((t :underline t :bold t))
  424.   "Overlay face for element highlight."
  425.   :group 'web-mode-faces)
  426.  
  427.  
  428. (defface web-mode-comment-keyword-face
  429.   '((t :weight bold :box t))
  430.   "Comment keywords."
  431.   :group 'web-mode-faces)
  432.  
  433. (defvar web-mode-void-elements
  434.   '("area" "base" "br" "col" "command" "embed" "hr" "img" "input" "keygen"
  435.     "link" "meta" "param" "source" "track" "wbr")
  436.   "Void (self-closing) tags.")
  437.  
  438. (defvar web-mode-text-properties
  439.   '(part-side nil part-token nil part-language nil tag-name nil tag-type nil tag-beg nil tag-end nil block-side nil block-token nil block-beg nil block-end nil face nil)
  440.   "Text properties used for fontification and indentation.")
  441.  
  442. (defvar web-mode-text-properties2
  443.   '(part-side nil part-token nil part-language nil tag-name nil tag-type nil tag-beg nil tag-end nil face nil)
  444.   "Text properties used for fontification and indentation.")
  445.  
  446. (defvar web-mode-large-embed-threshold 512
  447.   "Threshold for large part/block.")
  448.  
  449. (defvar web-mode-has-any-large-part nil
  450.   "Does the current buffer has large parts ?")
  451.  
  452. (defvar web-mode-has-any-large-block nil
  453.   "Does the current buffer has large blocks ?")
  454.  
  455. (defvar web-mode-is-scratch nil
  456.   "Is scratch buffer ?")
  457.  
  458. (defvar web-mode-time nil
  459.   "For benchmarking")
  460.  
  461. (defvar web-mode-start-tag-overlay nil)
  462.  
  463. (defvar web-mode-end-tag-overlay nil)
  464.  
  465. (defvar web-mode-expand-initial-pos nil
  466.   "First mark pos.")
  467.  
  468. (defvar web-mode-expand-previous-state ""
  469.   "Last mark state.")
  470.  
  471. (defvar web-mode-tag-regexp "<\\(/?[[:alpha:]][[:alnum:]]*\\)"
  472.   "Regular expression for HTML/XML tag.")
  473.  
  474. (defvar web-mode-start-tag-regexp "<\\([[:alpha:]][[:alnum:]]*\\)"
  475.   "Regular expression for HTML/XML start tag.")
  476.  
  477. (defvar web-mode-whitespaces-regexp
  478.   "^[ \t]\\{2,\\}$\\| \t\\|\t \\|[ \t]+$\\|^[ \n\t]+\\'\\|^[ \t]?[\n]\\{2,\\}"
  479.   "Regular expression for whitespaces.")
  480.  
  481. (defvar web-mode-engine nil
  482.   "Template engine")
  483.  
  484. (defvar web-mode-engines
  485.   '(("asp"        . ("asp"))
  486.     ("aspx"       . ("aspx"))
  487.     ("blade"      . ("laravel"))
  488.     ("closure"    . ("soy"))
  489.     ("ctemplate"  . ("mustache" "handlebars" "hapax" "ngtemplate" "ember" "kite"))
  490.     ("django"     . ("dtl" "twig" "swig" "jinja" "jinja2" "erlydtl"))
  491.     ("dust"       . ("dustjs"))
  492.     ("erb"        . ("eruby" "erubis"))
  493.     ("go"         . ("gtl"))
  494.     ("jsp"        . ())
  495.     ("python"     . ())
  496.     ("razor"      . ("play" "play2"))
  497.     ("underscore" . ("underscorejs"))
  498.     ("velocity"   . ("vtl" "cheetah")))
  499.   "Engine name aliases")
  500.  
  501. (defvar web-mode-content-types
  502.   '(("css"        . "\\.css\\'")
  503.     ("javascript" . "\\.js\\'")
  504.     ("json"       . "\\.\\(json\\|jsonld\\)\\'")
  505.     ("html"       . "."))
  506.   "content types")
  507.  
  508. (defvar web-mode-engine-file-regexps
  509.   '(("asp"              . "\\.asp\\'")
  510.     ("aspx"             . "\\.as[cp]x\\'")
  511.     ("blade"            . "\\.blade")
  512.     ("closure"          . "\\.soy\\'")
  513.     ("ctemplate"        . "\\.\\(chtml\\)\\'")
  514.     ("django"           . "\\.\\(djhtml\\|tmpl\\|dtl\\)\\'")
  515.     ("django"           . "twig")
  516.     ("dust"             . "\\.dust\\'")
  517.     ("erb"              . "\\.\\(erb\\|rhtml\\)\\'")
  518.     ("freemarker"       . "\\.ftl\\'")
  519.     ("go"               . "\\.go\\(html\\|tmpl\\)\\'")
  520.     ("handlebars"       . "\\(handlebars\\|.\\hbs\\'\\)")
  521.     ("jsp"              . "\\.jsp\\'")
  522.     ("mustache"         . "\\.mustache\\'")
  523.     ("php"              . "\\.\\(php\\|ctp\\|psp\\|inc\\)\\'")
  524.     ("python"           . "\\.pml\\'")
  525.     ("razor"            . "play\\|\\.scala\\.\\|\\.cshtml\\'\\|\\.vbhtml\\'")
  526.     ("smarty"           . "\\.tpl\\'")
  527.     ("template-toolkit" . "\\.tt.?\\'")
  528.     ("underscore"       . "\\.underscore\\'")
  529.     ("velocity"         . "\\.\\(vsl\\|vtl\\|vm\\)\\'"))
  530.   "Engine file extensions.")
  531.  
  532. (defvar web-mode-smart-quotes
  533.   '("«" . "»")
  534.   "Preferred smart quotes")
  535.  
  536. (defvar web-mode-xml-chars
  537.   '((?\& . "&amp;")
  538.     (?\< . "&lt;")
  539.     (?\> . "&gt;"))
  540.   "XML chars")
  541.  
  542. (defvar web-mode-html-entities
  543.   '(("eacute" . "é")
  544.     ("egrave" . "è")
  545.     ("middot" . "·")
  546.     ("quot"   . "\"")
  547.     ("amp"    . "&")
  548.     ("lt"     . "<")
  549.     ("gt"     . ">")
  550.     ("laquo"  . "«")
  551.     ("raquo"  . "»")
  552.     ("lsquo"  . "‘")
  553.     ("rsquo"  . "’")
  554.     ("ldquo"  . "“")
  555.     ("rdquo"  . "”")
  556.     ("apos"   . "'"))
  557.   "HTML entities")
  558.  
  559. (defvar web-mode-snippets
  560.   (list
  561.    '("table"
  562.      "<table><tbody>\n<tr>\n<td>"
  563.      "</td>\n<td></td>\n</tr>\n</tbody></table>")
  564.    '("ul"
  565.      "<ul>\n<li>"
  566.      "</li>\n<li></li>\n</ul>")
  567.    '("if"
  568.      "<?php if ( as ): ?>\n"
  569.      "\n<?php endif; ?>")
  570.    '("for"
  571.      "<?php for ( ; ; ): ?>\n"
  572.      "\n<?php endfor; ?>")
  573.    '("foreach"
  574.      "<?php foreach ( as ): ?>\n"
  575.      "\n<?php endforeach; ?>")
  576.    '("html5"
  577.      "<!doctype html>\n<html>\n<head>\n<title></title>\n<meta charset=\"utf-8\" />\n</head>\n<body>\n"
  578.      "\n</body>\n</html>")
  579.    )
  580.   "Code snippets")
  581.  
  582. ;; todo : dynamically construct according to engine
  583. (defvar web-mode-auto-pairs
  584.   (list
  585.    '("<?p"  "hp  ?>"   "\\?>"  3)
  586.    '("<? "  "?>"       "\\?>"  0)
  587.    '("<?="  "?>"       "\\?>"  0)
  588.    '("<!-"  "-  -->"   "--"    2)
  589. ;; underscrore js conflict
  590. ;;   '("<%-"  "-  --%>"  "--"    2)
  591.    '("<%@"  "  %>"     "%>"    1)
  592.    '("<%="  "%>"       "%>"    0)
  593.    '("<% "  " %>"      "%>"    0)
  594.    '("{{ "  " }}"      "}}"    0)
  595.    '("{% "  " %}"      "%}"    0)
  596.    '("{# "  " #}"      "#}"    0)
  597.    '("[% "  " %]"      "%]"    0)
  598.    '("[# "  " #]"      "#]"    0)
  599.    )
  600.   "Auto-Pairs")
  601.  
  602. (defvar web-mode-content-type ""
  603.   "Buffer file type.")
  604.  
  605. (defvar web-mode-comments-invisible nil
  606.   "Comments visbility.")
  607.  
  608. (defvar web-mode-is-narrowed nil
  609.   "Buffer has been narrowed.")
  610.  
  611. (defvar web-mode-hook nil
  612.   "List of functions to be executed with web-mode.")
  613.  
  614. (defvar web-mode-buffer-highlighted nil
  615.   "Is buffer highlighted.")
  616.  
  617. (defvar web-mode-display-table nil
  618.   "Display table.")
  619.  
  620. (defvar web-mode-hl-line-mode-flag nil
  621.   "Is hl-line-mode enabled ?")
  622.  
  623. (defvar web-mode-blade-active-blocks
  624.   '("else" "elseif" "foreach" "forelse" "for" "if" "section" "stop" "unless" "while")
  625.   "Blade controls.")
  626.  
  627. (defvar web-mode-closure-active-blocks
  628.   '("call" "case" "default" "deltemplate" "else" "elseif" "for" "foreach"
  629.     "if" "ifempty" "let" "literal" "msg" "param" "switch" "template")
  630.   "Closure controls.")
  631.  
  632. (defvar web-mode-django-active-blocks
  633.   '("assets" "autoescape" "block" "cache" "call" "comment"
  634.     "elif" "else" "elseif" "embed" "empty" "filter" "foreach" "for"
  635.     "ifchanged" "ifequal" "ifnotequal" "if"
  636.     "macro" "draw" "random" "sandbox" "spaceless" "trans" "verbatim" "with")
  637.   "Django controls.")
  638.  
  639. (defvar web-mode-go-active-blocks
  640.   '("else" "end" "if" "range" "with")
  641.   "Go controls.")
  642.  
  643. (defvar web-mode-php-active-blocks
  644.   '("declare" "else" "elseif" "for" "foreach" "if" "while")
  645.   "PHP controls.")
  646.  
  647. (defvar web-mode-smarty-active-blocks
  648.   '("block" "else" "elseif" "foreach" "for" "if" "section" "while")
  649.   "Smarty controls.")
  650.  
  651. (defvar web-mode-velocity-active-blocks
  652.   '("define" "else" "elseif" "end" "for" "foreach" "if" "macro")
  653.   "Velocity controls.")
  654.  
  655. (defvar web-mode-active-block-regexps
  656.   (list
  657.    (cons "asp"        "----")
  658.    (cons "aspx"       "----")
  659.    (cons "blade"      (concat "@\\(end\\)?" (regexp-opt web-mode-blade-active-blocks t)))
  660.    (cons "closure"    (concat "{/?" (regexp-opt web-mode-closure-active-blocks t)))
  661.    (cons "ctemplate"  "{{[#^/]\\([[:alnum:]_]+\\)")
  662.    (cons "django"     (concat "{%[-]?[ ]+\\(end\\)?" (regexp-opt web-mode-django-active-blocks t)))
  663.    (cons "dust"       "{[#/:?@><+^]\\([[:alpha:]_]+\\)")
  664.    (cons "erb"        "<%[-=]?[ ]+\\(.* do \\|for\\|unless\\|end\\|if\\|else\\)")
  665.    (cons "freemarker" "</?\\([[:alpha:]]+:[[:alpha:]]+\\)\\|[[<]/?[@#]\\([[:alpha:]]+\\)")
  666.    (cons "go"         (concat "{{[ ]*" (regexp-opt web-mode-go-active-blocks t)))
  667.    (cons "jsp"        "</?\\([[:alpha:]]+:[[:alpha:]]+\\)\\|<%[ ]*+\\(if\\|for\\|while\\|} else {\\)")
  668.    (cons "php"        (concat "<\\?\\(php[ ]+\\|[ ]*\\)?\\(end\\)?" (regexp-opt web-mode-php-active-blocks t)))
  669.    (cons "razor"      "----")
  670.    (cons "smarty"     (concat "{/?" (regexp-opt web-mode-smarty-active-blocks t)))
  671.    (cons "template-toolkit" (concat "\\[% " (regexp-opt '("foreach" "if" "else" "elsif" "filter" "end") t)))
  672.    (cons "underscore" "<%")
  673.    (cons "velocity"   (concat "#" (regexp-opt web-mode-velocity-active-blocks t))))
  674.   "Engine control regexps")
  675.  
  676. (defvar web-mode-close-block-regexps
  677.   '(("asp"              . "----")
  678.     ("aspx"             . "----")
  679.     ("blade"            . "@\\\(end\\|else\\|stop\\)")
  680.     ("closure"          . "{\\(/\\|else\\|case\\|default\\|ifempty\\)")
  681.     ("ctemplate"        . "{{/")
  682.     ("django"           . "{%[-]?[ ]+\\(end\\|else\\|elseif\\|elif\\|empty\\)")
  683.     ("dust"             . "{\\(/\\|:else\\)")
  684.     ("erb"              . "<%[-]?[ ]+\\(end\\|else\\)")
  685.     ("freemarker"       . "[<[]\\(/#\\|#els\\|#break\\)")
  686.     ("go"               . "{{[ ]*\\(end\\|else\\)")
  687.     ("jsp"              . "</\\|<% }")
  688.     ("php"              . "<\\?\\(php[ ]+\\|[ ]*\\)?\\(end\\|else\\|}\\)")
  689.     ("razor"            . "}")
  690.     ("smarty"           . "{\\(/\\|else\\)")
  691.     ("template-toolkit" . "\\[% \\(end\\|els\\)")
  692.     ("underscore"       . "<% }")
  693.     ("velocity"         . "#\\(end\\|else\\)"))
  694.   "Close control blocks.")
  695.  
  696. (defvar web-mode-block-regexps
  697.   '(("asp"              . "<%")
  698.     ("aspx"             . "<%")
  699.     ("blade"            . "{{\\|^[ \t]*@[[:alpha:]]")
  700.     ("closure"          . "{.\\|/\\*\\| //")
  701.     ("ctemplate"        . "[$]?{{.")
  702.     ("django"           . "{[#{%].")
  703.     ("dust"             . "{.")
  704.     ("erb"              . "<%\\|^%.")
  705.     ("freemarker"       . "<%\\|${\\|</?[[:alpha:]]+:[[:alpha:]]\\|</?[@#].\\|\\[/?[@#].")
  706.     ("go"               . "{{.")
  707.     ("jsp"              . "<%\\|${\\|</?[[:alpha:]]+:[[:alpha:]]")
  708.     ("php"              . "<\\?")
  709.     ("python"           . "<\\?")
  710.     ("razor"            . "@.")
  711.     ("smarty"           . "{[[:alpha:]#$/*\"]")
  712.     ("template-toolkit" . "\\[[%#]")
  713.     ("underscore"       . "<%")
  714.     ("velocity"         . "^[ \t]*#[[:alpha:]#*]\\|$[[:alpha:]!{]"))
  715.   "Engine block regexps.")
  716.  
  717. (defvar web-mode-block-electric-chars
  718.   (list
  719.    (cons "blade"      '(?\{ ?\@))
  720.    (cons "closure"    '(?\{ ?\/))
  721.    (cons "ctemplate"  '(?\{ ?\$))
  722.    (cons "django"     '(?\{))
  723.    (cons "dust"       '(?\{))
  724.    (cons "erb"        '(?\%))
  725.    (cons "freemarker" '(?\[))
  726.    (cons "go"         '(?\{))
  727.    (cons "jsp"        '(?\$))
  728.    (cons "razor"      '(?\@))
  729.    (cons "smarty"     '(?\{))
  730.    (cons "velocity"   '(?\# ?\$)))
  731.   "Block electric chars.")
  732.  
  733. (defvar web-mode-block-regexp nil
  734.   "Regular expression for identifying blocks.")
  735.  
  736. (defvar web-mode-active-block-regexp nil
  737.   "Engine control regexp")
  738.  
  739. (defvar web-mode-close-block-regexp nil
  740.   "Engine end control regexp")
  741.  
  742. (defvar web-mode-engine-control-matcher nil
  743.   "Engine control match")
  744.  
  745. (defvar web-mode-electric-chars nil
  746.   "electric chars")
  747.  
  748. (defvar web-mode-comment-keywords
  749.   (regexp-opt
  750.    (append web-mode-extra-comment-keywords
  751.            '("FIXME" "TODO" "BUG" "KLUDGE" "WORKAROUND"
  752.              "OPTIMIZE" "HACK" "REFACTOR")))
  753.   "Comment keywords.")
  754.  
  755. (defvar web-mode-php-constants
  756.   (regexp-opt
  757.    (append web-mode-extra-php-constants
  758.            '("TRUE" "FALSE" "NULL" "true" "false" "null"
  759.              "STR_PAD_LEFT" "STR_PAD_RIGHT"
  760.              "ENT_COMPAT" "ENT_QUOTES" "ENT_NOQUOTES" "ENT_IGNORE"
  761.              "ENT_SUBSTITUTE" "ENT_DISALLOWED" "ENT_HTML401" "ENT_XML1"
  762.              "ENT_XHTML" "ENT_HTML5"
  763.              "LIBXML_NOBLANKS")))
  764.   "PHP constants.")
  765.  
  766. (defvar web-mode-php-keywords
  767.   (regexp-opt
  768.    (append web-mode-extra-php-keywords
  769.            '("and" "array" "as" "break"
  770.              "callable" "case" "catch"  "catch all" "class" "const" "continue"
  771.              "default" "die" "do"
  772.              "echo" "else" "elseif" "empty"
  773.              "endfor" "endforeach" "endif" "endswitch" "endwhile" "exit" "extends"
  774.              "finally" "for" "foreach" "function" "global" "goto"
  775.              "if" "include" "include_once" "instanceof" "interface" "isset"
  776.              "list" "next" "new" "or"
  777.              "private" "protected" "public"
  778.              "require" "require_once" "return" "static" "switch" "try" "throw" "unset" "use"
  779.              "var" "when" "while" "xor" "yield")))
  780.   "PHP keywords.")
  781.  
  782. (defvar web-mode-php-types
  783.   (eval-when-compile
  784.     (regexp-opt
  785.      '("array" "bool" "boolean" "char" "const" "double" "float"
  786.        "int" "integer" "long" "mixed" "object" "real" "string"
  787.        "Exception")))
  788.   "PHP types.")
  789.  
  790. (defvar web-mode-css-at-rules
  791.   (eval-when-compile
  792.     (regexp-opt
  793.      '("charset" "import" "media" "page" "font-face"
  794.        "namespace" "supports" "document"
  795.        "keyframes" "-moz-keyframes" "-webkit-keyframes")))
  796.   "CSS at-rules.")
  797.  
  798. (defvar web-mode-css-pseudo-classes
  799.   (eval-when-compile
  800.     (regexp-opt
  801.      '("active" "after" "before" "checked" "disabled" "empty" "enabled"
  802.        "first" "first-child" "first-letter" "first-line" "first-of-type" "focus"
  803.        "hover" "lang" "last-child" "last-of-type" "left" "link"
  804.        "not" "nth-child" "nth-last-child" "nth-last-of-type" "nth-of-type"
  805.        "only-child" "only-of-type"
  806.        "right" "root" "selection" "target" "visited")))
  807.   "CSS pseudo-classes (and pseudo-elements).")
  808.  
  809. (defvar web-mode-python-keywords
  810.   (regexp-opt
  811.    (append web-mode-extra-python-keywords
  812.            '("False" "class" "finally" "is" "return"
  813.              "None" "continue" "for" "lambda" "try"
  814.              "True" "def" "from" "nonlocal" "while"
  815.              "and" "del" "global" "not" "with"
  816.              "as" "elif" "if" "or" "yield"
  817.              "assert" "else" "import" "pass"
  818.              "break" "except" "in" "raise")))
  819.   "Python keywords.")
  820.  
  821. (defvar web-mode-jsp-keywords
  822.   (regexp-opt
  823.    (append web-mode-extra-jsp-keywords
  824.            '("case" "catch" "do" "else" "end" "false" "for" "function"
  825.              "if" "in" "include" "new"
  826.              "package" "page" "private" "protected" "public"
  827.              "return" "tag" "taglib" "throw" "throws" "true" "try"
  828.              "void" "while")))
  829.   "JSP keywords.")
  830.  
  831. (defvar web-mode-erb-keywords
  832.   (regexp-opt
  833.    (append web-mode-extra-erb-keywords
  834.            '("alias" "and" "begin" "break" "case" "class"
  835.              "def" "defined?" "do" "elsif" "else" "end" "ensure"
  836.              "fail" "for" "if" "in" "module" "next" "not"
  837.              "or" "redo" "rescue" "retry" "return" "then" "super"
  838.              "unless" "undef" "until" "when" "while" "yield"
  839.              "__ENCODING__" "__FILE__" "__LINE__"
  840.              )))
  841.   "ERB keywords.")
  842.  
  843. (defvar web-mode-erb-builtins
  844.   (regexp-opt
  845.    '("__callee__" "__dir__" "__method__"
  846.      "abort" "at_exit" "autoload" "autoload?"
  847.      "binding" "block_given?" "caller" "catch"
  848.      "eval" "exec" "exit" "exit!" "fail" "fork" "format"
  849.      "lambda" "load" "loop" "open"
  850.      "p" "print" "printf" "proc" "putc" "puts"
  851.      "raise" "rand" "readline" "readlines" "require" "require_relative"
  852.      "sleep" "spawn" "sprintf" "srand" "syscall" "system"
  853.      "throw" "trap" "warn"
  854.      "alias_method" "attr" "attr_accessor" "attr_reader" "attr_writer"
  855.      "define_method" "extend" "include" "module_function"
  856.      "prepend" "private" "protected" "public"
  857.      "refine" "using"
  858.  
  859.      "error_message_on" "error_messages_for" "form" "input"
  860.      "auto_discovery_link_tag" "image_tag" "javascript_include_tag"
  861.      "stylesheet_link_tag" "image_path" "path_to_image"" "
  862.      "javascript_path" "path_to_javascript" "register_javascript_expansion"
  863.      "register_javascript_include_default" "register_stylesheet_expansion"
  864.      "stylesheet_path" "path_to_stylesheet" "atom_feed" "entry" "updated"
  865.      "benchmark" "cache" "capture" "content_for" "distance_of_time_in_words"
  866.      "distance_of_time_in_words_to_now" "time_ago_in_words" "date_select"
  867.      "datetime_select" "time_select" "select_date" "select_datetime"
  868.      "select_day" "select_hour" "select_minute" "select_month" "select_second"
  869.      "select_time" "select_year" "debug"
  870.      "check_box" "fields_for" "file_field" "form_for" "hidden_field"
  871.      "label" "password_field" "radio_button" "text_area" "text_field"
  872.      "check_box_tag" "field_set_tag" "file_field_tag" "form_tag"
  873.      "hidden_field_tag" "image_submit_tag" "label_tag" "password_field_tag"
  874.      "radio_button_tag" "select_tag" "submit_tag" "text_area_tag"
  875.      "text_field_tag"
  876.      "collection_select" "country_options_for_select" "country_select"
  877.      "option_groups_from_collection_for_select" "options_for_select"
  878.      "options_from_collection_for_select" "select"
  879.      "time_zone_options_for_select"
  880.      "time_zone_select" "button_to_function" "define_javascript_functions"
  881.      "escape_javascript" "javascript_tag" "link_to_function"" "
  882.      "number_to_currency" "number_to_human_size" "number_to_percentage"
  883.      "number_to_phone" "number_with_delimiter" "number_with_precision"
  884.      "evaluate_remote_response" "form_remote_for" "form_remote_tag"
  885.      "link_to_remote" "observe_field" "observe_field"
  886.      "periodically_call_remote"
  887.      "remote_form_for" "remote_function" "submit_to_remote" "update_page"
  888.      "update_page_tag" "dom_class" "dom_id" "partial_path" "sanitize"
  889.      "sanitize_css" "strip_links" "strip_tags"
  890.      "cdata_section" "content_tag" "escape_once" "tag"
  891.      "auto_link" "concat" "cycle" "excerpt" "highlight" "markdown" "pluralize"
  892.      "reset_cycle" "simple_format" "textilize" "textilize_without_paragraph"
  893.      "truncate" "word_wrap" "button_to" "current_page?" "link_to" "link_to_if"
  894.      "link_to_unless" "link_to_unless_current" "mail_to" "url_for"
  895.  
  896.      ))
  897.   "ERB builtins.")
  898.  
  899. (defvar web-mode-asp-constants
  900.   (regexp-opt
  901.    (append web-mode-extra-asp-constants
  902.            '("adAsyncExecute" "adAsyncFetch" "adAsyncFetchNonBlocking" "adCmdFile" "adCmdStoredProc" "adCmdTable" "adCmdTableDirect" "adCmdText" "adCmdUnknown"
  903.              "adCmdUnspecified" "adExecuteNoRecords" "adExecuteRecord" "adExecuteStream" "adLockBatchOptimistic" "adLockOptimistic" "adLockPessimistic"
  904.              "adLockReadOnly" "adLockUnspecified" "adOpenDynamic" "adOpenForwardOnly" "adOpenKeyset" "adOpenStatic" "adOpenUnspecified" "adOptionUnspecified"
  905.              "Empty" "Nothing" "Null" "True" "False"
  906.              "vbBack" "vbCr" "vbCrLf" "vbFormFeed" "vbLf" "vbNewLine" "vbNullChar" "vbNullString" "vbObjectError" "vbScript" "vbTab" "vbVerticalTab")))
  907.   "ASP constants.")
  908.  
  909. (defvar web-mode-asp-keywords
  910.   (regexp-opt
  911.    (append web-mode-extra-asp-keywords
  912.            '("Abs" "And" "Array" "Asc" "Atn"
  913.              "CBool" "CByte" "CCur" "CDate" "CDbl" "CInt" "CLng" "CSng" "CStr"
  914.              "Call" "Case" "Chr" "Class" "Const" "Cos" "CreateObject"
  915.              "Date" "DateAdd" "DateDiff" "DatePart" "DateSerial" "DateValue"
  916.              "Day" "Dim" "Do"
  917.              "Each" "Else" "ElseIf" "End" "Erase" "Err" "Eval" "Exit" "Exp"
  918.              "Explicit"
  919.              "Filter" "Fix" "For" "FormatCurrency" "FormatDateTime"
  920.              "FormatNumber" "FormatPercent" "Function"
  921.              "GetLocale" "GetObject" "GetRef" "Hex" "Hour"
  922.              "If" "In" "InStr" "InStrRev" "InputBox" "Int" "IsArray" "IsDate"
  923.              "IsEmpty" "IsNull" "IsNumeric" "IsObject" "Join"
  924.              "LBound" "LCase" "LTrim" "Language" "Left" "Len" "Let"
  925.              "LoadPicture" "Log" "Loop"
  926.              "Mid" "Minute" "Month" "MonthName" "MsgBox"
  927.              "New" "Next" "Not" "Now"
  928.              "Oct" "On" "Option" "Or" "Preserve" "Private" "Public"
  929.              "RGB" "RTrim" "Redim" "Rem" "Replace" "Right" "Rnd" "Round"
  930.              "ScriptEngine" "ScriptEngineBuildVersion"
  931.              "ScriptEngineMajorVersion" "ScriptEngineMinorVersion"
  932.              "Second" "Select" "Set" "SetLocale" "Sgn" "Sin" "Space" "Split"
  933.              "Sqr" "StrComp" "StrReverse" "String" "Sub"
  934.              "Tan" "Then" "Time" "TimeSerial" "TimeValue" "Timer" "To" "Trim"
  935.              "TypeName"
  936.              "UBound" "UCase" "Until" "VarType"
  937.              "Weekday" "WeekdayName" "Wend" "With" "While" "Year")))
  938.   "ASP keywords.")
  939.  
  940. (defvar web-mode-asp-types
  941.   (regexp-opt
  942.    (append web-mode-extra-asp-types
  943.            '("Application" "ASPError" "Request" "Response" "Server" "Session")))
  944.   "ASP types.")
  945.  
  946. (defvar web-mode-aspx-keywords
  947.   (regexp-opt
  948.    (append web-mode-extra-aspx-keywords
  949.            '("case" "catch" "do" "else" "end"
  950.              "for" "foreach" "function"
  951.              "if" "in" "include"
  952.              "new" "package" "page" "return"
  953.              "tag" "throw" "throws" "try" "while")))
  954.   "ASP.Net keywords.")
  955.  
  956. (defvar web-mode-smarty-keywords
  957.   (regexp-opt
  958.    '("as"))
  959.   "Smarty keywords.")
  960.  
  961. (defvar web-mode-velocity-keywords
  962.   (eval-when-compile
  963.     (regexp-opt
  964.      '("in")))
  965.   "Velocity keywords.")
  966.  
  967. (defvar web-mode-freemarker-keywords
  968.   (eval-when-compile
  969.     (regexp-opt
  970.      '("as" "list"))))
  971.  
  972. (defvar web-mode-go-keywords
  973.   (eval-when-compile
  974.     (regexp-opt
  975.      '("define" "else" "end" "if" "pipeline" "range" "template" "with"))))
  976.  
  977. (defvar web-mode-go-functions
  978.   (eval-when-compile
  979.     (regexp-opt
  980.      '("and" "call" "html" "index" "js" "len" "not" "or"
  981.        "print" "printf" "println" "urlquery")))
  982.   "Go functions.")
  983.  
  984. (defvar web-mode-closure-keywords
  985.   (eval-when-compile
  986.     (regexp-opt
  987.      '("in" "and" "not" "or")
  988.      ))
  989.   "Closure keywords")
  990.  
  991. (defvar web-mode-django-keywords
  992.   (eval-when-compile
  993.     (regexp-opt
  994.      '("and" "as" "autoescape" "block" "blocktrans" "break"
  995.        "cache" "call" "comment" "context" "continue" "csrf_token" "cycle"
  996.        "debug" "do"
  997.        "embed" "empty" "else" "elseif" "elif" "endautoescape" "endblock" "endcomment"
  998.        "endcache" "endcall" "endembed" "endfilter" "endfor" "endif"
  999.        "endifchanged" "endifequal" "endifnotequal" "endmacro" "endrandom" "endraw"
  1000.        "endsandbox" "endset" "endspaceless" "endtrans" "endverbatim" "endwith"
  1001.        "extends" "filter" "firstof" "flush" "for" "from"
  1002.        "if" "ifchanged" "ifequal" "ifnotequal" "ignore" "import"
  1003.        "in" "include" "is"
  1004.        "load" "macro" "missing" "none" "not" "now" "or" "pluralize"
  1005.        "random" "raw" "regroup" "trans"
  1006.        "sandbox" "set" "spaceless" "ssi" "static" "templatetag" "trans"
  1007.        "use" "url" "var" "verbatim" "widthratio" "with")))
  1008.   "Django keywords.")
  1009.  
  1010. (defvar web-mode-django-types
  1011.   (eval-when-compile
  1012.     (regexp-opt
  1013.      '("null" "empty" "false" "true"
  1014.        ))))
  1015.  
  1016. (defvar web-mode-directives
  1017.   (eval-when-compile
  1018.     (regexp-opt
  1019.      '("include" "page" "taglib"
  1020.        "Assembly" "Control" "Implements" "Import"
  1021.        "Master" "OutputCache" "Page" "Reference" "Register")))
  1022.   "Directives.")
  1023.  
  1024. (defvar web-mode-template-toolkit-keywords
  1025.   (regexp-opt
  1026.    '("block" "call" "case" "catch" "clear" "default" "do"
  1027.      "else" "elsif" "end" "filter" "final" "for"
  1028.      "foreach" "get" "if" "in" "include" "insert" "is" "last"
  1029.      "macro" "meta" "or" "perl" "process" "rawperl" "return"
  1030.      "set" "stop" "switch" "tags" "throw" "try"
  1031.      "unless" "use" "while" "wrapper"))
  1032.   "Template-toolkit keywords")
  1033.  
  1034. (defvar web-mode-javascript-keywords
  1035.   (regexp-opt
  1036.    (append web-mode-extra-javascript-keywords
  1037.            '("break" "case" "catch" "class" "const" "continue"
  1038.              "debugger" "default" "delete" "do" "else" "enum" "eval"
  1039.              "export" "extends" "finally" "for" "function" "if"
  1040.              "implements" "import" "in" "instanceof" "interface" "let"
  1041.              "new" "package" "private" "protected" "public"
  1042.              "return" "static" "super" "switch" "throw"
  1043.              "try" "typeof" "var" "void" "while" "with" "yield"
  1044.              )))
  1045.   "JavaScript keywords.")
  1046.  
  1047. (defvar web-mode-javascript-constants
  1048.   (regexp-opt
  1049.    '("false" "null" "undefined"
  1050.      "Infinity" "NaN"
  1051.      "true" "arguments" "this"
  1052.      ))
  1053.   "JavaScript constants.")
  1054.  
  1055.  
  1056. (defvar web-mode-razor-keywords
  1057.   (regexp-opt
  1058.    (append web-mode-extra-razor-keywords
  1059.            '("false" "true" "foreach" "if" "in" "var" "for" "display")))
  1060.   "Razor keywords.")
  1061.  
  1062. (defvar web-mode-dust-font-lock-keywords
  1063.   (list
  1064.    '("/?}\\|{[#/:?@><+^]?" 0 'web-mode-preprocessor-face)
  1065.    '("{[#:/?@><+^]\\([[:alpha:]_]+\\)" 1 'web-mode-block-control-face)
  1066.    '(":\\([[:alpha:]]+\\)" 1 'web-mode-keyword-face)
  1067.    '("\\<\\([[:alpha:]_]+=\\)\\(\"[^\"]*\"\\|[[:alnum:]_]*\\)"
  1068.      (1 'web-mode-block-attr-name-face)
  1069.      (2 'web-mode-block-attr-value-face))
  1070.    '("\\\([[:alnum:]_]+\\)" 0 'web-mode-variable-name-face)
  1071.    ))
  1072.  
  1073. (defvar web-mode-template-toolkit-font-lock-keywords
  1074.   (list
  1075.    '("\\[%[-+]?\\|[-+=]?%\\]" 0 'web-mode-preprocessor-face)
  1076.    (cons (concat "\\<\\(" web-mode-template-toolkit-keywords "\\)\\>")
  1077.          '(1 'web-mode-keyword-face))
  1078.    '("\\\([[:alpha:]][[:alnum:]_]+\\)[ ]?(" 1 'web-mode-function-name-face)
  1079.    '("\\\([[:alpha:]][[:alnum:]_]+\\)" 0 'web-mode-variable-name-face)
  1080.    ))
  1081.  
  1082. (defvar web-mode-smarty-font-lock-keywords
  1083.   (list
  1084.    '("}\\|{/?" 0 'web-mode-preprocessor-face)
  1085.    (cons (concat "[ ]\\(" web-mode-smarty-keywords "\\)[ ]") '(1 'web-mode-keyword-face))
  1086.    '("{/?\\([[:alpha:]_]+\\)" 1 'web-mode-block-control-face)
  1087.    '("\\<\\([$]\\)\\([[:alnum:]_]+\\)" (1 nil) (2 'web-mode-variable-name-face))
  1088.    '("\\<\\(\\sw+\\)[ ]?(" 1 'web-mode-function-name-face)
  1089.    '(" \\(\\sw+[ ]?=\\)" 1 'web-mode-param-name-face)
  1090.    '(" \\(\\sw+\\)[ }]" 1 'web-mode-param-name-face)
  1091.    '("|\\([[:alnum:]_]+\\)" 1 'web-mode-function-name-face)
  1092.    '("\\(->\\)\\(\\sw+\\)" (1 nil) (2 'web-mode-variable-name-face))
  1093.    '("[.]\\([[:alnum:]_-]+\\)[ ]?(" (1 'web-mode-function-name-face))
  1094.    '("[.]\\([[:alnum:]_]+\\)" (1 'web-mode-variable-name-face))
  1095.    '("#\\([[:alnum:]_]+\\)#" 1 'web-mode-variable-name-face)
  1096.    ))
  1097.  
  1098. (defvar web-mode-velocity-font-lock-keywords
  1099.   (list
  1100.    '("\\([#]\\)\\([[:alpha:]]+\\)\\>"
  1101.      (1 'web-mode-preprocessor-face)
  1102.      (2 'web-mode-block-control-face))
  1103.    (cons (concat "[ ]\\(" web-mode-velocity-keywords "\\)[ ]") '(1 'web-mode-keyword-face t t))
  1104.    '("#macro([ ]*\\([[:alpha:]]+\\)[ ]+" 1 'web-mode-function-name-face)
  1105.    '("[.]\\([[:alnum:]_-]+\\)" 1 'web-mode-variable-name-face)
  1106.    '("\\<\\($[!]?[{]?\\)\\([[:alnum:]_-]+\\)[}]?" (1 nil) (2 'web-mode-variable-name-face))
  1107.    ))
  1108.  
  1109. (defvar web-mode-django-expr-font-lock-keywords
  1110.   (list
  1111.    '("\\({{\\)[ ]?" 1 'web-mode-preprocessor-face)
  1112.    '("[ ]?\\(}}\\)" 1 'web-mode-preprocessor-face)
  1113.    '("|[ ]?\\([[:alpha:]]+\\)\\>" 1 'web-mode-function-name-face)
  1114.    (cons (concat "\\<\\(" web-mode-django-types "\\)\\>") '(1 'web-mode-type-face))
  1115.    '("\\<\\([[:alpha:]_]+\\)[ ]?(" 1 'web-mode-function-name-face)
  1116.    '("[[:alnum:]_]+" 0 'web-mode-variable-name-face)
  1117.    )
  1118.   "Font lock keywords for dtl expr")
  1119.  
  1120. (defvar web-mode-django-code-font-lock-keywords
  1121.   (list
  1122.    '("{%\\|%}" 0 'web-mode-preprocessor-face)
  1123.    (cons (concat "\\<\\(" web-mode-django-keywords "\\)\\>") '(1 'web-mode-keyword-face))
  1124.    (cons (concat "\\<\\(" web-mode-django-types "\\)\\>") '(1 'web-mode-type-face))
  1125.    '("|[ ]?\\([[:alpha:]_]+\\)\\>" 1 'web-mode-function-name-face)
  1126. ;;   (cons (concat "|[ ]?\\(" web-mode-django-filters "\\)\\>") '(1 'web-mode-function-name-face t t))
  1127.    '("\\<\\([[:alpha:]_]+\\)[ ]?(" 1 'web-mode-function-name-face)
  1128.    '("[[:alnum:]_]+" 0 'web-mode-variable-name-face)
  1129.    ))
  1130.  
  1131. (defvar web-mode-ctemplate-font-lock-keywords
  1132.   (list
  1133.    '("${{\\|{{[>#/{%^&]?\\|[}]?}}" 0 'web-mode-preprocessor-face)
  1134.    '("{{[#/>][ ]*\\([[:alnum:]_]+\\)" 1 'web-mode-block-control-face)
  1135.    '("[[:alnum:]_]" 0 'web-mode-variable-name-face)
  1136.    '("[ ]+\\([[:alnum:]_]+=\\)" 1 'web-mode-param-name-face t t)
  1137.    '("[:=]\\([[:alpha:]_]+\\)" 1 'web-mode-function-name-face t t)
  1138.    ))
  1139.  
  1140. (defvar web-mode-razor-font-lock-keywords
  1141.   (list
  1142.    '("@" 0 'web-mode-preprocessor-face)
  1143.    (cons (concat "\\<\\(" web-mode-razor-keywords "\\)\\>") '(1 'web-mode-keyword-face t t))
  1144.    '("\\<\\([[:alnum:]_]+\\)[ ]?(" 1 'web-mode-function-name-face)
  1145.    '("<\\([[:alnum:]_]+\\)>" 1 'web-mode-type-face)
  1146.    '("\\<\\([[:alnum:].]+\\)[ ]+[{[:alpha:]]+" 1 'web-mode-type-face)
  1147.    '("[[:alnum:]_]+" 0 'web-mode-variable-name-face)
  1148.    ))
  1149.  
  1150. (defvar web-mode-closure-font-lock-keywords
  1151.   (list
  1152.    '("{/?\\|/?}" 0 'web-mode-preprocessor-face)
  1153.    '("{/?\\([[:alpha:]]+\\)" 1 'web-mode-block-control-face)
  1154.    '("{param[ ]+\\([[:alnum:]]+\\)" 1 'web-mode-symbol-face)
  1155.    '("\\<\\(true\\|false\\|null\\)\\>" 1 'web-mode-type-face)
  1156.    (cons (concat "\\<\\(" web-mode-closure-keywords "\\)\\>") '(1 'web-mode-keyword-face))
  1157.    '("{\\(alias\\|call\\|delcall\\|delpackage\\|deltemplate\\|namespace\\|template\\)[ ]+\\([[:alnum:].]+\\)" 2 'web-mode-constant-face)
  1158.    '("\\(allowemptydefault\\|data\\|desc\\|meaning\\|autoescape\\|private\\|variant\\)=" 0 'web-mode-block-attr-name-face)
  1159.    '("|\\([[:alpha:]]+\\)" 1 'web-mode-function-name-face)
  1160.    '("\\<\\([[:alnum:]]+\\)[ ]?(" 1 'web-mode-function-name-face)
  1161.    '("$\\([[:alnum:]._]+\\)" 1 'web-mode-variable-name-face)
  1162.    ))
  1163.  
  1164. (defvar web-mode-go-font-lock-keywords
  1165.   (list
  1166.    '("{{\\|}}" 0 'web-mode-preprocessor-face)
  1167.    '("{{\\([[:alpha:]]+\\)" 1 'web-mode-block-control-face)
  1168.    (cons (concat "\\<\\(" web-mode-go-keywords "\\)\\>") '(1 'web-mode-keyword-face))
  1169.    (cons (concat "\\<\\(" web-mode-go-functions "\\)\\>") '(1 'web-mode-function-name-face))
  1170.    '("[$.]\\([[:alnum:]_]+\\)" 1 'web-mode-variable-name-face t t)
  1171.  
  1172.    ))
  1173.  
  1174. (defvar web-mode-expression-font-lock-keywords
  1175.   (list
  1176.    '("<%\\$\\|%>" 0 'web-mode-preprocessor-face)
  1177.    '("[[:alpha:]_]" 0 'web-mode-variable-name-face)
  1178.    ))
  1179.  
  1180. (defvar web-mode-selector-font-lock-keywords
  1181.   (list
  1182.    (cons (concat "@\\(" web-mode-css-at-rules "\\)\\>") '(1 'web-mode-css-at-rule-face))
  1183.    '("\\<\\(all\|braille\\|embossed\\|handheld\\|print\\|projection\\|screen\\|speech\\|tty\\|tv\\|and\\|or\\)\\>" 1 'web-mode-keyword-face)
  1184.    (cons (concat ":\\(" web-mode-css-pseudo-classes "\\)\\>") '(1 'web-mode-css-pseudo-class-face))
  1185.    '("[[:alnum:]-]+" 0 'web-mode-css-selector-face)
  1186.    '("\\[.*?\\]\\|(.*?)" 0 nil t t)
  1187.    '("url(\\(.+?\\))" 1 'web-mode-string-face)
  1188.    ))
  1189.  
  1190. (defvar web-mode-declaration-font-lock-keywords
  1191.   (list
  1192.    (cons (concat "@\\(" web-mode-css-at-rules "\\)\\>") '(1 'web-mode-css-at-rule-face))
  1193.    '("url(\\([^)]+\\)" 1 'web-mode-string-face)
  1194.    '("\\([[:alpha:]-]\\{3,\\}\\)[ ]?:" 1 'web-mode-css-property-name-face)
  1195.    '("\\([[:alpha:]-]+\\)[ ]?(" 1 'web-mode-css-function-face)
  1196.    '("#[[:alnum:]]\\{1,6\\}" 0 'web-mode-css-color-face t t)
  1197.    '("![ ]?important" 0 'web-mode-css-priority-face t t)
  1198.    ))
  1199.  
  1200. (defvar web-mode-html-font-lock-keywords
  1201.   (list
  1202.    '("</?[[:alnum:]]+\\|>" 0 'web-mode-html-tag-face)
  1203.    '(" \\([[:alnum:]-]+=\\)\\(\"[^\"]+\"\\)"
  1204.      (1 'web-mode-html-attr-name-face)
  1205.      (2 'web-mode-html-attr-value-face))
  1206.    ))
  1207.  
  1208. (defvar web-mode-javascript-font-lock-keywords
  1209.   (list
  1210.    (cons (concat "\\<\\(" web-mode-javascript-keywords "\\)\\>") '(0 'web-mode-keyword-face))
  1211.    (cons (concat "\\<\\(" web-mode-javascript-constants "\\)\\>") '(0 'web-mode-constant-face))
  1212.    '("\\<\\(new\\|instanceof\\) \\([[:alnum:]_.]+\\)\\>" 2 'web-mode-type-face)
  1213.    '("\\<\\([[:alnum:]_]+\\):[ ]*function[ ]*(" 1 'web-mode-function-name-face)
  1214.    '("\\<function[ ]+\\([[:alnum:]_]+\\)" 1 'web-mode-function-name-face)
  1215.    '("\\<\\(var\\)\\>[ ]+"
  1216.      (1 'web-mode-keyword-face)
  1217.      ("\\([[:alnum:]_]+\\)\\([ ]*=[^,;]*\\)?[,; ]" nil nil (1 'web-mode-variable-name-face)))
  1218.    '("\\<\\(function\\)[ ]*("
  1219.      (1 'web-mode-keyword-face)
  1220.      ("\\([[:alnum:]_]+\\)\\([ ]*=[^,)]*\\)?[,)]" nil nil (1 'web-mode-variable-name-face)))
  1221.    '("\\([[:alnum:]]+\\):" 1 'web-mode-variable-name-face)
  1222.    '("/[^/]+/" 0 'web-mode-string-face)
  1223.    ))
  1224.  
  1225. (defvar web-mode-underscore-font-lock-keywords
  1226.   (list
  1227.    '("<%[-=]?\\|%>" 0 'web-mode-preprocessor-face)
  1228.    (cons (concat "\\<\\(" web-mode-javascript-keywords "\\)\\>") '(0 'web-mode-keyword-face))
  1229.    '("\\<\\(_\.[[:alpha:]]+\\)(" 1 'web-mode-function-name-face)
  1230.    '("\\<new \\([[:alnum:]_.]+\\)\\>" 1 'web-mode-type-face)
  1231.    '("\\<\\([[:alnum:]_]+\\):[ ]*function[ ]*(" 1 'web-mode-function-name-face)
  1232.    '("\\<\\(var\\)\\>[ ]+\\([[:alnum:]_]+\\)"
  1233.      (1 'web-mode-keyword-face)
  1234.      (2 'web-mode-variable-name-face))
  1235.    ))
  1236.  
  1237. (defvar web-mode-asp-font-lock-keywords
  1238.   (list
  1239.    '("<%=?\\|%>" 0 'web-mode-preprocessor-face)
  1240.    (cons (concat "\\<\\(" web-mode-asp-keywords "\\)\\>")
  1241.          '(0 'web-mode-keyword-face))
  1242.    (cons (concat "\\<\\(" web-mode-asp-types "\\)\\>")
  1243.          '(0 'web-mode-type-face))
  1244.    (cons (concat "\\<\\(" web-mode-asp-constants "\\)\\>")
  1245.          '(0 'web-mode-constant-face))
  1246.    '("\\(Class\\|new\\) \\([[:alnum:]_]+\\)" 2 'web-mode-type-face)
  1247.    '("Const \\([[:alnum:]_]+\\)" 1 'web-mode-constant-face)
  1248.    '("\\<dim\\>"
  1249.      (0 'web-mode-keyword-face)
  1250.      ("[[:alnum:]_]+" nil nil (0 'web-mode-variable-name-face)))
  1251.    '("\\<\\(public\\|private\\|sub\\|function\\)\\> \\([[:alnum:]_]+\\)[ ]*("
  1252.      2 'web-mode-function-name-face)
  1253.    '("\\<\\(public\\|private\\|dim\\)\\> \\([[:alnum:]_]+\\)"
  1254.      2 'web-mode-variable-name-face)
  1255.    ))
  1256.  
  1257. (defvar web-mode-aspx-font-lock-keywords
  1258.   (list
  1259.    '("<%[:=#]?\\|%>" 0 'web-mode-preprocessor-face)
  1260.    (cons (concat "\\<\\(" web-mode-aspx-keywords "\\)\\>") '(0 'web-mode-keyword-face))
  1261.    '("\\<\\([[:alnum:].]+\\)[ ]+[[:alpha:]]+" 1 'web-mode-type-face)
  1262.    ))
  1263.  
  1264. ;;Unified Expression Language
  1265. (defvar web-mode-uel-font-lock-keywords
  1266.   (list
  1267.    '("[$#{]{\\|}" 0 'web-mode-preprocessor-face)
  1268.    '("\\([[:alpha:]_]+\\)[ ]?(" 1 'web-mode-function-name-face)
  1269.    '("[[:alpha:]_]" 0 'web-mode-variable-name-face)
  1270.    ))
  1271.  
  1272. (defvar web-mode-freemarker-square-font-lock-keywords
  1273.   (list
  1274.    '("\\[/?[#@]\\|/?>\\|/?\\]" 0 'web-mode-preprocessor-face)
  1275.    '("\\[/?[#@]\\([[:alpha:]_.]*\\)" 1 'web-mode-block-control-face)
  1276.    '("#\\(macro\\|function\\) \\([[:alpha:]]+\\)" 2 'web-mode-function-name-face)
  1277.    (cons (concat "\\<\\(" web-mode-freemarker-keywords "\\)\\>") '(1 'web-mode-keyword-face))
  1278.    '("\\<\\([[:alnum:]._]+\\)[ ]?(" 1 'web-mode-function-name-face)
  1279.    '("[[:alpha:]]\\([[:alnum:]_]+\\)?" 0 'web-mode-variable-name-face)
  1280.    ))
  1281.  
  1282. (defvar web-mode-freemarker-font-lock-keywords
  1283.   (list
  1284.    '("</?[#@]\\|/?>\\|/?>" 0 'web-mode-preprocessor-face)
  1285.    '("</?[#@]\\([[:alpha:]_.]*\\)" 1 'web-mode-block-control-face)
  1286.    '("#\\(macro\\|function\\) \\([[:alpha:]]+\\)" 2 'web-mode-function-name-face)
  1287.    (cons (concat "\\<\\(" web-mode-freemarker-keywords "\\)\\>") '(1 'web-mode-keyword-face))
  1288.    '("\\<\\([[:alnum:]._]+\\)[ ]?(" 1 'web-mode-function-name-face)
  1289.    '("[[:alpha:]]\\([[:alnum:]_]+\\)?" 0 'web-mode-variable-name-face)
  1290.    ))
  1291.  
  1292. ;;TODO : definir web-mode-block-attr-name-face et web-mode-block-attr-name-face
  1293. (defvar web-mode-jsp-tag-font-lock-keywords
  1294.   (list
  1295.    '("</?\\|/?>" 0 'web-mode-preprocessor-face)
  1296.    '("</?\\([[:alpha:]]+:[[:alpha:]]+\\)" 1 'web-mode-block-control-face)
  1297.    '("\\<\\([[:alpha:]]+=\\)\\(\"[^\"]*\"\\)"
  1298.      (1 'web-mode-block-attr-name-face t t)
  1299.      (2 'web-mode-block-attr-value-face t t))
  1300.    ))
  1301.  
  1302. (defvar web-mode-jsp-font-lock-keywords
  1303.   (list
  1304.    '("-?%>\\|<%\\(!\\|=\\|#=\\)?" 0 'web-mode-preprocessor-face)
  1305.    '("\\(throws\\|new\\|extends\\)[ ]+\\([[:alnum:].]+\\)" 2 'web-mode-type-face)
  1306.    (cons (concat "\\<\\(" web-mode-jsp-keywords "\\)\\>") '(0 'web-mode-keyword-face))
  1307.    '("\\<\\([[:alnum:]._]+\\)[ ]?(" 1 'web-mode-function-name-face)
  1308.    '("@\\(\\sw*\\)" 1 'web-mode-variable-name-face)
  1309.    '("\\<\\([[:alnum:].]+\\)[ ]+[{[:alpha:]]+" 1 'web-mode-type-face)
  1310.    ))
  1311.  
  1312. (defvar web-mode-directive-font-lock-keywords
  1313.   (list
  1314.    '("<%@\\|%>" 0 'web-mode-preprocessor-face)
  1315.    '("<%@[ ]*\\([[:alpha:]]+\\)[ ]+" 1 'web-mode-block-control-face)
  1316.    '("\\<\\([[:alpha:]]+=\\)\\(\"[^\"]*\"\\)"
  1317.      (1 'web-mode-block-attr-name-face t t)
  1318.      (2 'web-mode-block-attr-value-face t t))
  1319.    ))
  1320.  
  1321. (defvar web-mode-erb-font-lock-keywords
  1322.   (list
  1323.    '("-?%>\\|^%\\|<%[=-]?" 0 'web-mode-preprocessor-face)
  1324.    '("\\(:[[:alnum:]_]+\\)" 1 'web-mode-symbol-face)
  1325.    '("\\([[:alnum:]_]+:\\)[ ]+" 1 'web-mode-symbol-face)
  1326.    (cons (concat "\\<\\(" web-mode-erb-builtins "\\)\\>")
  1327.          '(0 'web-mode-builtin-face))
  1328.    (cons (concat "\\<\\(" web-mode-erb-keywords "\\)\\>")
  1329.          '(0 'web-mode-keyword-face))
  1330.    '("\\<\\(self\\|true\\|false\\|nil\\)\\>" 0 'web-mode-variable-name-face)
  1331.    '("[@$]@?\\([[:alnum:]_]+\\)" 0 'web-mode-variable-name-face)
  1332.    '("class[ ]+\\([[:alnum:]_]+\\)" 1 'web-mode-type-face)
  1333.    '("def[ ]+\\([[:alnum:]_]+\\)" 1 'web-mode-function-name-face)
  1334.    '("\\(?:\\_<\\|::\\)\\([A-Z]+[[:alnum:]_]+\\)"
  1335.      1 (unless (eq ?\( (char-after)) 'web-mode-type-face))
  1336.    '("/[^/]+/" 0 'web-mode-string-face)
  1337.    ))
  1338.  
  1339. (defvar web-mode-python-font-lock-keywords
  1340.   (list
  1341.    '("<\\?\\|\\?>" 0 'web-mode-preprocessor-face)
  1342.    (cons (concat "\\<\\(" web-mode-python-keywords "\\)\\>") '(0 'web-mode-keyword-face))
  1343.    ))
  1344.  
  1345. (defvar web-mode-php-font-lock-keywords
  1346.   (list
  1347.    '("<\\?\\(php\\|=\\)?\\|\\?>" 0 'web-mode-preprocessor-face)
  1348.    (cons (concat "\\<\\(" web-mode-php-keywords "\\)\\>") '(0 'web-mode-keyword-face))
  1349.    (cons (concat "(\\<\\(" web-mode-php-types "\\)\\>") '(1 'web-mode-type-face))
  1350.    (cons (concat "\\<\\(" web-mode-php-constants "\\)\\>") '(0 'web-mode-constant-face))
  1351.    '("\\<\\(\\sw+\\)[ ]?(" 1 'web-mode-function-name-face)
  1352.    '("[[:alnum:]_][ ]?::[ ]?\\([[:alnum:]_]+\\)" 1 'web-mode-constant-face)
  1353.    '("->[ ]?\\([[:alnum:]_]+\\)" 1 'web-mode-variable-name-face)
  1354.    '("\\<\\([[:alnum:]_]+\\)[ ]?::" 1 'web-mode-type-face)
  1355.    '("\\<\\(instanceof\\|class\\|extends\\|new\\)[ ]+\\([[:alnum:]_]+\\)" 2 'web-mode-type-face)
  1356.    '("\\<\\([$]\\)\\([[:alnum:]_]*\\)" (1 nil) (2 'web-mode-variable-name-face))
  1357.    ))
  1358.  
  1359. (defvar web-mode-blade-font-lock-keywords
  1360.   (append
  1361.    (list
  1362.     '("{{\\|}}" 0 'web-mode-preprocessor-face)
  1363.     '("\\(@\\)\\([[:alpha:]_]+\\)"
  1364.       (1 'web-mode-preprocessor-face)
  1365.       (2 'web-mode-block-control-face)))
  1366.    web-mode-php-font-lock-keywords))
  1367.  
  1368. (defvar web-mode-syntax-table
  1369.   (let ((table (make-syntax-table)))
  1370.     (modify-syntax-entry ?_ "w" table)
  1371.     table)
  1372.   "Syntax table in use in web-mode buffers.")
  1373.  
  1374. (defvar web-mode-map
  1375.   (let ((map (make-sparse-keymap)))
  1376.  
  1377.     (define-key map [menu-bar wm] (cons "Web-Mode" (make-sparse-keymap)))
  1378.     (define-key map [menu-bar wm blk] (cons "Block" (make-sparse-keymap)))
  1379.     (define-key map [menu-bar wm tag] (cons "Html Tag" (make-sparse-keymap)))
  1380.     (define-key map [menu-bar wm elt] (cons "Html Element" (make-sparse-keymap)))
  1381.  
  1382.     (define-key map [menu-bar wm sep-1] '(menu-item "--"))
  1383.     (define-key map [menu-bar wm blk blk-sel] '(menu-item "Select" web-mode-block-select))
  1384.     (define-key map [menu-bar wm blk blk-kill] '(menu-item "Kill" web-mode-block-kill))
  1385.     (define-key map [menu-bar wm blk blk-next] '(menu-item "Next" web-mode-block-next))
  1386.     (define-key map [menu-bar wm blk blk-prev] '(menu-item "Previous" web-mode-block-previous))
  1387.     (define-key map [menu-bar wm blk blk-end] '(menu-item "End" web-mode-block-beginning))
  1388.     (define-key map [menu-bar wm blk blk-beg] '(menu-item "Beginning" web-mode-block-beginning))
  1389.     (define-key map [menu-bar wm tag tag-sel] '(menu-item "Select" web-mode-tag-select))
  1390.     (define-key map [menu-bar wm tag tag-match] '(menu-item "Match" web-mode-tag-match))
  1391.     (define-key map [menu-bar wm tag tag-next] '(menu-item "Next" web-mode-tag-next))
  1392.     (define-key map [menu-bar wm tag tag-prev] '(menu-item "Previous" web-mode-tag-previous))
  1393.     (define-key map [menu-bar wm tag tag-end] '(menu-item "End" web-mode-tag-beginning))
  1394.     (define-key map [menu-bar wm tag tag-beg] '(menu-item "Beginning" web-mode-tag-beginning))
  1395.     (define-key map [menu-bar wm elt elt-in] '(menu-item "Inner Content" web-mode-element-content-select))
  1396.     (define-key map [menu-bar wm elt elt-parent] '(menu-item "Parent" web-mode-element-parent))
  1397.     (define-key map [menu-bar wm elt elt-sel] '(menu-item "Select" web-mode-element-select))
  1398.     (define-key map [menu-bar wm elt elt-ren] '(menu-item "Rename" web-mode-element-rename))
  1399.     (define-key map [menu-bar wm elt elt-dup] '(menu-item "Clone" web-mode-element-clone))
  1400.     (define-key map [menu-bar wm elt elt-close] '(menu-item "Close" web-mode-element-close))
  1401.     (define-key map [menu-bar wm elt elt-trav] '(menu-item "Traverse DOM" web-mode-element-traverse))
  1402.     (define-key map [menu-bar wm elt elt-child] '(menu-item "Child" web-mode-element-child))
  1403.     (define-key map [menu-bar wm elt elt-del] '(menu-item "Kill" web-mode-element-kill))
  1404.     (define-key map [menu-bar wm elt elt-next] '(menu-item "Next" web-mode-element-next))
  1405.     (define-key map [menu-bar wm elt elt-prev] '(menu-item "Previous" web-mode-element-previous))
  1406.     (define-key map [menu-bar wm elt elt-end] '(menu-item "End" web-mode-element-end))
  1407.     (define-key map [menu-bar wm elt elt-beg] '(menu-item "Beginning" web-mode-element-beginning))
  1408.     (define-key map [menu-bar wm err] '(menu-item "Show error(s)" web-mode-errors-show))
  1409.     (define-key map [menu-bar wm fold] '(menu-item "Fold/Unfold" web-mode-fold-or-unfold))
  1410.     (define-key map [menu-bar wm indent] '(menu-item "Indent buffer" web-mode-buffer-indent))
  1411.     (define-key map [menu-bar wm nav] '(menu-item "Tag/Block navigation" web-mode-tag-match))
  1412.     (define-key map [menu-bar wm expand] '(menu-item "Mark and Expand" web-mode-mark-and-expand))
  1413.     (define-key map [menu-bar wm space] '(menu-item "Toggle whitespaces" web-mode-whitespaces-show))
  1414.     (define-key map [menu-bar wm xpath] '(menu-item "XPath" web-mode-xpath))
  1415.     (define-key map [menu-bar wm snippet] '(menu-item "Insert snippet" web-mode-snippet-insert))
  1416.     (define-key map [menu-bar wm entities] '(menu-item "Replace HTML entities" web-mode-entities-replace))
  1417.  
  1418.     (define-key map (kbd "C-;")       'web-mode-comment-or-uncomment)
  1419.     (define-key map (kbd "M-;")       'web-mode-comment-or-uncomment)
  1420.  
  1421.     (define-key map (kbd "C-c C-d")   'web-mode-errors-show)
  1422.     (define-key map (kbd "C-c C-f")   'web-mode-fold-or-unfold)
  1423.     (define-key map (kbd "C-c C-i")   'web-mode-buffer-indent)
  1424.     (define-key map (kbd "C-c C-m")   'web-mode-mark-and-expand)
  1425.     (define-key map (kbd "C-c C-n")   'web-mode-tag-match)
  1426.     (define-key map (kbd "C-c C-r")   'web-mode-entities-replace)
  1427.     (define-key map (kbd "C-c C-s")   'web-mode-snippet-insert)
  1428.     (define-key map (kbd "C-c C-x")   'web-mode-xpath)
  1429.     (define-key map (kbd "C-c C-w")   'web-mode-whitespaces-show)
  1430.  
  1431.     (define-key map (kbd "C-c /")     'web-mode-element-close)
  1432.     (define-key map (kbd "C-c <")     'web-mode-element-beginning)
  1433.     (define-key map (kbd "C-c >")     'web-mode-element-end)
  1434.  
  1435.     (define-key map (kbd "C-c C-b b") 'web-mode-block-beginning)
  1436.     (define-key map (kbd "C-c C-b e") 'web-mode-block-end)
  1437.     (define-key map (kbd "C-c C-b k") 'web-mode-block-kill)
  1438.     (define-key map (kbd "C-c C-b n") 'web-mode-block-next)
  1439.     (define-key map (kbd "C-c C-b p") 'web-mode-block-previous)
  1440.     (define-key map (kbd "C-c C-b s") 'web-mode-block-select)
  1441.  
  1442.     (define-key map (kbd "C-c C-e b") 'web-mode-element-beginning)
  1443.     (define-key map (kbd "C-c C-e c") 'web-mode-element-clone)
  1444.     (define-key map (kbd "C-c C-e d") 'web-mode-element-child)
  1445.     (define-key map (kbd "C-c C-e e") 'web-mode-element-end)
  1446.     (define-key map (kbd "C-c C-e i") 'web-mode-element-content-select)
  1447.     (define-key map (kbd "C-c C-e k") 'web-mode-element-kill)
  1448.     (define-key map (kbd "C-c C-e n") 'web-mode-element-next)
  1449.     (define-key map (kbd "C-c C-e p") 'web-mode-element-previous)
  1450.     (define-key map (kbd "C-c C-e r") 'web-mode-element-rename)
  1451.     (define-key map (kbd "C-c C-e s") 'web-mode-element-select)
  1452.     (define-key map (kbd "C-c C-e t") 'web-mode-element-traverse)
  1453.     (define-key map (kbd "C-c C-e u") 'web-mode-element-parent)
  1454.  
  1455.     (define-key map (kbd "C-c C-t b") 'web-mode-tag-beginning)
  1456.     (define-key map (kbd "C-c C-t e") 'web-mode-tag-end)
  1457.     (define-key map (kbd "C-c C-t m") 'web-mode-tag-match)
  1458.     (define-key map (kbd "C-c C-t n") 'web-mode-tag-next)
  1459.     (define-key map (kbd "C-c C-t p") 'web-mode-tag-previous)
  1460.     (define-key map (kbd "C-c C-t s") 'web-mode-tag-select)
  1461.  
  1462.     ;; compatibility with nxml
  1463.     (define-key map (kbd "M-C-u")     'web-mode-element-parent)
  1464.     (define-key map (kbd "M-C-d")     'web-mode-element-child)
  1465.     (define-key map (kbd "M-C-n")     'web-mode-element-next)
  1466.     (define-key map (kbd "M-C-p")     'web-mode-element-previous)
  1467.  
  1468.     map)
  1469.   "Keymap for `web-mode'.")
  1470.  
  1471. ;;--- compatibility
  1472.  
  1473. (eval-and-compile
  1474.  
  1475.   (defalias 'web-mode-prog-mode
  1476.     (if (fboundp 'prog-mode) 'prog-mode 'fundamental-mode))
  1477.  
  1478.   (if (fboundp 'with-silent-modifications)
  1479.       (defalias 'web-mode-with-silent-modifications 'with-silent-modifications)
  1480.     (defmacro web-mode-with-silent-modifications (&rest body)
  1481.       "For compatibility with Emacs pre 23.3"
  1482.       `(let ((old-modified-p (buffer-modified-p))
  1483.              (inhibit-modification-hooks t)
  1484.              (buffer-undo-list t))
  1485.          (unwind-protect
  1486.              ,@body
  1487.            (set-buffer-modified-p old-modified-p)))))
  1488.  
  1489.   );eval-and-compile
  1490.  
  1491. ;;;###autoload
  1492. (define-derived-mode web-mode web-mode-prog-mode "Web"
  1493.   "Major mode for editing web templates."
  1494.  
  1495.   (make-local-variable 'after-change-functions)
  1496.   (make-local-variable 'font-lock-fontify-buffer-function)
  1497.   (make-local-variable 'font-lock-keywords)
  1498.   (make-local-variable 'font-lock-multiline)
  1499.   (make-local-variable 'font-lock-unfontify-buffer-function)
  1500. ;;  (make-local-variable 'forward-sexp-function)
  1501.   (make-local-variable 'imenu-case-fold-search)
  1502.   (make-local-variable 'imenu-create-index-function)
  1503.   (make-local-variable 'imenu-generic-expression)
  1504.   (make-local-variable 'indent-line-function)
  1505. ;;  (make-local-variable 'indent-tabs-mode)
  1506. ;;  (make-local-variable 'require-final-newline)
  1507.  
  1508.   (make-local-variable 'web-mode-buffer-highlighted)
  1509.   (make-local-variable 'web-mode-comment-style)
  1510.   (make-local-variable 'web-mode-content-type)
  1511.   (make-local-variable 'web-mode-display-table)
  1512.   (make-local-variable 'web-mode-engine)
  1513.   (make-local-variable 'web-mode-block-regexps)
  1514.   (make-local-variable 'web-mode-engine-file-regexps)
  1515.   (make-local-variable 'web-mode-expand-initial-pos)
  1516.   (make-local-variable 'web-mode-expand-previous-state)
  1517.   (make-local-variable 'web-mode-has-any-large-block)
  1518.   (make-local-variable 'web-mode-has-any-large-part)
  1519.   (make-local-variable 'web-mode-hl-line-mode-flag)
  1520.   (make-local-variable 'web-mode-indent-style)
  1521.   (make-local-variable 'web-mode-is-narrowed)
  1522.   (make-local-variable 'web-mode-block-regexp)
  1523.   (make-local-variable 'web-mode-start-tag-overlay)
  1524.   (make-local-variable 'web-mode-end-tag-overlay)
  1525.   (make-local-variable 'web-mode-time)
  1526.  
  1527.   (if (and (fboundp 'global-hl-line-mode)
  1528.            global-hl-line-mode)
  1529.       (setq web-mode-hl-line-mode-flag t))
  1530.  
  1531.   (setq fill-paragraph-function 'web-mode-fill-paragraph
  1532.         font-lock-fontify-buffer-function 'web-mode-scan-buffer
  1533. ;;        forward-sexp-function 'web-mode-forward-sexp
  1534.         ;;          font-lock-keywords-only t
  1535.         font-lock-unfontify-buffer-function 'web-mode-scan-buffer
  1536.         imenu-case-fold-search t
  1537.         imenu-create-index-function 'web-mode-imenu-index
  1538.         indent-line-function 'web-mode-indent-line
  1539.  
  1540. ;;        indent-tabs-mode nil
  1541. ;;        require-final-newline nil
  1542.         )
  1543.  
  1544.   (remove-hook 'after-change-functions 'font-lock-after-change-function t)
  1545.  
  1546.   (when web-mode-enable-current-element-highlight
  1547.     (add-hook 'post-command-hook 'web-mode-hightlight-current-element nil t))
  1548.  
  1549.   (add-hook 'after-change-functions 'web-mode-on-after-change t t)
  1550.  
  1551.   (add-hook 'after-save-hook
  1552.             '(lambda ()
  1553.                (when web-mode-is-scratch
  1554.                  (web-mode-guess-engine-and-content-type)
  1555.                  (web-mode-scan-buffer)
  1556. ;;                 (message "-->%S" (buffer-file-name))
  1557.                  )
  1558.                nil)
  1559.             t t)
  1560.  
  1561.   (cond
  1562.    ((boundp 'yas-after-exit-snippet-hook)
  1563.     (add-hook 'yas-after-exit-snippet-hook
  1564.               '(lambda () (web-mode-buffer-refresh))
  1565.               t t))
  1566.    ((boundp 'yas/after-exit-snippet-hook)
  1567.     (add-hook 'yas/after-exit-snippet-hook
  1568.               '(lambda () (web-mode-buffer-refresh))
  1569.               t t))
  1570.    )
  1571.  
  1572.   (when web-mode-enable-whitespaces
  1573.     (web-mode-whitespaces-on))
  1574.  
  1575.   (web-mode-guess-engine-and-content-type)
  1576.   (web-mode-scan-buffer)
  1577.  
  1578.   )
  1579.  
  1580. (defun web-mode-forward-sexp (&optional arg)
  1581.   "Move forward."
  1582.   (interactive "p")
  1583.   (unless arg (setq arg 1))
  1584.   (cond
  1585.    ((> arg 0)
  1586.     (while
  1587.         (progn
  1588.           (web-mode-tag-next)
  1589.           (> (setq arg (1- arg)) 0))))
  1590.    ((< arg 0)
  1591.     (while
  1592.         (progn
  1593.           (web-mode-tag-previous)
  1594.           (< (setq arg (1+ arg)) 0))))
  1595.    ))
  1596.  
  1597. (defun web-mode-set-engine (engine)
  1598.   "set engine"
  1599.   (interactive
  1600.    (list (completing-read
  1601.           "Engine: "
  1602.           (let (engines elt)
  1603.             (dolist (elt web-mode-engines)
  1604.               (setq engines (append engines (list (car elt)))))
  1605.             engines))))
  1606.   (setq web-mode-content-type "html"
  1607.         web-mode-engine engine)
  1608.   (web-mode-on-engine-setted)
  1609.   (web-mode-scan-buffer)
  1610.   )
  1611.  
  1612. (defun web-mode-on-engine-setted ()
  1613.   "engine setted"
  1614.   (when (string= web-mode-engine "razor")
  1615.     (setq web-mode-enable-block-face t))
  1616.   (cond
  1617.    ((member web-mode-content-type '("css" "javascript" "json"))
  1618.     (setq web-mode-has-any-large-part t))
  1619.    ((member web-mode-content-type '("php"))
  1620.     (setq web-mode-has-any-large-block nil)))
  1621.   (setq web-mode-electric-chars nil)
  1622.   (when (string= web-mode-content-type "html")
  1623.     (unless (string= web-mode-engine "none")
  1624.       (setq web-mode-active-block-regexp
  1625.             (cdr (assoc web-mode-engine web-mode-active-block-regexps)))
  1626.       (setq web-mode-close-block-regexp
  1627.             (cdr (assoc web-mode-engine web-mode-close-block-regexps)))
  1628.       (setq web-mode-engine-control-matcher
  1629.             (intern-soft (concat "web-mode-match-" web-mode-engine "-block")))
  1630.       )
  1631.     (setq web-mode-electric-chars
  1632.           (append '(?\<)
  1633.                   (cdr (assoc web-mode-engine web-mode-block-electric-chars)))
  1634.           )
  1635.     );when
  1636.  
  1637.     (setq elt (assoc web-mode-engine web-mode-block-regexps))
  1638.     (if elt
  1639.         (setq web-mode-block-regexp (cdr elt))
  1640.       (setq web-mode-engine "none")
  1641.       )
  1642.  
  1643.     ;;(message "buffer=%S engine=%S type=%S regexp=%S"
  1644.     ;;          buff-name web-mode-engine web-mode-content-type web-mode-block-regexp)
  1645.  
  1646.     ;;  (message "%S\n%S\n%S\n%S" web-mode-active-block-regexp web-mode-close-block-regexp web-mode-engine-control-matcher web-mode-electric-chars)
  1647.  
  1648.   )
  1649.  
  1650. (defun web-mode-guess-engine-and-content-type ()
  1651.   "Try to guess the server engine and the content type."
  1652.   (let (buff-name elt found)
  1653.     (setq buff-name (buffer-file-name))
  1654.     (unless buff-name (setq buff-name (buffer-name)))
  1655.     (setq web-mode-is-scratch (string= buff-name "*scratch*"))
  1656.     (setq web-mode-content-type nil)
  1657.     (when (boundp 'web-mode-content-types-alist)
  1658.       (setq found nil)
  1659.       (dolist (elt web-mode-content-types-alist)
  1660.         (when (and (not found) (string-match-p (cdr elt) buff-name))
  1661.           (setq web-mode-content-type (car elt)
  1662.                 found t))
  1663.         )
  1664.       )
  1665.     (unless web-mode-content-type
  1666.       (setq found nil)
  1667.       (dolist (elt web-mode-content-types)
  1668.         (when (and (not found) (string-match-p (cdr elt) buff-name))
  1669.           (setq web-mode-content-type (car elt)
  1670.                 found t))
  1671.         )
  1672.       )
  1673.     (when (boundp 'web-mode-engines-alist)
  1674.       (setq found nil)
  1675.       (dolist (elt web-mode-engines-alist)
  1676.         (when (string-match-p (cdr elt) buff-name)
  1677.           (setq web-mode-engine (car elt)))
  1678.         )
  1679.       )
  1680.     (unless web-mode-engine
  1681.       (setq found nil)
  1682.       (dolist (elt web-mode-engine-file-regexps)
  1683.         (when (and (not found) (string-match-p (cdr elt) buff-name))
  1684.           (setq web-mode-engine (car elt)
  1685.                 found t))
  1686.         )
  1687.       )
  1688.     (when web-mode-engine
  1689.       (setq found nil)
  1690.       (dolist (elt web-mode-engines)
  1691.         (when (and (not found) (member web-mode-engine (cdr elt)))
  1692.           (setq web-mode-engine (car elt)
  1693.                 found t))
  1694.         )
  1695.       )
  1696.     (web-mode-on-engine-setted)
  1697.     ))
  1698.  
  1699. (defun web-mode-imenu-index ()
  1700.   "Return a table of contents."
  1701.   (let (toc-index)
  1702.     (save-excursion
  1703.       (goto-char (point-min))
  1704.       (while (re-search-forward "<h\\([1-9]\\)\\([^>]*\\)>\\([^<]*\\)" nil t)
  1705.     (setq toc-index
  1706.           (cons (cons (concat (make-string
  1707.                    (* 2 (1- (string-to-number (match-string 1))))
  1708.                    ?\s)
  1709.                   (match-string 3))
  1710.               (line-beginning-position))
  1711.             toc-index))))
  1712.     (nreverse toc-index)))
  1713.  
  1714. (defun web-mode-scan-buffer ()
  1715.   "Scan entine buffer."
  1716.   (interactive)
  1717.   (web-mode-scan-region (point-min) (point-max)))
  1718.  
  1719. (defun web-mode-scan-region (beg end &optional content-type)
  1720.   "Identify code blocks (client/server) and syntactic symbols (strings/comments)."
  1721.   (interactive)
  1722.   (web-mode-trace "scanning region")
  1723. ;;  (message "scanning buffer from %d to %d" beg end)
  1724.   (web-mode-with-silent-modifications
  1725.    (save-excursion
  1726.      (save-restriction
  1727.        (save-match-data
  1728.          (let ((inhibit-modification-hooks t)
  1729.                (inhibit-point-motion-hooks t)
  1730.                (inhibit-quit t))
  1731.            (setq beg (if web-mode-is-narrowed 1 beg))
  1732.  
  1733.            (cond
  1734.  
  1735.             ((member web-mode-content-type '("javascript" "json" "css"))
  1736.              (remove-text-properties beg end web-mode-text-properties2)
  1737.              (web-mode-scan-part beg end web-mode-content-type))
  1738.  
  1739.             ((string= web-mode-engine "none")
  1740.              (remove-text-properties beg end web-mode-text-properties2)
  1741.              (web-mode-scan-parts beg end)
  1742.              (web-mode-trace "parts scanned")
  1743.              )
  1744.  
  1745.             ((and content-type (member content-type '("css")))
  1746.              (remove-text-properties beg end web-mode-text-properties2)
  1747.              (web-mode-mark-blocks beg end)
  1748.              (web-mode-scan-part beg end "css")
  1749.              (web-mode-scan-blocks beg end)
  1750.              )
  1751.  
  1752.             ((and content-type (member content-type '("asp")))
  1753.              (remove-text-properties beg end '(block-token nil font nil))
  1754.              (web-mode-scan-block beg end)
  1755.              )
  1756.  
  1757.             (t
  1758.              (remove-text-properties beg end web-mode-text-properties)
  1759.              (web-mode-mark-blocks beg end)
  1760.              (web-mode-trace "blocks marked")
  1761.              (web-mode-scan-parts beg end)
  1762.              (web-mode-trace "parts scanned")
  1763.              (web-mode-scan-blocks beg end)
  1764.              (web-mode-trace "blocks scanned")
  1765.              (when (string= web-mode-engine "django")
  1766.                (web-mode-scan-django-extra-comments beg end)
  1767.                (web-mode-trace "extra")
  1768.                );when
  1769.              )
  1770.  
  1771.             );cond
  1772.  
  1773.            (if web-mode-enable-whitespaces
  1774.                (web-mode-scan-whitespaces beg end))
  1775.            ))))))
  1776.  
  1777. (defun web-mode-mark-blocks (beg end)
  1778.   "Identifies blocks (with block-side, block-beg, block-end text properties)."
  1779.   (save-excursion
  1780.  
  1781.     (let ((i 0)
  1782.           open close closing-string start sub1 sub2 sub3 pos tagopen l tmp)
  1783.  
  1784.       (goto-char beg)
  1785.  
  1786.       ;;      (message "%S: %Sx%S" (point) beg end)
  1787.       ;;      (message "regexp=%S" web-mode-block-regexp)
  1788.       (while (and (< i 1200)
  1789.                   (> end (point))
  1790.                   (re-search-forward web-mode-block-regexp end t))
  1791.  
  1792.         (setq i (1+ i)
  1793.               closing-string nil
  1794.               close nil
  1795.               tagopen (match-string 0)
  1796.               open (match-beginning 0)
  1797.               pos nil)
  1798.  
  1799.         (when (member (string-to-char tagopen) '(?\s ?\t))
  1800.           (setq l (length tagopen))
  1801.           (setq tagopen (replace-regexp-in-string "\\`[ \t]*" "" tagopen))
  1802.           (setq open (+ open (- l (length tagopen))))
  1803.           )
  1804.  
  1805.         (setq sub1 (substring tagopen 0 1)
  1806.               sub2 (substring tagopen 0 2))
  1807.  
  1808.         (cond
  1809.  
  1810.          ((string= web-mode-engine "php")
  1811.           (unless (looking-at-p "xml ")
  1812.             (setq closing-string '("<\\?". "\\?>"))
  1813.             )
  1814.           );php
  1815.  
  1816.          ((string= web-mode-engine "django")
  1817.           (cond
  1818.            ((string= sub2 "{{")
  1819.             (setq closing-string '("{{" . "}}")))
  1820. ;;            (setq closing-string "}}"))
  1821.            ((string= sub2 "{%")
  1822.             (setq closing-string "%}"))
  1823.            (t
  1824.             (setq closing-string "#}"))
  1825.            )
  1826.           );django
  1827.  
  1828.          ((string= web-mode-engine "ctemplate")
  1829.           (setq closing-string "}}")
  1830.           );ctemplate
  1831.  
  1832.          ((or (string= web-mode-engine "asp")
  1833.               (string= web-mode-engine "aspx"))
  1834.           (setq closing-string "%>")
  1835.           );asp
  1836.  
  1837.          ((string= web-mode-engine "blade")
  1838.           (cond
  1839.            ((string= sub2 "{{")
  1840.             (setq closing-string "}}"))
  1841.            ((string= sub1 "@")
  1842.             (setq closing-string "EOL"))
  1843.            )
  1844.           );blade
  1845.  
  1846.          ((string= web-mode-engine "smarty")
  1847.           (cond
  1848.            ((string= sub2 "{*")
  1849.             (setq closing-string "*}"))
  1850.            ((string= sub2 "{#")
  1851.             (setq closing-string "#}"))
  1852.            (t
  1853.             (setq closing-string "}"))
  1854.            )
  1855.           );smarty
  1856.  
  1857.          ((string= web-mode-engine "dust")
  1858.           (cond
  1859.            ((string= sub2 "{!")
  1860.             (setq closing-string "!}"))
  1861.            (t
  1862.             (setq closing-string "}")
  1863.             )
  1864.            )
  1865.           );dust
  1866.  
  1867.          ((string= web-mode-engine "closure")
  1868.           (cond
  1869.            ((string= sub2 "//")
  1870.             (setq closing-string "EOL")
  1871.             )
  1872.            ((string= sub2 "/*")
  1873.             (setq closing-string "*/")
  1874.             )
  1875.            (t
  1876.             (setq closing-string "}")
  1877.             )
  1878.            )
  1879.           );closure
  1880.  
  1881.          ((string= web-mode-engine "ctemplate")
  1882.           (cond
  1883.            ((string= sub3 "{{{")
  1884.             (setq closing-string "}}}"))
  1885.            (t
  1886.             (setq closing-string "}}"))
  1887.            )
  1888.           );ctemplate
  1889.  
  1890.          ((string= web-mode-engine "go")
  1891.           (setq closing-string "}}")
  1892.           );go
  1893.  
  1894.          ((string= web-mode-engine "erb")
  1895.           (cond
  1896.            ((string= sub2 "<%")
  1897.             (setq closing-string "%>"))
  1898.            (t
  1899.             (setq closing-string "EOL"))
  1900.            )
  1901.           );erb
  1902.  
  1903.          ((string= web-mode-engine "jsp")
  1904.           (cond
  1905.            ((string= sub2 "<%")
  1906.             (setq closing-string "%>"))
  1907.            ((string= sub2 "${")
  1908.             (setq closing-string "}"))
  1909.            (t
  1910.             (setq closing-string ">"))
  1911.            )
  1912.           );jsp
  1913.  
  1914.          ((string= web-mode-engine "underscore")
  1915.           (cond
  1916.            (t
  1917.             (setq closing-string "%>"))
  1918.            )
  1919.           );underscore
  1920.  
  1921.          ((string= web-mode-engine "template-toolkit")
  1922.           (cond
  1923.            ((string= sub2 "[#")
  1924.             (setq closing-string "#]"))
  1925.            (t
  1926.             (setq closing-string "%]"))
  1927.            )
  1928.           );underscore
  1929.  
  1930.          ((string= web-mode-engine "freemarker")
  1931.           (cond
  1932.            ((string= sub1 "<")
  1933.             (setq closing-string ">"))
  1934.            ((string= sub1 "[")
  1935.             (setq closing-string "]"))
  1936.            (t
  1937.             (setq closing-string "}"))
  1938.            )
  1939.           );freemarker
  1940.  
  1941.          ((string= web-mode-engine "velocity")
  1942.           (cond
  1943.            ((string= sub2 "##")
  1944.             (setq closing-string "EOL"))
  1945.            ((string= sub2 "#*")
  1946.             (setq closing-string "*#"))
  1947.            (t
  1948.             (setq closing-string "EOV"))
  1949.            )
  1950.           );velocity
  1951.  
  1952.          ((string= web-mode-engine "razor")
  1953.           (cond
  1954.            ((string= sub2 "@@")
  1955.             (forward-char 2)
  1956.             (setq closing-string nil))
  1957.            ((string= sub2 "@*")
  1958.             (setq closing-string "*@"))
  1959.            ((string= sub1 "@")
  1960.             (setq closing-string "EOR"))
  1961.            ((string= sub1 "}")
  1962.             (setq closing-string "EOR"))
  1963.            )
  1964.           );razor
  1965.  
  1966.          ((string= web-mode-engine "python")
  1967.           (unless (looking-at-p "xml ")
  1968.             (setq closing-string "?>"))
  1969.           );python
  1970.  
  1971.          );cond
  1972.  
  1973.         (when closing-string
  1974.  
  1975.           (cond
  1976.  
  1977.            ((listp closing-string)
  1978.             (if (web-mode-rsf-balanced (car closing-string) (cdr closing-string) end t)
  1979.                 (progn
  1980.                   (setq close (match-end 0)
  1981.                         pos (point))
  1982. ;;                  (message "close=%S pos=%S" close pos)
  1983.                   )
  1984.               (when (string= "<?" sub2)
  1985.                 (setq close (point-max)
  1986.                       pos (point-max)))
  1987.               )
  1988.             )
  1989.  
  1990.            ((and (member web-mode-engine '("closure" "dust" "smarty"))
  1991.                  (string= closing-string "}"))
  1992.             (goto-char open)
  1993.             (setq tmp (web-mode-closing-paren-position (point) (line-end-position)))
  1994.             (if tmp
  1995.                 (setq tmp (1+ tmp))
  1996.               (setq tmp (line-end-position)))
  1997.             (goto-char tmp)
  1998.             (setq close (point)
  1999.                   pos (point))
  2000.             )
  2001.  
  2002.            ((string= closing-string "EOL")
  2003.             (end-of-line)
  2004.             (setq close (point)
  2005.                   pos (point)))
  2006.  
  2007.            ((string= closing-string "EOR")
  2008.             (web-mode-razor-skip-forward open)
  2009.             (setq close (point)
  2010.                   pos (point)))
  2011.  
  2012.            ((string= closing-string "EOV")
  2013.             (web-mode-velocity-skip-forward open)
  2014.             (setq close (point)
  2015.                   pos (point)))
  2016.  
  2017.            ((search-forward closing-string end t)
  2018.             (setq close (match-end 0)
  2019.                   pos (point)))
  2020.  
  2021.            );cond
  2022.  
  2023.           (when (and close (>= end pos))
  2024.             ;;(message "pos(%S) : open(%S) close(%S)" pos open close)
  2025.             (add-text-properties open close '(block-side t))
  2026.             (put-text-property open (1+ open) 'block-beg t)
  2027.             (put-text-property (1- close) close 'block-end t)
  2028.             )
  2029.  
  2030.           (if pos (goto-char pos))
  2031.  
  2032.           );when closing-string
  2033.  
  2034.         );while
  2035.  
  2036.       (when (>= i 1200)
  2037.         (message "** strange loop (web-mode-mark-blocks) **"))
  2038.  
  2039.       )))
  2040.  
  2041. (defun web-mode-scan-django-extra-comments (reg-beg reg-end)
  2042.   "Scan extra"
  2043.   (save-excursion
  2044.     (let (beg end)
  2045.       (goto-char reg-beg)
  2046.       (while (and (< (point) reg-end)
  2047.                   (re-search-forward "{% comment %}" reg-end t))
  2048.         ;;        (message "pt=%S" (point))
  2049.         (setq beg (point))
  2050.         (goto-char (1+ (match-beginning 0)))
  2051.         (when (web-mode-match-django-block)
  2052.           (setq end (1- (point)))
  2053.           (remove-text-properties beg end web-mode-text-properties)
  2054.           (add-text-properties beg end '(block-token comment face web-mode-comment-face))
  2055.           )
  2056.         )
  2057.       )))
  2058.  
  2059. (defun web-mode-scan-blocks (region-beg region-end)
  2060.   "Fontify blocks. The scan relies on the 'block-beg text property."
  2061.   (let ((i 0)
  2062.         (comment nil)
  2063.         (beg region-beg)
  2064.         (end nil)
  2065.         (continue t))
  2066.     (while continue
  2067.       (setq end nil
  2068.             i (1+ i))
  2069.       (unless (get-text-property beg 'block-beg)
  2070.         (setq beg (web-mode-block-next-position beg)))
  2071.       (when (and beg (< beg region-end))
  2072.         (setq end (web-mode-block-end-position beg)))
  2073.       (cond
  2074.        ((or (null end)
  2075.             (> end region-end)
  2076.             (> i 1200))
  2077.         (setq continue nil)
  2078.         (if (> i 1200) (message "*** invalid loop (web-mode-scan-blocks) ***")))
  2079.        (t
  2080.         (setq end (1+ end))
  2081.         ;;(message "beg=%S end=%S" beg end)
  2082.  
  2083.         (when (and (not web-mode-has-any-large-block)
  2084.                    (> (- end beg) web-mode-large-embed-threshold))
  2085.           (message "** large block detected [ %S - %S ] **" beg end)
  2086.           (setq web-mode-has-any-large-block t))
  2087.  
  2088.         (web-mode-scan-block beg end)
  2089.         (when (and (member web-mode-engine '("jsp"))
  2090.                    (> (- end beg) 12)
  2091.                    (eq ?\< (char-after beg)))
  2092.           (web-mode-scan-jsp-tag beg end))
  2093.         (setq beg end)
  2094.         )
  2095.        );cond
  2096.       );while
  2097.  
  2098.     ))
  2099.  
  2100. (defun web-mode-scan-block (beg end)
  2101.   "Fontify a block."
  2102.   (let ((sub1 "") (sub2 "") (sub3 "") regexp props start ms continue fc keywords tag token-type hddeb hdend hdflk)
  2103.  
  2104. ;;    (remove-text-properties beg end web-mode-text-properties)
  2105.  
  2106.     (goto-char beg)
  2107.  
  2108.     (setq sub1 (buffer-substring-no-properties beg (+ beg 1))
  2109.           sub2 (buffer-substring-no-properties beg (+ beg 2)))
  2110.     (setq sub3 sub2)
  2111.     (if (>= (point-max) (+ beg 3))
  2112.         (setq sub3 (buffer-substring-no-properties beg (+ beg 3))))
  2113.  
  2114.     (cond
  2115.  
  2116.      ((string= web-mode-engine "php")
  2117.       (setq regexp "//\\|/\\*\\|\"\\|'\\|<<<['\"]?\\([[:alnum:]]+\\)['\"]?"
  2118.             props '(face nil)
  2119.             keywords web-mode-php-font-lock-keywords)
  2120.       );php
  2121.  
  2122.      ((string= web-mode-engine "django")
  2123.       (cond
  2124.        ((string= sub2 "{{")
  2125.         (setq regexp "\"\\|'"
  2126.               props '(face nil)
  2127.               keywords web-mode-django-expr-font-lock-keywords)
  2128.         )
  2129.        ((string= sub2 "{%")
  2130.         (setq regexp "\"\\|'"
  2131.               props '(face nil)
  2132.               keywords web-mode-django-code-font-lock-keywords)
  2133.         )
  2134.        ((string= sub2 "{#")
  2135.         (setq props '(block-token comment face web-mode-comment-face))
  2136.         )
  2137.        )
  2138.       );django
  2139.  
  2140.      ((string= web-mode-engine "ctemplate")
  2141.       (cond
  2142.        ((string= sub3 "{{!")
  2143.         (setq props '(block-token comment face web-mode-comment-face)))
  2144.        ((string= sub3 "{{%")
  2145.         (setq regexp "\"\\|'"
  2146.               props '(face nil)
  2147.               keywords web-mode-ctemplate-font-lock-keywords))
  2148.        (t
  2149.         (setq props '(face nil)
  2150.               keywords web-mode-ctemplate-font-lock-keywords))
  2151.        )
  2152.       );ctemplate
  2153.  
  2154.      ((string= web-mode-engine "go")
  2155.       (cond
  2156.        ((string= sub3 "{{/")
  2157.         (setq props '(block-token comment face web-mode-comment-face)))
  2158.        ((string= sub2 "{{")
  2159.         (setq regexp "\"\\|'"
  2160.               props '(face nil)
  2161.               keywords web-mode-go-font-lock-keywords))
  2162.        )
  2163.       );go
  2164.  
  2165.      ((string= web-mode-engine "razor")
  2166.       (cond
  2167.        ((string= sub2 "@*")
  2168.         (setq props '(block-token comment face web-mode-comment-face)))
  2169.        (t
  2170.         (setq regexp "\"\\|'"
  2171.               props '(face nil)
  2172.               keywords web-mode-razor-font-lock-keywords))
  2173.        )
  2174.       );razor
  2175.  
  2176.      ((string= web-mode-engine "python")
  2177.       (setq regexp "\"\\|'\\|#"
  2178.             props '(face nil)
  2179.             keywords web-mode-python-font-lock-keywords)
  2180.       );python
  2181.  
  2182.      ((string= web-mode-engine "blade")
  2183.       (cond
  2184.        ((string= sub3 "{{-")
  2185.         (setq props '(block-token comment face web-mode-comment-face)))
  2186.        (t
  2187.         (setq regexp "\"\\|'"
  2188.               props '(face nil)
  2189.               keywords web-mode-blade-font-lock-keywords))
  2190.        )
  2191.       );blade
  2192.  
  2193.      ((string= web-mode-engine "velocity")
  2194.       (cond
  2195.        ((member sub2 '("##" "#*"))
  2196.         (setq props '(block-token comment face web-mode-comment-face)))
  2197.        ((string= sub1 "$")
  2198.         (setq regexp "\"\\|'"
  2199.               props '(face nil)
  2200.               keywords web-mode-velocity-font-lock-keywords))
  2201.        ((string= sub1 "#")
  2202.         (setq regexp "\"\\|'"
  2203.               props '(face nil)
  2204.               keywords web-mode-velocity-font-lock-keywords))
  2205.        )
  2206.       );velocity
  2207.  
  2208.      ((string= web-mode-engine "jsp")
  2209.       (cond
  2210.        ((string= sub3 "<%-")
  2211.         (setq props '(block-token comment face web-mode-comment-face)))
  2212.        ((string= sub3 "<%@")
  2213.         (setq regexp "/\\*"
  2214.               props '(face nil)
  2215.               keywords web-mode-directive-font-lock-keywords))
  2216.        ((member sub2 '("${" "#{"))
  2217.         (setq regexp "\"\\|'"
  2218.               props '(face nil)
  2219.               keywords web-mode-uel-font-lock-keywords))
  2220.        ((string= sub2 "<%")
  2221.         (setq regexp "//\\|/\\*\\|\"\\|'"
  2222.               props '(face nil)
  2223.               keywords web-mode-jsp-font-lock-keywords))
  2224.        (t
  2225.         (setq props '(face nil)
  2226.               keywords web-mode-jsp-tag-font-lock-keywords)
  2227.         )
  2228.        )
  2229.       );jsp
  2230.  
  2231.      ((string= web-mode-engine "freemarker")
  2232.       (cond
  2233.        ((member sub3 '("<#-" "[#-"))
  2234.         (setq props '(block-token comment face web-mode-comment-face))
  2235.         )
  2236.        ((member sub2 '("${" "#{"))
  2237.         (setq regexp "\"\\|'"
  2238.               props '(face nil)
  2239.               keywords web-mode-uel-font-lock-keywords))
  2240.        ((or (member sub2 '("<@" "[@" "<#" "[#"))
  2241.             (member sub3 '("</@" "[/@" "</#" "[/#")))
  2242.         (setq regexp "\""
  2243.               props '(face nil)
  2244.               keywords (if (eq ?\[ (aref sub2 0))
  2245.                            web-mode-freemarker-square-font-lock-keywords
  2246.                          web-mode-freemarker-font-lock-keywords))
  2247.         )
  2248.        (t
  2249.         (setq props '(face nil)
  2250.               keywords web-mode-jsp-tag-font-lock-keywords)
  2251.         )
  2252.        )
  2253.       );freemarker
  2254.  
  2255.      ((string= web-mode-engine "erb")
  2256.       (cond
  2257.        ((string= sub3 "<%#")
  2258.         (setq props '(block-token comment face web-mode-comment-face)))
  2259.        (t
  2260.         (setq regexp "\"\\|'\\|#\\|<<[-]?['\"]?\\([[:alnum:]]+\\)['\"]?"
  2261.               props '(face nil)
  2262.               keywords web-mode-erb-font-lock-keywords)
  2263.         )
  2264.        )
  2265.       );erb
  2266.  
  2267.      ((string= web-mode-engine "asp")
  2268.       (setq regexp "//\\|/\\*\\|\"\\|'"
  2269.             props '(face nil)
  2270.             keywords web-mode-asp-font-lock-keywords)
  2271.       );asp
  2272.  
  2273.  
  2274.      ((string= web-mode-engine "template-toolkit")
  2275.       (cond
  2276.        ((string= sub2 "[#")
  2277.         (setq props '(block-token comment face web-mode-comment-face)))
  2278.        (t
  2279.         (setq regexp "#\\|\"\\|'"
  2280.               props '(face nil)
  2281.               keywords web-mode-template-toolkit-font-lock-keywords)
  2282.         )));template-toolkit
  2283.  
  2284.      ((string= web-mode-engine "underscore")
  2285.       (setq regexp "/\\*\\|\"\\|'"
  2286.             props '(face nil)
  2287.             keywords web-mode-underscore-font-lock-keywords)
  2288.       );underscore
  2289.  
  2290.      ((string= web-mode-engine "aspx")
  2291.       (cond
  2292.        ((string= sub3 "<%-")
  2293.         (setq props '(block-token comment face web-mode-comment-face)))
  2294.        ((string= sub3 "<%@")
  2295.         (setq regexp "/\\*"
  2296.               props '(face nil)
  2297.               keywords web-mode-directive-font-lock-keywords))
  2298.        ((string= sub3 "<%$")
  2299.         (setq regexp "\"\\|'"
  2300.               props '(face nil)
  2301.               keywords web-mode-expression-font-lock-keywords))
  2302.        (t
  2303.         (setq regexp "//\\|/\\*\\|\"\\|'"
  2304.               props '(face nil)
  2305.               keywords web-mode-aspx-font-lock-keywords)
  2306.         )
  2307.        )
  2308.       );aspx
  2309.  
  2310.      ((string= web-mode-engine "smarty")
  2311.       (cond
  2312.        ((string= sub2 "{*")
  2313.         (setq props '(block-token comment face web-mode-comment-face))
  2314.         )
  2315.        (t
  2316.         (setq regexp "\"\\|'"
  2317.               props '(face nil)
  2318.               keywords web-mode-smarty-font-lock-keywords)
  2319.         )
  2320.        )
  2321.       );smarty
  2322.  
  2323.      ((string= web-mode-engine "dust")
  2324.       (cond
  2325.        ((string= sub2 "{!")
  2326.         (setq props '(block-token comment face web-mode-comment-face))
  2327.         )
  2328.        (t
  2329.         (setq regexp "\"\\|'"
  2330.               props '(face nil)
  2331.               keywords web-mode-dust-font-lock-keywords)
  2332.         )
  2333.        )
  2334.       );dust
  2335.  
  2336.      ((string= web-mode-engine "closure")
  2337.       (cond
  2338.        ((member sub2 '("/*" "//"))
  2339.         (setq props '(block-token comment face web-mode-comment-face))
  2340.         )
  2341.        (t
  2342.         (setq regexp "\"\\|'"
  2343.               props '(face nil)
  2344.               keywords web-mode-closure-font-lock-keywords)
  2345.         )
  2346.        )
  2347.       );closure
  2348.  
  2349.      )
  2350.  
  2351.     (add-text-properties beg end props)
  2352.  
  2353.     (when keywords (web-mode-fontify-region beg end keywords))
  2354.  
  2355.     (when regexp
  2356.       (setq token-type "string")
  2357.       (goto-char beg)
  2358.       (while (re-search-forward regexp end t)
  2359.         (setq start (match-beginning 0)
  2360.               ms (match-string 0)
  2361.               continue t)
  2362.         (setq fc (aref ms 0))
  2363.         (cond
  2364.  
  2365.          ((and (string= web-mode-engine "asp")
  2366.                (eq fc ?\'))
  2367.           (setq props '(block-token comment face web-mode-block-comment-face)
  2368.                 token-type "comment")
  2369.           (goto-char (if (< end (line-end-position)) end (line-end-position)))
  2370.           )
  2371.  
  2372.          ((eq fc ?\')
  2373.           (setq props '(block-token string face web-mode-block-string-face))
  2374.           (while (and continue (search-forward "'" end t))
  2375.             (setq continue (eq ?\\ (char-before (1- (point)))))
  2376.             )
  2377.           )
  2378.  
  2379.          ((eq fc ?\")
  2380.          (setq props '(block-token string face web-mode-block-string-face))
  2381.          (while (and continue (search-forward "\"" end t))
  2382.             (setq continue (eq ?\\ (char-before (1- (point)))))
  2383.             )
  2384.           )
  2385.  
  2386.          ((string= ms "//")
  2387.           (setq props '(block-token comment face web-mode-block-comment-face)
  2388.                 token-type "comment")
  2389.           (goto-char (if (< end (line-end-position)) end (line-end-position)))
  2390.           )
  2391.  
  2392.          ((eq fc ?\#)
  2393.           (setq props '(block-token comment face web-mode-block-comment-face)
  2394.                 token-type "comment")
  2395.           (goto-char (if (< end (line-end-position)) end (line-end-position)))
  2396.           )
  2397.  
  2398.  
  2399.          ((string= ms "/*")
  2400.           (setq props '(block-token comment face web-mode-block-comment-face)
  2401.                 token-type "comment")
  2402.           (search-forward "*/" end t)
  2403.           )
  2404.  
  2405.          ((eq fc ?\<)
  2406.           (when (and web-mode-enable-heredoc-fontification
  2407.                      (string-match-p "JS\\|JAVASCRIPT\\|HTM\\|CSS" (match-string 1)))
  2408.             (setq hddeb (1+ (point))
  2409.                   hdflk (if (string-match-p "HTM" (match-string 1))
  2410.                             web-mode-html-font-lock-keywords
  2411.                           web-mode-javascript-font-lock-keywords))
  2412.             )
  2413.           ;;          (message "tag=%s pos=%S" (match-string 1) (point))
  2414.           (setq props '(block-token string face web-mode-block-string-face))
  2415.           (re-search-forward (concat "^[ ]*" (match-string 1)) end t)
  2416.           (when hddeb (setq hdend (1- (match-beginning 0))))
  2417.           )
  2418.  
  2419.          ((and (member web-mode-engine '("python" "erb"))
  2420.                (eq fc ?\#))
  2421.           (setq props '(block-token comment face web-mode-block-comment-face))
  2422.           (goto-char (if (< end (line-end-position)) end (line-end-position)))
  2423.           )
  2424.  
  2425.          );;cond
  2426.  
  2427.         ;;        (message "elt=%S" (buffer-substring start (point)))
  2428.         (add-text-properties start (point) props)
  2429.  
  2430.         (when (and (eq fc ?\")
  2431.                   (member web-mode-engine '("php" "erb"))
  2432.                   (> (- (point) start) 4))
  2433.          (web-mode-interpolate-string start (point))
  2434.          )
  2435.  
  2436.        (when hddeb
  2437.          (web-mode-fontify-region hddeb hdend hdflk)
  2438.          (setq hddeb nil))
  2439.  
  2440.        (cond
  2441.         ((string= token-type "comment")
  2442.          (if web-mode-enable-comment-keywords
  2443.              (web-mode-interpolate-comment start (point) t))
  2444.          )
  2445.         (t
  2446.          )
  2447.         )
  2448.  
  2449.        );while
  2450.  
  2451.      );when regexp
  2452.  
  2453.    (when web-mode-enable-block-face
  2454.      (font-lock-prepend-text-property beg end
  2455.                                      'face
  2456.                                      'web-mode-block-face))
  2457.    ))
  2458.  
  2459. (defun web-mode-scan-jsp-tag (beg end)
  2460.  "Scan a jsp tag to fontify ${ } blocks"
  2461.  (save-excursion
  2462.    (goto-char (+ 4 beg))
  2463.    (setq end (1- end))
  2464.    (while (re-search-forward "${.*}" end t)
  2465.      (web-mode-fontify-region (match-beginning 0) (match-end 0)
  2466.                               web-mode-uel-font-lock-keywords)
  2467.      )
  2468.    ))
  2469.  
  2470. (defun web-mode-interpolate-string (beg end)
  2471.  "Interpolate php/erb strings."
  2472.  (save-excursion
  2473.    (goto-char (1+ beg))
  2474.    (setq end (1- end))
  2475.    (cond
  2476.     ((string= web-mode-engine "php")
  2477.      (while (re-search-forward "$[[:alnum:]]+" end t)
  2478.        (put-text-property (match-beginning 0) (match-end 0)
  2479.                           'face nil)
  2480.        (put-text-property (1+ (match-beginning 0)) (match-end 0)
  2481.                           'face 'web-mode-variable-name-face)
  2482.        ))
  2483.     ((string= web-mode-engine "erb")
  2484.      (while (re-search-forward "#{.*}" end t)
  2485.        (put-text-property (match-beginning 0) (match-end 0)
  2486.                           'face 'web-mode-variable-name-face)
  2487.        ))
  2488.     );cond
  2489.    ))
  2490.  
  2491.  
  2492. (defun web-mode-interpolate-comment (beg end block-side)
  2493.  "Interpolate comment"
  2494.  (save-excursion
  2495.    (let (regexp)
  2496.      (goto-char beg)
  2497.      (setq regexp (concat "\\<\\(" web-mode-comment-keywords "\\)\\>"))
  2498.      (while (re-search-forward regexp end t)
  2499.        (font-lock-prepend-text-property (match-beginning 1) (match-end 1)
  2500.                                         'face
  2501.                                         'web-mode-comment-keyword-face)
  2502.        )
  2503.      )))
  2504.  
  2505. ;; start-tag, end-tag, tag-name, element (<a>xsx</a>, an element is delimited by tags), void-element
  2506. ;; http://www.w3.org/TR/html-markup/syntax.html#syntax-elements
  2507. ;;<#include "toto">
  2508. (defun web-mode-scan-parts (beg end)
  2509.  "Scan client side blocks (JavaScript / CSS / HTML Comments) and identifies strings and comments."
  2510.  (save-excursion
  2511.    (let (open limit close ms expr props closing-string start tag tag-name tag-beg tag-end tag-stop element-content-type attrs-end close-found pos markup-face prop-type prop-name)
  2512.  
  2513.      (goto-char beg)
  2514.  
  2515.      ;; <\\(!--\\|!doctype\\|/?[[:alnum:]]+[:_]?[[:alnum:]]*\\|\?xml\\)
  2516.      ;; <\\(/?[[:alnum:]]+\\|!--\\|!doctype\\|\?xml\\)
  2517.      ;; <[[:alpha:]/!?]
  2518.      (while (web-mode-rsf-client "<\\(/?[[:alnum:]]+\\|!--\\|!doctype\\|\?xml\\)" end t)
  2519.        (setq tag-name (downcase (match-string 1))
  2520.              tag-beg (match-beginning 0)
  2521.              tag-end nil
  2522.              element-content-type nil
  2523.              tag-stop (point)
  2524.              prop-name 'tag-name
  2525.              prop-type 'tag-type
  2526.              open nil
  2527.              limit end
  2528.              close nil
  2529.              pos nil
  2530.              markup-face nil
  2531.              props nil
  2532.              expr nil
  2533.              closing-string nil
  2534.              close-found nil)
  2535.  
  2536.        (cond
  2537.         ((string= tag-name "!--")
  2538.          (setq expr "-->"))
  2539.         ((string= tag-name "!doctype")
  2540.          (setq expr ">"))
  2541.         ((string= tag-name "?xml")
  2542.          (setq expr "?>"))
  2543.         (t
  2544.          (setq props '(face web-mode-html-tag-face))
  2545.          (cond
  2546.           ((eq ?\/ (string-to-char tag-name))
  2547.            (setq props (plist-put props prop-name (substring tag-name 1)))
  2548.            (setq props (plist-put props prop-type 'end))
  2549.            (setq expr ">")
  2550.            (setq limit (if (> end (line-end-position)) (line-end-position) end))
  2551.            )
  2552.           ((web-mode-is-void-element tag-name)
  2553.            (setq props (plist-put props prop-name tag-name))
  2554.            (setq props (plist-put props prop-type 'void))
  2555.            (setq expr ">")
  2556.            )
  2557.           (t
  2558.            (setq props (plist-put props prop-name tag-name))
  2559.            (setq props (plist-put props prop-type 'start))
  2560.            (setq expr ">")
  2561.            )
  2562.           );cond
  2563.          );t
  2564.         );cond
  2565.  
  2566.        (if (web-mode-sf-client expr limit t)
  2567.            (progn
  2568.              (setq attrs-end (- (point) (length expr))
  2569.                    tag-end (point)
  2570.                    close-found t)
  2571.              (when (eq ?\/ (char-after (- (point) 2)))
  2572.                (setq attrs-end (1- attrs-end)
  2573.                      props (plist-put props prop-type 'void)))
  2574.              );progn
  2575.          (setq attrs-end (line-end-position)
  2576.                tag-end (line-end-position))
  2577.          );if
  2578.  
  2579.        (cond
  2580.         ((string= tag-name "script")
  2581.          (setq tag (buffer-substring-no-properties tag-beg tag-end))
  2582.          (cond
  2583.           ((string-match-p " type[ ]*=[ ]*[\"']text/\\(x-handlebars\\|html\\)" tag)
  2584.             (setq element-content-type "html"))
  2585.            ((string-match-p " type[ ]*=[ ]*[\"']application/\\(ld\\+json\\|json\\)" tag)
  2586.             (setq element-content-type "json"))
  2587.            (t
  2588.             (setq element-content-type "javascript"))
  2589.            )
  2590. ;;          (message "tag=%S : %S" tag element-content-type)
  2591.           );case script
  2592.          ((string= tag-name "style")
  2593.           (setq element-content-type "css")
  2594.           )
  2595.          )
  2596.  
  2597. ;;        (message "tag=%S (%S > %S)\n%S" tag-name tag-beg tag-end props)
  2598.         (add-text-properties tag-beg tag-end props)
  2599.         (put-text-property tag-beg (1+ tag-beg) 'tag-beg t)
  2600.         (put-text-property (1- tag-end) tag-end 'tag-end t)
  2601.  
  2602.         (cond
  2603.  
  2604.          ((or (string= tag-name "!doctype") (string= tag-name "?xml"))
  2605.           (add-text-properties tag-beg tag-end '(tag-name "doctype" tag-type void face web-mode-doctype-face)))
  2606.  
  2607.          ((string= tag-name "!--")
  2608.           (add-text-properties tag-beg tag-end '(tag-name "comment" tag-type void part-side t part-token comment face web-mode-comment-face)))
  2609.  
  2610.          (close-found
  2611.           (when (and (not (eq ?\/ (aref tag-name 0)))
  2612.                      (> (- attrs-end tag-stop) 1))
  2613. ;;            (message "tag-stop=%S attrs-end=%S" tag-stop attrs-end)
  2614.             (web-mode-scan-attrs tag-stop attrs-end)
  2615.             )
  2616.           (cond
  2617.            ((and (string= tag-name "script")
  2618.                  (member element-content-type '("javascript" "json")))
  2619.             (setq closing-string "</script>"))
  2620.            ((string= tag-name "style")
  2621.             (setq closing-string "</style>"))
  2622.            )
  2623.  
  2624.           ;; si <script type="document/html"> on ne fait pas la suite
  2625.  
  2626.           (when (and closing-string (web-mode-sf-client closing-string end t))
  2627.             (setq open tag-end
  2628.                   close (match-beginning 0))
  2629.             (if (>= (- close open) 3)
  2630.                 (web-mode-scan-part open close element-content-type)
  2631.               (remove-text-properties open close web-mode-text-properties2))
  2632.             (goto-char close)
  2633.             ); when
  2634.           ); close-found
  2635.          ); cond tag
  2636.  
  2637.         ); while
  2638.  
  2639.       )))
  2640.  
  2641. ;; todo : il serait préférable d'identifier les tokens et ensuite de fontifier
  2642. (defun web-mode-scan-part (part-beg part-end content-type)
  2643.   "Scan client part (e.g. javascript, json, css)."
  2644.   (save-excursion
  2645.     (let (token-re ch-before ch-at ch-next props start continue keywords token-type face)
  2646.  
  2647.       (remove-text-properties part-beg part-end web-mode-text-properties2)
  2648.  
  2649.       (goto-char part-beg)
  2650.  
  2651.       (when (and (not web-mode-has-any-large-part)
  2652.                  (> (- part-end part-beg) web-mode-large-embed-threshold))
  2653.         (message "** large part detected [ %S - %S ] **" part-beg part-end)
  2654.         (setq web-mode-has-any-large-part t))
  2655.  
  2656.       (cond
  2657.        ((string= content-type "javascript")
  2658.         (setq token-re "//\\|/\\*\\|\"\\|'"
  2659.               keywords web-mode-javascript-font-lock-keywords
  2660.               props '(part-language javascript part-side t)))
  2661.        ((string= content-type "json")
  2662.         (setq token-re "//\\|/\\*\\|\"\\|'"
  2663.               keywords web-mode-javascript-font-lock-keywords
  2664.               props '(part-language json part-side t)))
  2665.        ((string= content-type "css")
  2666.         (setq token-re "/\\*\\|\"\\|'"
  2667.               props '(part-language css part-side t)))
  2668.        )
  2669.  
  2670.       (add-text-properties part-beg part-end props)
  2671.  
  2672.       (when keywords
  2673.         (web-mode-fontify-region part-beg part-end keywords))
  2674.  
  2675.       (when (string= content-type "css")
  2676.         (web-mode-css-scan-rules part-beg part-end))
  2677.  
  2678.       (when token-re
  2679.         (while (and token-re (web-mode-rsf-client token-re part-end t))
  2680.           (setq start (match-beginning 0)
  2681.                 props nil
  2682.                 continue t)
  2683.           (setq ch-at (char-after start))
  2684.           (setq ch-next (or (char-after (1+ start)) ?\d))
  2685.           (setq ch-before (or (char-before start) ?\d))
  2686.           (setq token-type "string")
  2687.           ;;        (message "beg=%S :%c%c%c" start ch-before ch-at ch-next)
  2688.           (cond
  2689.  
  2690.            ((eq ?\' ch-at)
  2691.             (unless (eq ?\\ ch-before)
  2692.               (while (and continue (search-forward "'" part-end t))
  2693.                 (setq continue (or (get-text-property (1- (point)) 'block-side)
  2694.                                    (eq ?\\ (char-before (1- (point))))))
  2695.                 )
  2696.               (cond
  2697.                ((string= content-type "javascript")
  2698.                 (setq props '(part-token string face web-mode-javascript-string-face)))
  2699.                ((string= content-type "css")
  2700.                 (setq props '(part-token string face web-mode-css-string-face)))
  2701.                ((string= content-type "json")
  2702.                 (setq props '(part-token string face web-mode-json-string-face)))
  2703.                (t
  2704.                 (setq props '(part-token string face web-mode-part-string-face)))
  2705.                );cond
  2706.               );unless
  2707.             )
  2708.  
  2709.            ((eq ?\" ch-at)
  2710.            (unless (eq ?\\ ch-before)
  2711.              (while (and continue (search-forward "\"" part-end t))
  2712.                 (setq continue (or (get-text-property (1- (point)) 'block-side)
  2713.                                    (eq ?\\ (char-before (1- (point))))))
  2714.                 )
  2715.               (cond
  2716.                ((string= content-type "json")
  2717.                 (if (looking-at-p "[ ]*:")
  2718.                     (cond
  2719.                      ((eq ?\@ (char-after (1+ start)))
  2720.                       (setq props '(part-token string face web-mode-json-context-face))
  2721.                       )
  2722.                      (t
  2723.                       (setq props '(part-token string face web-mode-json-key-face))
  2724.                       )
  2725.                      )
  2726.                   (setq props '(part-token string face web-mode-json-string-face)))
  2727.                 )
  2728.                (t
  2729.                 (cond
  2730.                  ((string= content-type "javascript")
  2731.                   (setq props '(part-token string face web-mode-javascript-string-face)))
  2732.                  ((string= content-type "css")
  2733.                   (setq props '(part-token string face web-mode-css-string-face)))
  2734.                  (t
  2735.                   (setq props '(part-token string face web-mode-part-string-face)))
  2736.                  );cond
  2737.                 );t
  2738.                );cond
  2739.               );unless
  2740.             )
  2741.  
  2742.            ((eq ?\/ ch-next)
  2743.             (unless (eq ?\\ ch-before)
  2744.               (setq props '(part-token comment face web-mode-part-comment-face)
  2745.                     token-type "comment")
  2746.               (goto-char (if (< part-end (line-end-position)) part-end (line-end-position)))
  2747.               )
  2748.             )
  2749.  
  2750.            ((eq ?\* ch-next)
  2751.             (unless (eq ?\\ ch-before)
  2752.               (setq props '(part-token comment face web-mode-part-comment-face)
  2753.                     token-type "comment")
  2754.               (search-forward "*/" part-end t)
  2755.               )
  2756.             )
  2757.  
  2758.            );cond
  2759.  
  2760.           (when (>= part-end (point))
  2761.             (if props (add-text-properties start (point) props))
  2762.             (when (and (string= token-type "comment")
  2763.                        web-mode-enable-comment-keywords)
  2764.               (web-mode-interpolate-comment start (point) t))
  2765.             )
  2766.  
  2767.           ));while | when token-re
  2768.  
  2769.       (when web-mode-enable-part-face
  2770.         (font-lock-append-text-property part-beg part-end
  2771.                                         'web-mode-part-face
  2772.                                         face))
  2773.  
  2774.       )))
  2775.  
  2776. (defun web-mode-css-scan-rules (part-beg part-end)
  2777.   "Fontify css rule."
  2778.   (save-excursion
  2779.     (goto-char part-beg)
  2780.     (let (rule (continue t) (i 0) at-rule)
  2781.       (while continue
  2782.         (setq i (1+ i))
  2783.         (setq rule (web-mode-css-next-rule part-end))
  2784. ;;        (if (< (point) 328) (message "pt=%S" (point)))
  2785. ;;        (if (and (< i 6) rule) (message "%S rule=%S (%S)" i rule (point)))
  2786.         (cond
  2787.          ((> i 1000)
  2788.           (message "*** too much css rules ***")
  2789.           (setq continue nil))
  2790.          ((null rule)
  2791.           (setq continue nil)
  2792.           )
  2793.          ((and (setq at-rule (plist-get rule :at-rule))
  2794.                (not (member at-rule '("charset" "font-face" "import")))
  2795.                (plist-get rule :dec-end))
  2796.           (web-mode-css-fontify-rule (plist-get rule :sel-beg)
  2797.                                      (plist-get rule :sel-end)
  2798.                                      nil nil)
  2799.           (web-mode-css-scan-rules (plist-get rule :dec-beg)
  2800.                                    (plist-get rule :dec-end))
  2801.           )
  2802.          (t
  2803.           (web-mode-css-fontify-rule (plist-get rule :sel-beg)
  2804.                                      (plist-get rule :sel-end)
  2805.                                      (plist-get rule :dec-beg)
  2806.                                      (plist-get rule :dec-end))
  2807.           )
  2808.          );cond
  2809.         )
  2810.       )
  2811.     ))
  2812.  
  2813. (defun web-mode-css-fontify-rule (sel-beg sel-end dec-beg dec-end)
  2814.   "Fontify css rule."
  2815.   (save-excursion
  2816. ;;    (message "sel-beg=%S sel-end=%S dec-beg=%S dec-end=%S" sel-beg sel-end dec-beg dec-end)
  2817.     (web-mode-fontify-region sel-beg sel-end
  2818.                              web-mode-selector-font-lock-keywords)
  2819.     (when (and dec-beg dec-end)
  2820.       (web-mode-fontify-region dec-beg dec-end
  2821.                                web-mode-declaration-font-lock-keywords)
  2822.       (goto-char dec-beg)
  2823.       (while (and (not web-mode-disable-css-colorization)
  2824.                   (re-search-forward "#[0-9a-fA-F]\\{6\\}\\|#[0-9a-fA-F]\\{3\\}\\|rgb([ ]*\\([[:digit:]]\\{1,3\\}\\)[ ]*,[ ]*\\([[:digit:]]\\{1,3\\}\\)[ ]*,[ ]*\\([[:digit:]]\\{1,3\\}\\)\\(.*?\\))" dec-end t)
  2825.                   (< (point) dec-end))
  2826.         (web-mode-colorize (match-beginning 0) (match-end 0))
  2827.         )
  2828.       )))
  2829.  
  2830. ;; css rule = selectors + declaration (properties)
  2831. (defun web-mode-css-next-rule (limit)
  2832.   "next rule"
  2833.   (let (at-rule sel-beg sel-end dec-beg dec-end chunk)
  2834.     (skip-chars-forward "\n\t ")
  2835.     (setq sel-beg (point))
  2836.     (when (and (< (point) limit)
  2837.                (web-mode-rsf-client "[{;]" limit t))
  2838.       (setq sel-end (1- (point)))
  2839.       (cond
  2840.        ((eq (char-before) ?\{)
  2841.         (setq dec-beg (point))
  2842.         (setq dec-end (web-mode-closing-paren-position (1- dec-beg) limit))
  2843.         (if dec-end
  2844.             (progn
  2845.               (goto-char dec-end)
  2846.               (forward-char))
  2847.           (setq dec-end limit)
  2848.           (goto-char limit))
  2849.         )
  2850.        (t
  2851.         )
  2852.        );cond
  2853.       (setq chunk (buffer-substring-no-properties sel-beg sel-end))
  2854.       (when (string-match "@\\([[:alpha:]-]+\\)" chunk)
  2855.         (setq at-rule (match-string-no-properties 1 chunk))
  2856. ;;        (message "%S at-rule=%S" chunk at-rule)
  2857.         )
  2858.       );when
  2859.     (if (not sel-end)
  2860.         (progn (goto-char limit) nil)
  2861.       (list :at-rule at-rule
  2862.             :sel-beg sel-beg
  2863.             :sel-end sel-end
  2864.             :dec-beg dec-beg
  2865.             :dec-end dec-end)
  2866.       );if
  2867.     ))
  2868.  
  2869. (defun web-mode-css-current-rule (pos min max)
  2870.   "current css rule"
  2871.   (save-excursion
  2872.     (let (beg end)
  2873.       (goto-char pos)
  2874.       (if (not (web-mode-sb-client "{" min t))
  2875.           (progn
  2876.             (setq beg min)
  2877.             (if (web-mode-sf-client ";" max t)
  2878.                 (setq end (1+ (point)))
  2879.               (setq end max))
  2880.             )
  2881.         (setq beg (point))
  2882.         (setq end (web-mode-closing-paren-position beg max))
  2883.         (if end
  2884.             (setq end (1+ end))
  2885.           (setq end max)
  2886.           )
  2887. ;;        (message "%S >>beg%S >>end%S" pos beg end)
  2888.         (if (> pos end)
  2889.  
  2890.             ;;selectors
  2891.             (progn
  2892.               (goto-char pos)
  2893.               (if (web-mode-rsb-client "[};]" min t)
  2894.                   (setq beg (1+ (point)))
  2895.                 (setq beg min)
  2896.                 )
  2897.               (goto-char pos)
  2898.               (if (web-mode-rsf-client "[{;]" max t)
  2899.                   (cond
  2900.                    ((eq (char-before) ?\;)
  2901.                     (setq end (point))
  2902.                     )
  2903.                    (t
  2904.                     (setq end (web-mode-closing-paren-position (1- (point)) max))
  2905.                     (if end
  2906.                         (setq end (1+ end))
  2907.                       (setq end max))
  2908.                     )
  2909.                    );cond
  2910.                 (setq end max)
  2911.                 )
  2912.               );progn selectors
  2913.  
  2914.           ;; declaration
  2915.           (goto-char beg)
  2916.           (if (web-mode-rsb-client "[}{;]" min t)
  2917.               (setq beg (1+ (point)))
  2918.             (setq beg min)
  2919.             )
  2920.           )
  2921.         )
  2922. ;;      (message "beg(%S) end(%S)" beg end)
  2923.       (cons beg end)
  2924.       )))
  2925.  
  2926. ;; http://www.w3.org/TR/html-markup/syntax.html#syntax-attributes
  2927. ;; states:
  2928. ;; nil(0) space(1) name(2) space-before(3) equal(4) space-after(5) value-uq(6) value-sq(7) value-dq(8)
  2929. (defun web-mode-scan-attrs (beg end)
  2930.   "Scan and fontify html attributes."
  2931.   (save-excursion
  2932.   ;;    (message "beg(%S) end(%S)" beg end)
  2933.     (let (name-beg name-end val-beg val-end (state 0) char pos escaped spaced)
  2934.       (goto-char (1- beg))
  2935.  
  2936.       (while (< (point) end)
  2937.         (forward-char)
  2938.         (setq pos (point)
  2939.               char (char-after))
  2940.         (setq spaced (eq ?\s char))
  2941. ;;        (setq char (buffer-substring-no-properties pos (1+ pos)))
  2942.  
  2943.         (cond
  2944.  
  2945.          ((= pos end)
  2946.           (web-mode-propertize-attr state char name-beg name-end val-beg)
  2947.           (setq state 0
  2948.                 name-beg nil
  2949.                 name-end nil
  2950.                 val-beg nil
  2951.                 val-end nil)
  2952.           )
  2953.  
  2954.          ((get-text-property pos 'block-side)
  2955.           )
  2956.  
  2957.          ((and spaced (= state 0))
  2958.           (setq state 1)
  2959.           )
  2960.  
  2961.          ((and spaced (member state '(1 3 5)))
  2962.           )
  2963.  
  2964.          ((and spaced (= state 2))
  2965.           (setq state 3)
  2966.           )
  2967.  
  2968.          ((and spaced (= state 4))
  2969.           (setq state 5)
  2970.           )
  2971.  
  2972.          ((and (eq ?\n char) (not (member state '(7 8))))
  2973.           (web-mode-propertize-attr state char name-beg name-end val-beg)
  2974.           (setq state 1
  2975.                 name-beg nil
  2976.                 name-end nil
  2977.                 val-beg nil
  2978.                 val-end nil)
  2979.           )
  2980.  
  2981.          ((or (and (eq ?\" char) (= state 8) (not escaped))
  2982.              (and (eq ?\' char) (= state 7) (not escaped))
  2983.              (and (member char '(?\s ?\n ?\>)) (= state 6)))
  2984.          (web-mode-propertize-attr state char name-beg name-end val-beg)
  2985.          (setq state (if (= state 6) 1 0)
  2986.                name-beg nil
  2987.                name-end nil
  2988.                val-beg nil
  2989.                val-end nil)
  2990.          )
  2991.  
  2992.         ((and (not spaced) (= state 1))
  2993.          (setq state 2)
  2994.          (setq name-beg pos)
  2995.          )
  2996.  
  2997.         ((and (eq ?\= char) (member state '(2 3)))
  2998.          (setq name-end pos)
  2999.          (setq state 4)
  3000.          )
  3001.  
  3002.         ((and (eq ?\" char) (member state '(4 5)))
  3003.          (setq val-beg pos)
  3004.          (setq state 8)
  3005.          )
  3006.  
  3007.         ((and (eq ?\' char) (member state '(4 5)))
  3008.          (setq val-beg pos)
  3009.          (setq state 7)
  3010.          )
  3011.  
  3012.         ((member state '(4 5))
  3013.          (setq val-beg pos)
  3014.          (setq state 6)
  3015.          )
  3016.  
  3017.         ((= state 1)
  3018.          (setq state 2)
  3019.          )
  3020.  
  3021.         );;cond
  3022.  
  3023.        ;;        (message "point(%S) end(%S) state(%S) c(%S) name-beg(%S) name-end(%S) val-beg(%S) val-end(%S)" pos end state char name-beg name-end val-beg val-end)
  3024.  
  3025.        (setq escaped (eq ?\\ char))
  3026.  
  3027.        );;while
  3028.  
  3029.      )))
  3030.  
  3031. (defun web-mode-propertize-attr (state char name-beg name-end val-beg &optional val-end)
  3032.  "propertize attr."
  3033.  (unless val-end (setq val-end (point)))
  3034.  ;;  (message "point(%S) state(%S) c(%S) name-beg(%S) name-end(%S) val-beg(%S) val-end(%S)" (point) state char name-beg name-end val-beg val-end)
  3035.  (cond
  3036.   ((and (= state 8) (not (eq ?\" char)))
  3037.    )
  3038.   ((and (= state 7) (not (eq ?\' char)))
  3039.    )
  3040.   ((= state 4)
  3041.    )
  3042.   ((null name-beg)
  3043.    )
  3044.   (t
  3045.    (if (or (and (= state 8) (eq ?\" char))
  3046.            (and (= state 7) (eq ?\' char)))
  3047.        (add-text-properties name-beg (1+ (point)) '(part-token attr face web-mode-html-attr-name-face))
  3048.      (add-text-properties name-beg (point) '(part-token attr face web-mode-html-attr-name-face)))
  3049.    (when (and val-beg val-end)
  3050.      (setq val-end (if (eq ?\> char) val-end (1+ val-end)))
  3051.      (add-text-properties val-beg val-end '(face web-mode-html-attr-value-face)))
  3052.    );t
  3053.   );cond
  3054.  )
  3055.  
  3056. (defun web-mode-velocity-skip-forward (pos)
  3057.  "find the end of a velocity block."
  3058.  (goto-char pos)
  3059.  (let (continue)
  3060.    (when (eq ?\# (char-after))
  3061.      (forward-char))
  3062.    ;;(message "pt=%S %c" (point) (char-after))
  3063.    (when (member (char-after) '(?\$ ?\@))
  3064.      ;;              (message "pt=%S" (point))
  3065.      (forward-char))
  3066.    (when (member (char-after) '(?\!))
  3067.      ;;              (message "pt=%S" (point))
  3068.      (forward-char))
  3069.    (if (member (char-after) '(?\{))
  3070.        (search-forward "}")
  3071.      (setq continue t)
  3072.      (while continue
  3073.        (skip-chars-forward "a-zA-Z0-9_-")
  3074.        (when (member (char-after) '(?\())
  3075.          (search-forward ")")
  3076.          )
  3077.        (if (member (char-after) '(?\.))
  3078.            (forward-char)
  3079.          (setq continue nil))
  3080.        );while
  3081.      );if
  3082.    ))
  3083.  
  3084. (defun web-mode-razor-skip-forward (pos)
  3085.  "find the end of a razor block."
  3086.  (goto-char pos)
  3087.  ;;            (message "pt=%S %c" (point) (char-after))
  3088.  (let (continue)
  3089.    (cond
  3090.     ((looking-at-p "@\\(if\\|for\\|section\\)")
  3091.      (search-forward "{")
  3092.      )
  3093.     ((looking-at-p "@[(}]")
  3094.      (forward-char)
  3095.      (goto-char (web-mode-closing-paren-position (point) (line-end-position)))
  3096.      )
  3097.     (t
  3098.      (forward-char)
  3099.      (setq continue t)
  3100.      (while continue
  3101.        (skip-chars-forward " a-zA-Z0-9_-"); caractère 'espace' pour '} else {'
  3102.        (cond
  3103.         ((eq ?\( (char-after))
  3104.          (search-forward ")")
  3105.          )
  3106.         ((eq ?\. (char-after))
  3107.          (forward-char))
  3108.         ((looking-at-p "[ ]*{")
  3109.          (search-forward "}")
  3110.          )
  3111.         (t
  3112.          (setq continue nil))
  3113.         );cond
  3114.        );while
  3115.      )
  3116.     );cond
  3117.    ))
  3118.  
  3119. (defun web-mode-colorize-foreground (color)
  3120.  "Colorize foreground based on background luminance."
  3121.  (let* ((values (x-color-values color))
  3122.      (r (car values))
  3123.      (g (cadr values))
  3124.      (b (car (cdr (cdr values)))))
  3125.    (if (> 128.0 (floor (+ (* .3 r) (* .59 g) (* .11 b)) 256))
  3126.     "white" "black")))
  3127.  
  3128. (defun web-mode-colorize (beg end)
  3129.  "Colorize CSS colors."
  3130.  (let (str plist len)
  3131.    (setq str (buffer-substring-no-properties beg end))
  3132.    (setq len (length str))
  3133.    (cond
  3134.     ((string= (substring str 0 1) "#")
  3135.      (setq plist (list :background str
  3136.                        :foreground (web-mode-colorize-foreground str)))
  3137.      (put-text-property beg end 'face plist))
  3138.     ((string= (substring str 0 4) "rgb(")
  3139.      (setq str (format "#%02X%02X%02X"
  3140.                        (string-to-number (match-string-no-properties 1))
  3141.                        (string-to-number (match-string-no-properties 2))
  3142.                        (string-to-number (match-string-no-properties 3))))
  3143.      (setq plist (list :background str
  3144.                        :foreground (web-mode-colorize-foreground str)))
  3145.      (put-text-property beg end 'face plist))
  3146.     );cond
  3147.    ))
  3148.  
  3149. (defun web-mode-fontify-region (beg end keywords)
  3150.  "Highlight block."
  3151.  (save-excursion
  3152. ;;    (message "beg=%S end=%S" beg end)
  3153.    (let ((font-lock-keywords keywords)
  3154.          (font-lock-multiline nil)
  3155.          (font-lock-keywords-case-fold-search (member web-mode-engine
  3156.                                                       '("asp"
  3157.                                                         "template-toolkit")))
  3158.          (font-lock-keywords-only t)
  3159.          (font-lock-extend-region-functions nil)
  3160.          )
  3161.      (font-lock-fontify-region beg end)
  3162.      ))
  3163.  
  3164.  ;; UGLY HACK / workaround (help needed)
  3165.  (unless web-mode-buffer-highlighted
  3166.    (setq web-mode-buffer-highlighted t)
  3167.    (web-mode-fontify-region beg end keywords)
  3168.    )
  3169.  )
  3170.  
  3171. (defun web-mode-fill-paragraph (&optional justify)
  3172.  "fill paragraph"
  3173.  (save-excursion
  3174.    (let ((pos (point)) fill-coll
  3175.          prop pair beg end delim-beg delim-end chunk fill-col)
  3176.      (cond
  3177.       ((or (eq (get-text-property pos 'part-token) 'comment)
  3178.            (eq (get-text-property pos 'block-token) 'comment))
  3179.        (setq prop
  3180.              (if (get-text-property pos 'part-token) 'part-token 'block-token))
  3181.        (setq pair (web-mode-property-boundaries prop pos))
  3182.        (when (and pair (> (- (cdr pair) (car pair)) 6))
  3183.          (setq fill-coll (if (< fill-column 10) 70 fill-column))
  3184.          (setq beg (car pair)
  3185.                end (cdr pair))
  3186.          (goto-char beg)
  3187.          (setq chunk (buffer-substring-no-properties beg (+ beg 2)))
  3188.          (cond
  3189.           ((string= chunk "//")
  3190.            (setq delim-beg "//"
  3191.                  delim-end "EOL"))
  3192.           ((string= chunk "/*")
  3193.            (setq delim-beg "/*"
  3194.                 delim-end "*/"))
  3195.           ((string= chunk "{#")
  3196.            (setq delim-beg "{#"
  3197.                  delim-end "#}"))
  3198.           ((string= chunk "<!")
  3199.            (setq delim-beg "<!--"
  3200.                  delim-end "-->"))
  3201.           )
  3202.          ;;          (subst-char-in-region beg end ?\n ?\s)
  3203.          ;;          (message "fill-column=%S pt=%S pair=%S chunk=%S"
  3204.          ;;                   fill-column (point) pair chunk)
  3205.          )
  3206.        );comment - case
  3207.  
  3208.       ((web-mode-is-html-text)
  3209.        (setq pair (web-mode-property-boundaries prop pos))
  3210.        (setq beg (previous-property-change pos)
  3211.              end (next-property-change pos))
  3212.        )
  3213.  
  3214.       );cond
  3215.      ;;(message "beg%S end%S" beg end)
  3216.      (when (and beg end)
  3217.        (fill-region beg end))
  3218.      t)))
  3219.  
  3220. (defun web-mode-property-boundaries (prop &optional pos)
  3221.  "property boundaries (cdr is 1+)"
  3222.  (unless pos (setq pos (point)))
  3223.  (let (beg end val)
  3224.    (setq val (get-text-property pos prop))
  3225.    (if (null val)
  3226.        val
  3227.      (if (or (bobp)
  3228.              (not (eq (get-text-property (1- pos) prop) val)))
  3229.          (setq beg pos)
  3230.        (setq beg (previous-single-property-change pos prop))
  3231.        (when (null beg) (setq beg (point-min))))
  3232.      (if (or (eobp)
  3233.              (not (eq (get-text-property (1+ pos) prop) val)))
  3234.          (setq end pos)
  3235.        (setq end (next-single-property-change pos prop))
  3236.        (when (null end) (setq end (point-min))))
  3237.      (cons beg end))))
  3238.  
  3239. (defun web-mode-scan-whitespaces (beg end)
  3240.  "Scan whitespaces."
  3241.  (save-excursion
  3242.    (goto-char beg)
  3243.    (while (re-search-forward web-mode-whitespaces-regexp end t)
  3244.      (add-text-properties (match-beginning 0) (match-end 0)
  3245.                           '(face web-mode-whitespace-face))
  3246.      );while
  3247.    ))
  3248.  
  3249. (defun web-mode-errors-show ()
  3250.  "Show unclosed tags."
  3251.  (interactive)
  3252.  (let (beg end tag pos l n tags i cont cell overlay overlays first
  3253.            (ori (point))
  3254.            (errors 0)
  3255.            (continue t)
  3256.        )
  3257.    (setq overlays (overlays-in (point-min) (point-max)))
  3258.    (when overlays
  3259.      (dolist (overlay overlays)
  3260.        (when (eq (overlay-get overlay 'face) 'web-mode-warning-face)
  3261.          (delete-overlay overlay)
  3262.          )
  3263.        )
  3264.      )
  3265.    (goto-char (point-min))
  3266.    (when (not (or (get-text-property (point) 'tag-beg)
  3267.                   (web-mode-tag-next)))
  3268.      (setq continue nil))
  3269.    (while continue
  3270.      (setq pos (point))
  3271.      (setq tag (get-text-property pos 'tag-name))
  3272.      (cond
  3273.       ((eq (get-text-property (point) 'tag-type) 'start)
  3274.        (setq tags (add-to-list 'tags (list tag pos)))
  3275. ;;        (message "(%S) opening %S" pos tag)
  3276.        )
  3277.       ((eq (get-text-property (point) 'tag-type) 'end)
  3278.        (setq i 0
  3279.              l (length tags)
  3280.              cont t)
  3281.        (while (and (< i l) cont)
  3282.          (setq cell (nth i tags))
  3283. ;;          (message "cell=%S" cell)
  3284.          (setq i (1+ i))
  3285.          (cond
  3286.           ((string= tag (nth 0 cell))
  3287.            (setq cont nil)
  3288.            )
  3289.           (t
  3290.            (setq errors (1+ errors))
  3291.            (setq beg (nth 1 cell))
  3292.            (setq end (web-mode-tag-end-position beg))
  3293.            (unless first
  3294.              (setq first beg))
  3295.            (setq overlay (make-overlay beg (1+ end)))
  3296.            (overlay-put overlay 'face 'web-mode-warning-face)
  3297. ;;            (message "invalid <%S> at %S" (nth 0 cell) (nth 1 cell))
  3298.            )
  3299.           );cond
  3300.          );while
  3301.  
  3302.        (dotimes (i i)
  3303.          (setq tags (cdr tags))
  3304. ;;          (setq cell (nth i tags))
  3305. ;;          (message "removing=%S" cell)
  3306.          )
  3307.  
  3308.        )
  3309.       );cond
  3310.      (when (not (web-mode-tag-next))
  3311.        (setq continue nil))
  3312.      );while
  3313.    (message "%S error(s) detected" errors)
  3314.    (if (> errors 0)
  3315.        (progn (goto-char first)
  3316.               (recenter))
  3317.      (goto-char ori)
  3318.      );if
  3319.    ;;    (message "%S" tags)
  3320.    ))
  3321.  
  3322. (defun web-mode-whitespaces-show ()
  3323.  "Toggle whitespaces."
  3324.  (interactive)
  3325.  (if web-mode-enable-whitespaces
  3326.      (web-mode-whitespaces-off)
  3327.    (web-mode-whitespaces-on))
  3328.  (web-mode-scan-buffer))
  3329.  
  3330. (defun web-mode-whitespaces-on ()
  3331.  "Show whitespaces."
  3332.  (interactive)
  3333.  (when (null web-mode-display-table)
  3334.    ;;    http://webdesign.about.com/od/localization/l/blhtmlcodes-ascii.htm
  3335.    (setq web-mode-display-table (make-display-table))
  3336.    (aset web-mode-display-table 9  (vector ?\xBB ?\t)) ;tab
  3337.    (aset web-mode-display-table 10 (vector ?\xB6 ?\n)) ;line feed
  3338.    (aset web-mode-display-table 32 (vector ?\xB7)) ;space
  3339.    );when
  3340.  (when web-mode-hl-line-mode-flag
  3341.    (global-hl-line-mode -1))
  3342.  (setq buffer-display-table web-mode-display-table)
  3343.  (setq web-mode-enable-whitespaces t))
  3344.  
  3345. (defun web-mode-whitespaces-off ()
  3346.  "Hide whitespaces."
  3347.  (when web-mode-hl-line-mode-flag
  3348.    (global-hl-line-mode 1))
  3349.  (setq buffer-display-table nil)
  3350.  (setq web-mode-enable-whitespaces nil))
  3351.  
  3352. (defun web-mode-buffer-indent ()
  3353.  "Indent all buffer."
  3354.  (interactive)
  3355.  (indent-region (point-min) (point-max))
  3356.  (delete-trailing-whitespace))
  3357.  
  3358. (defun web-mode-buffer-refresh ()
  3359.  "Indent and fontify buffer."
  3360.  (interactive)
  3361.  (web-mode-scan-buffer)
  3362.  (web-mode-buffer-indent))
  3363.  
  3364. (defun web-mode-previous-usable-server-line ()
  3365.  "Return previous non blank/comment/string line and return this line (trimmed)."
  3366.  (interactive)
  3367.  (save-excursion
  3368.    (let ((continue t)
  3369.          (line "")
  3370.          (pos (point)))
  3371.      (beginning-of-line)
  3372.      (while (and continue
  3373.                  (not (bobp))
  3374.                  (forward-line -1))
  3375.        (if (not (web-mode-is-comment-or-string-line))
  3376.            (setq line (web-mode-trim (buffer-substring (point) (line-end-position)))))
  3377.        (when (not (string= line "")) (setq continue nil))
  3378.        );while
  3379.      (if (string= line "")
  3380.          (progn (goto-char pos) nil)
  3381.        (cons line (current-indentation)))
  3382.      )))
  3383.  
  3384. (defun web-mode-previous-usable-client-line ()
  3385.  "Return previous non blank/comment/string line and return this line (trimmed)."
  3386.  (interactive)
  3387.  (save-excursion
  3388.    (let ((continue t)
  3389.          (line "")
  3390.          (pos (point)))
  3391.      (beginning-of-line)
  3392.      (while (and continue
  3393.                  (not (bobp))
  3394.                  (forward-line -1))
  3395.        (if (not (web-mode-is-part-token-line))
  3396.            (setq line (web-mode-trim (buffer-substring (point) (line-end-position)))))
  3397.        (when (not (string= line "")) (setq continue nil))
  3398.        )
  3399.      (if (string= line "")
  3400.          (progn (goto-char pos) nil)
  3401.        (cons line (current-indentation)))
  3402.      )))
  3403.  
  3404. (defun web-mode-in-code-block (open close &optional prop)
  3405.  "Detect if point is in a block delimited by open and close."
  3406.  (save-excursion
  3407.    (let ((pos (point)) pos-open pos-close start end ret)
  3408.      (when prop
  3409.        (setq start pos
  3410.              end pos)
  3411.        (when (eq (get-text-property pos prop) (get-text-property (1- pos) prop))
  3412.          (setq start (or (previous-single-property-change pos prop) (point-min))))
  3413.        (when (eq (get-text-property pos prop) (get-text-property (1+ pos) prop))
  3414.          (setq end (next-single-property-change pos prop)))
  3415.        ;;        (message "start(%S) end(%S)" start end)
  3416.        )
  3417.      (setq ret (and (web-mode-sb open start t)
  3418.                     (setq pos-open (point))
  3419.                     (web-mode-sf close end t)
  3420.                     (setq pos-close (point))
  3421.                     (>= pos-close pos)))
  3422.      (if ret
  3423.          (cons pos-open pos-close)
  3424.        ret)
  3425.      )))
  3426.  
  3427. (defun web-mode-line-number (&optional pos)
  3428.  "Return line number at point."
  3429.  (unless pos (setq pos (point)))
  3430.  (let (ret)
  3431.    (setq ret (+ (count-lines 1 pos)
  3432.                 (if (= (web-mode-column-at-pos pos) 0) 1 0)))
  3433.    ret))
  3434.  
  3435. (defun web-mode-clean-client-line (input)
  3436.  "Remove comments and server scripts."
  3437.  (let ((out "")
  3438.        (beg 0)
  3439.        (keep t)
  3440.        (n (length input)))
  3441.    (dotimes (i n)
  3442.      (if (or (get-text-property i 'block-side input)
  3443.              (eq (get-text-property i 'part-token input) 'comment))
  3444.          (when keep
  3445.            (setq out (concat out (substring input beg i))
  3446.                  beg 0
  3447.                  keep nil))
  3448.        (when (null keep)
  3449.          (setq beg i
  3450.                keep t))
  3451.        );if
  3452.      ;;      (message "out=%s beg=%d" out beg)
  3453.      );dotimes
  3454.    (if (> beg 0) (setq out (concat out (substring input beg n))))
  3455.    (setq out (if (= (length out) 0) input out))
  3456.    (web-mode-trim out)
  3457.    ;;    (message "%S [%s] > [%s]" beg input out)
  3458.    ))
  3459.  
  3460. (defun web-mode-clean-server-line (input)
  3461.  "Remove comments from server line."
  3462.  (let ((out "")
  3463.        (beg 0)
  3464.        (keep t)
  3465.        (n (length input)))
  3466.    (dotimes (i n)
  3467.      (if (eq (get-text-property i 'block-token input) 'comment)
  3468.          (when keep
  3469.            (setq out (concat out (substring input beg i))
  3470.                  beg 0
  3471.                  keep nil))
  3472.        (when (null keep)
  3473.          (setq beg i
  3474.                keep t))
  3475.        );if
  3476.      );dotimes
  3477.    (if (> beg 0) (setq out (concat out (substring input beg n))))
  3478.    (setq out (if (= (length out) 0) input out))
  3479.    (web-mode-trim out)
  3480.    ;;    (message "%S [%s] > [%s]" beg input out)
  3481.    ))
  3482.  
  3483. (defun web-mode-column-at-pos (&optional pos)
  3484.  "Column at point"
  3485.  (unless pos (setq pos (point)))
  3486.  (save-excursion
  3487.    (goto-char pos)
  3488.    (current-column)
  3489.    ))
  3490.  
  3491. ;; doit-on considérer que '=' est un bloc ouvrant avec ';' comme char de fin ?
  3492. (defun web-mode-point-context (pos)
  3493.  "POS should be at the beginning of the indentation.
  3494.    Return ctx = plist containing
  3495.     :block-beg, :block-column,
  3496.     :first-char, :line (trimmed)
  3497.     :type (live, comment, string),
  3498.     :language (html, php, jsp, aspx, asp + javascript, css),
  3499.     :indent-offset
  3500.     :prev-line :prev-char :prev-props :prev-indentation"
  3501.  (save-excursion
  3502.    (let (ctx pos-min
  3503.              block-beg block-column first-char line type language indent-offset
  3504.              prev prev-line prev-char prev-props prev-indentation)
  3505.  
  3506.      (setq pos-min (point-min))
  3507.      (setq block-beg pos-min
  3508.            block-column 0
  3509.            type "live"
  3510.            language ""
  3511.            prev-line ""
  3512.            prev-char 0)
  3513.      (cond
  3514.  
  3515.       ((bobp)
  3516.        )
  3517.  
  3518.       ((string= web-mode-content-type "css")
  3519.        (setq language "css"
  3520.              indent-offset web-mode-css-indent-offset))
  3521.  
  3522.       ((member web-mode-content-type '("javascript" "json"))
  3523.        (setq language "javascript"
  3524.              indent-offset web-mode-code-indent-offset))
  3525.  
  3526.       ((string= web-mode-content-type "php")
  3527.        (setq language "php"
  3528.              indent-offset web-mode-code-indent-offset))
  3529.  
  3530.       ((or (string= web-mode-content-type "xml"))
  3531.        (setq language "xml"
  3532.              indent-offset web-mode-markup-indent-offset))
  3533.  
  3534.       ((and (get-text-property pos 'tag-beg)
  3535.             (get-text-property pos 'tag-name))
  3536.        (setq language "html"
  3537.              indent-offset web-mode-markup-indent-offset)
  3538.        )
  3539.  
  3540.       ((or (and (eq (get-text-property pos 'part-token) 'comment)
  3541.                 (eq (get-text-property (1- pos) 'part-token) 'comment)
  3542.                 (progn
  3543.                   (setq block-beg (previous-single-property-change pos 'part-token))
  3544.                   t))
  3545.            (and (eq (get-text-property pos 'block-token) 'comment)
  3546.                 (eq (get-text-property (1- pos) 'block-token) 'comment)
  3547.                 (progn
  3548.                   (setq block-beg (previous-single-property-change pos 'block-token))
  3549.                   t)))
  3550.        (setq type "comment"))
  3551.  
  3552.       ((or (and (eq (get-text-property pos 'part-token) 'string)
  3553.                 (eq (get-text-property (1- pos) 'part-token) 'string))
  3554.            (and (eq (get-text-property pos 'block-token) 'string)
  3555.                 (eq (get-text-property (1- pos) 'block-token) 'string)))
  3556.        (setq type "string"))
  3557.  
  3558.       ((and (get-text-property pos 'block-side)
  3559.             (not (get-text-property pos 'block-beg)))
  3560.        (setq block-beg (or (web-mode-block-beginning-position pos) pos-min))
  3561.        (goto-char block-beg)
  3562.        (setq block-column (current-column))
  3563.        (setq language web-mode-engine)
  3564.        (setq indent-offset web-mode-code-indent-offset)
  3565.        (cond
  3566.         ((string= web-mode-engine "blade")
  3567.          (setq block-beg (+ block-beg 2)
  3568.                block-column (+ block-column 2))
  3569.          )
  3570.         ((string= web-mode-engine "razor")
  3571.          (setq block-beg (+ block-beg 2)
  3572.                block-column (+ block-column 2))
  3573.          )
  3574.         ((string= web-mode-engine "template-toolkit")
  3575.          (setq block-beg (+ block-beg 3)
  3576.                block-column (+ block-column 3))
  3577.          )
  3578.         ((and (string= web-mode-engine "jsp")
  3579.               (web-mode-looking-at-pos "<%@\\|<[[:alpha:]]" block-beg))
  3580.          (save-excursion
  3581.            (goto-char block-beg)
  3582.            (looking-at "<%@[ ]*[[:alpha:]]+[ ]+\\|</?[[:alpha:]]+:[[:alpha:]]+[ ]+")
  3583.            (goto-char (match-end 0))
  3584.            (setq block-column (current-column))
  3585.            )
  3586.          )
  3587.         ((and (string= web-mode-engine "freemarker")
  3588.               (web-mode-looking-at-pos "<@\\|<%@\\|<[[:alpha:]]" block-beg))
  3589.          (save-excursion
  3590.            (goto-char block-beg)
  3591.            (looking-at "<@[[:alpha:].]+[ ]+\\|<%@[ ]*[[:alpha:]]+[ ]+\\|<[[:alpha:]]+:[[:alpha:]]+[ ]+")
  3592.            (goto-char (match-end 0))
  3593.            (setq block-column (current-column))
  3594.            )
  3595.          )
  3596.         );cond
  3597.        )
  3598.  
  3599.       ((and (get-text-property pos 'part-side)
  3600.             (get-text-property pos 'part-language))
  3601.        (setq block-beg (or (previous-single-property-change pos 'part-side) pos-min))
  3602.        (goto-char block-beg)
  3603.        (search-backward "<")
  3604.        (setq block-column (current-column))
  3605.        (setq language (symbol-name (get-text-property pos 'part-language)))
  3606.        (cond
  3607.         ((string= language "css")
  3608.          (setq indent-offset web-mode-css-indent-offset)
  3609.          )
  3610.         (t
  3611.          (setq language "javascript"
  3612.                indent-offset web-mode-code-indent-offset)
  3613.          )
  3614.         )
  3615.        )
  3616.  
  3617.       (t
  3618.        (setq language "html"
  3619.              indent-offset web-mode-markup-indent-offset)
  3620.        )
  3621.  
  3622.       );cond
  3623.  
  3624.      (goto-char pos)
  3625.      (setq line (web-mode-trim (buffer-substring-no-properties (line-beginning-position)
  3626.                                                                (line-end-position))))
  3627.      (setq first-char (if (string= line "") 0 (aref line 0)))
  3628.  
  3629.      (when (or (member language '("php" "javascript"))
  3630.                (and (string= language "html") (not (eq ?\< first-char))))
  3631.        (cond
  3632.         ((member language '("html" "javascript"))
  3633.          (setq prev (web-mode-previous-usable-client-line))
  3634.          ;;          (message "prev-line=%S" prev-line)
  3635.          (when prev
  3636.            (setq prev-line (car prev)
  3637.                  prev-indentation (cdr prev))
  3638.            (setq prev-line (web-mode-clean-client-line prev-line))
  3639.            (setq prev-props (text-properties-at (1- (length prev-line)) prev-line)))
  3640.          )
  3641.         (t
  3642.          (setq prev (web-mode-previous-usable-server-line))
  3643.          (when prev
  3644.            (setq prev-line (car prev)
  3645.                  prev-indentation (cdr prev))
  3646.            (setq prev-line (web-mode-clean-server-line prev-line)))
  3647.          )
  3648.         );cond
  3649.        (when (>= (length prev-line) 1)
  3650.          (setq prev-char (aref prev-line (1- (length prev-line))))
  3651.          (setq prev-line (substring-no-properties prev-line))
  3652.          )
  3653.        )
  3654.  
  3655. ;;      (if (string= language "json") (setq language "javascript"))
  3656.  
  3657.      (when (string= web-mode-content-type "html")
  3658.        (cond
  3659.         ((string= language "javascript")
  3660.          (setq block-column (+ block-column web-mode-script-padding)))
  3661.         ((string= language "css")
  3662.          (setq block-column (+ block-column web-mode-style-padding)))
  3663.         ((not (member language '("html" "razor")))
  3664.          (setq block-column (+ block-column web-mode-block-padding)))
  3665.         )
  3666.        )
  3667.  
  3668.      (setq ctx (list :block-beg block-beg
  3669.                      :block-column block-column
  3670.                      :first-char first-char
  3671.                      :line line
  3672.                      :type type
  3673.                      :language language
  3674.                      :indent-offset indent-offset
  3675.                      :prev-line prev-line
  3676.                      :prev-char prev-char
  3677.                      :prev-props prev-props
  3678.                      :prev-indentation prev-indentation))
  3679. ;;      (message "%S" ctx)
  3680.      ctx
  3681.      )))
  3682.  
  3683. (defun web-mode-indent-line ()
  3684.  "Indent current line according to language."
  3685.  (let ((inhibit-modification-hooks t)
  3686.        pos
  3687.        offset
  3688.        ctx
  3689.        block-beg
  3690.        block-column
  3691.        first-char
  3692.        line
  3693.        type
  3694.        language
  3695.        indent-offset
  3696.        prev-line
  3697.        prev-char
  3698.        prev-props
  3699.        prev-indentation)
  3700.  
  3701.    (save-excursion
  3702.      (back-to-indentation)
  3703.      (setq pos (point))
  3704.      (setq ctx (web-mode-point-context pos))
  3705.      (setq block-beg (plist-get ctx :block-beg))
  3706.      (setq block-column (plist-get ctx :block-column))
  3707.      (setq first-char (plist-get ctx :first-char))
  3708.      (setq line (plist-get ctx :line))
  3709.      (setq type (plist-get ctx :type))
  3710.      (setq language (plist-get ctx :language))
  3711.      (setq indent-offset (plist-get ctx :indent-offset))
  3712.      (setq prev-line (plist-get ctx :prev-line))
  3713.      (setq prev-char (plist-get ctx :prev-char))
  3714.      (setq prev-props (plist-get ctx :prev-props))
  3715.      (setq prev-indentation (plist-get ctx :prev-indentation))
  3716.  
  3717.      (cond
  3718.  
  3719.       ((or (bobp)
  3720.            (= (line-number-at-pos pos) 1))
  3721.        (setq offset 0)
  3722.        )
  3723.  
  3724.       ((string= type "string")
  3725.        (setq offset nil)
  3726.        )
  3727.  
  3728.       ((string= type "comment")
  3729.        (goto-char (car
  3730.                    (web-mode-property-boundaries
  3731.                     (if (eq (get-text-property pos 'part-token) 'comment)
  3732.                         'part-token
  3733.                       'block-token)
  3734.                     pos)))
  3735.        (setq offset (current-column))
  3736.        (cond
  3737.         ((and (string= (buffer-substring-no-properties (point) (+ (point) 2)) "/*")
  3738.                   (eq ?\* first-char))
  3739.          (setq offset (1+ offset)))
  3740.         ((and (string= web-mode-engine "django")
  3741.               (looking-back "{% comment %}"))
  3742.          (setq offset (- offset 12))
  3743.          )
  3744.         );cond
  3745.        );case comment
  3746.  
  3747.       ((member language '("php" "jsp" "asp" "aspx" "javascript" "code" "python" "erb" "freemarker" "blade" "template-toolkit"))
  3748.  
  3749.        (cond
  3750.  
  3751.         ((string-match-p "^[?%]>" line)
  3752.          (if (web-mode-block-beginning pos)
  3753.              (setq offset (current-column)))
  3754.          )
  3755.  
  3756.         ((and (string-match-p "^[=]?%]" line)
  3757.               (string= web-mode-engine "template-toolkit"))
  3758.          (if (web-mode-block-beginning pos)
  3759.              (setq offset (current-column)))
  3760.          )
  3761.  
  3762.  
  3763.         ((and (string= language "php") (string-match-p "^->" line))
  3764.          (when (web-mode-sb "->" block-beg)
  3765.            (setq offset (current-column)))
  3766.          )
  3767.  
  3768.         ((and (string= language "php")
  3769.               (or (string-match-p "^else$" prev-line)
  3770.                   (string-match-p "^if[ ]*(.+)$" prev-line)))
  3771.          (setq offset (+ prev-indentation web-mode-code-indent-offset))
  3772.          )
  3773.  
  3774.         ((and (string= language "javascript") (eq ?\. first-char))
  3775.          (when (web-mode-rsb "[[:alnum:][:blank:]]\\.[[:alpha:]]" block-beg)
  3776.            (setq offset (1+ (current-column))))
  3777.          )
  3778.  
  3779.         ((member first-char '(?\? ?\. ?\:))
  3780.          (web-mode-rsb "[^!=][=(]" block-beg)
  3781.          (setq offset (1+ (current-column)))
  3782.          (when (and (string= web-mode-engine "php")
  3783.                     (looking-at-p " =>"))
  3784.            (setq offset (1+ offset))
  3785.            )
  3786.          )
  3787.  
  3788.         ((and (member prev-char '(?\. ?\+ ?\? ?\:))
  3789.               (not (string-match-p "^\\(case\\|default\\)[ :]" prev-line)))
  3790.          (web-mode-rsb "[=(]" block-beg)
  3791.          (skip-chars-forward "= (")
  3792.          (setq offset (current-column))
  3793.          )
  3794.  
  3795.         ((string= language "erb")
  3796.          (setq offset (web-mode-ruby-indentation pos
  3797.                                                  line
  3798.                                                  block-column
  3799.                                                  indent-offset
  3800.                                                  block-beg))
  3801.          )
  3802.  
  3803.         ((string= language "asp")
  3804.          (setq offset (web-mode-asp-indentation pos
  3805.                                                 line
  3806.                                                 block-column
  3807.                                                 indent-offset
  3808.                                                 block-beg))
  3809.          )
  3810.  
  3811.         (t
  3812.          (setq offset (web-mode-bracket-indentation pos
  3813.                                                     block-column
  3814.                                                     indent-offset
  3815.                                                     block-beg))
  3816.          );t
  3817.  
  3818.         ));end case script block
  3819.  
  3820.       ((string= language "css")
  3821.        (setq offset (web-mode-bracket-indentation pos
  3822.                                                   block-column
  3823.                                                   indent-offset
  3824.                                                   block-beg))
  3825.        );case style
  3826.  
  3827.       (t ; case html block
  3828.  
  3829.        (cond
  3830.  
  3831.         ((and prev-props (eq (plist-get prev-props 'part-token) 'attr))
  3832.          (web-mode-tag-beginning)
  3833.          (let (skip)
  3834.            (setq skip (next-single-property-change (point) 'part-token))
  3835.            (when skip
  3836.              (goto-char skip)
  3837.              (setq offset (current-column))
  3838.              ))
  3839.          )
  3840.  
  3841.         ((or (and (eq (get-text-property pos 'tag-type) 'end)
  3842.                   (web-mode-match-html-tag))
  3843.              (and (get-text-property pos 'block-beg)
  3844.                   (looking-at-p web-mode-close-block-regexp)
  3845.                   (funcall web-mode-engine-control-matcher))
  3846.              )
  3847.          (setq offset (current-indentation))
  3848.          )
  3849.  
  3850.         ((or (eq (length line) 0)
  3851.              (= web-mode-indent-style 2)
  3852.              (get-text-property pos 'tag-beg)
  3853.              (get-text-property pos 'block-beg))
  3854.          (setq offset (web-mode-markup-indentation pos))
  3855.          )
  3856.  
  3857.         );cond
  3858.  
  3859.        );end case html block
  3860.  
  3861.       );end switch language block
  3862.  
  3863.      );save-excursion
  3864.  
  3865.    (when offset
  3866.      (let ((diff (- (current-column) (current-indentation))))
  3867.        (setq offset (max 0 offset))
  3868.        (indent-line-to offset)
  3869.        (if (> diff 0) (forward-char diff))
  3870.        );let
  3871.      );when
  3872.  
  3873.    ))
  3874.  
  3875. (defun web-mode-is-active-block (pos)
  3876.  "web-mode-is-active-block"
  3877.  (save-excursion
  3878.    (let (ctrl state)
  3879.      (goto-char pos) ;;(message "pos=%S" pos)
  3880.      (when (looking-at web-mode-active-block-regexp)
  3881.  
  3882.        (cond
  3883.  
  3884.         ((string= web-mode-engine "php")
  3885.          (setq ctrl (match-string-no-properties 3))
  3886.          (if (member ctrl '("else" "elseif"))
  3887.              (setq ctrl nil)
  3888.            (setq state (not (string= "end" (match-string-no-properties 2))))
  3889.            )
  3890.          )
  3891.  
  3892.         ((string= web-mode-engine "django")
  3893.          (setq ctrl (match-string-no-properties 2))
  3894.          (if (member ctrl '("else" "elseif" "elif" "empty"))
  3895.              (setq ctrl nil)
  3896.            (setq state (not (string= "end" (match-string-no-properties 1))))
  3897.            )
  3898.          )
  3899.  
  3900.         ((string= web-mode-engine "smarty")
  3901.          (setq ctrl (match-string-no-properties 1))
  3902.          (if (member ctrl '("else" "elseif"))
  3903.              (setq ctrl nil)
  3904.            (setq state (not (eq ?\/ (aref (match-string-no-properties 0) 1))))
  3905.            )
  3906.          )
  3907.  
  3908.         ((string= web-mode-engine "dust")
  3909.          (setq ctrl (match-string-no-properties 1))
  3910.          (if (or (member ctrl '("else"))
  3911.                  (eq ?\/ (char-after (1- (web-mode-block-end-position)))))
  3912.              (setq ctrl nil)
  3913.            (setq state (not (eq ?\/ (aref (match-string-no-properties 0) 1))))
  3914.            )
  3915.          )
  3916.  
  3917.         ((string= web-mode-engine "closure")
  3918.          (setq ctrl (match-string-no-properties 1))
  3919.          (if (or (member ctrl '("else" "elseif" "case" "default"))
  3920.                  (eq ?\/ (char-after (1- (web-mode-block-end-position)))))
  3921.              (setq ctrl nil)
  3922.            (setq state (not (eq ?\/ (aref (match-string-no-properties 0) 1))))
  3923.            )
  3924.          )
  3925.  
  3926.         ((string= web-mode-engine "ctemplate")
  3927.          (setq ctrl (match-string-no-properties 1))
  3928.          (setq state (not (eq ?\/ (aref (match-string-no-properties 0) 2))))
  3929.          )
  3930.  
  3931.         ((string= web-mode-engine "velocity")
  3932.          (setq ctrl (match-string-no-properties 1))
  3933.          (if (member ctrl '("else" "elseif"))
  3934.              (setq ctrl nil)
  3935.            (setq state (not (string= "end" (match-string-no-properties 1))))
  3936.            )
  3937.          )
  3938.  
  3939.         ((string= web-mode-engine "blade")
  3940.          (setq ctrl (match-string-no-properties 2))
  3941.          (cond
  3942.           ((string= ctrl "stop")
  3943.            (setq ctrl "section"))
  3944.           ((member ctrl '("else" "elseif"))
  3945.            (setq ctrl nil))
  3946.           (t
  3947.            (setq state (not (string= "end" (match-string-no-properties 1)))))
  3948.           )
  3949.          )
  3950.  
  3951.         ((string= web-mode-engine "go")
  3952.          (setq ctrl (match-string-no-properties 1))
  3953.          (if (member ctrl '("else"))
  3954.              (setq ctrl nil)
  3955.            (setq state (not (string= "end" ctrl)))
  3956.            )
  3957.          )
  3958.  
  3959.         ((string= web-mode-engine "erb")
  3960.          (setq ctrl (match-string-no-properties 1))
  3961.          (if (member ctrl '("else"))
  3962.              (setq ctrl nil)
  3963.            (setq state (not (string= "end" ctrl)))
  3964.            )
  3965.          )
  3966.  
  3967.         ((string= web-mode-engine "template-toolkit")
  3968.          (setq ctrl (match-string-no-properties 1))
  3969.          (if (member ctrl '("else"))
  3970.              (setq ctrl nil)
  3971.            (setq state (not (string= "end" ctrl)))
  3972.            )
  3973.          )
  3974.  
  3975.         ((string= web-mode-engine "jsp")
  3976.          (cond
  3977.           ((eq (aref (match-string-no-properties 0) 1) ?\%)
  3978.            (setq ctrl (match-string-no-properties 2)
  3979.                  state t)
  3980.            )
  3981.           (t
  3982.            (setq ctrl (match-string-no-properties 1))
  3983.            (if (or (member ctrl '("h:inputtext" "jsp:usebean" "jsp:forward" "struts:property"))
  3984.                    (eq ?\/ (char-after (1- (web-mode-block-end-position)))))
  3985.                (setq ctrl nil)
  3986.              (setq state (not (eq ?\/ (aref (match-string-no-properties 0) 1))))
  3987.              )
  3988.            )
  3989.           )
  3990.          )
  3991.  
  3992.         ((string= web-mode-engine "freemarker")
  3993.          (if (or (member (aref (match-string-no-properties 0) 1) '(?\@ ?\#))
  3994.                  (member (aref (match-string-no-properties 0) 2) '(?\@ ?\#)))
  3995.              (setq ctrl (match-string-no-properties 2))
  3996.            (setq ctrl (match-string-no-properties 1))
  3997.            )
  3998. ;;          (message "ctrl=%S" ctrl)
  3999.          (if (or (member ctrl '("include" "setting" "import" "global" "ftl"
  4000.                                 "nested" "return" "local" "flush" "break" "recover"))
  4001.                  (eq ?\/ (char-after (1- (web-mode-block-end-position)))))
  4002.              (setq ctrl nil)
  4003.            (setq state (not (eq ?\/ (aref (match-string-no-properties 0) 1))))
  4004.            )
  4005.          )
  4006.  
  4007.         ((string= web-mode-engine "underscore")
  4008.          (cond
  4009.           ((web-mode-block-ends-with "{ %>")
  4010.            (setq ctrl "ctrl"
  4011.                  state t))
  4012.           ((looking-at-p "<% }")
  4013.            (setq ctrl "ctrl"
  4014.                  state nil))
  4015.           )
  4016.          )
  4017.  
  4018.         );cond
  4019.  
  4020.        );when
  4021.  
  4022. ;;      (message "engine=%S ctrl=%S state=%S" web-mode-engine ctrl state)
  4023.  
  4024.      (if ctrl (cons ctrl state) nil)
  4025.      )))
  4026.  
  4027. (defun web-mode-markup-indentation-origin ()
  4028.  "web-mode-indentation-origin-pos"
  4029.  (let ((continue t) pos)
  4030.    (while continue
  4031.      (forward-line -1)
  4032.      (back-to-indentation)
  4033.      (setq continue (not (bobp)))
  4034.      (when (or (get-text-property (point) 'tag-beg)
  4035.                (and (get-text-property (point) 'block-beg)
  4036.                     (web-mode-is-active-block (point))
  4037.                     (not (looking-at-p "{% comment"))))
  4038.        (setq continue nil
  4039.              pos (point))
  4040.        )
  4041.      );while
  4042.    (message "indent-origin=%S" pos)
  4043.    pos
  4044.    ))
  4045.  
  4046. (defun web-mode-markup-indentation (pos)
  4047.  "markup indentation"
  4048.  (save-excursion
  4049.    (goto-char pos)
  4050.    (let ((offset 0) beg ret)
  4051.      (setq beg (web-mode-markup-indentation-origin))
  4052.      (when beg
  4053.        (goto-char beg)
  4054.        (setq ret (web-mode-is-opened-element beg pos))
  4055.        (cond
  4056.         ((null ret)
  4057.          (setq offset (current-indentation)))
  4058.         ((eq ret t)
  4059.          (setq offset (+ (current-indentation) web-mode-markup-indent-offset))
  4060.          )
  4061.         (t
  4062.          (setq offset ret))
  4063.         )
  4064. ;;        (setq offset (+ (current-indentation)
  4065. ;;                        (if (web-mode-is-opened-element beg pos)
  4066. ;;                            web-mode-markup-indent-offset
  4067. ;;                          0)))
  4068.        );when
  4069.      offset
  4070.      )))
  4071.  
  4072. ;; state(t) <=> start tag
  4073. (defun web-mode-is-opened-element (pos limit)
  4074.  "Is there any HTML element without a closing tag ?"
  4075.  (interactive)
  4076.  (let (tag
  4077.        last-tag
  4078.        tag-pos block-pos
  4079.        state
  4080.        n
  4081.        ret
  4082.        (continue t)
  4083.        (buffer (current-buffer))
  4084.        (h (make-hash-table :test 'equal))
  4085.        (h2 (make-hash-table :test 'equal))
  4086.        ctrl)
  4087.    (while continue
  4088.      (setq ctrl nil
  4089.            last-tag nil)
  4090.      (when (or (and (get-text-property pos 'tag-beg)
  4091.                     (member (get-text-property pos 'tag-type) '(start end)))
  4092.                (and (get-text-property pos 'block-beg)
  4093.                     (setq ctrl (web-mode-is-active-block pos))))
  4094.        (if ctrl
  4095.            (setq tag (car ctrl)
  4096.                  state (cdr ctrl))
  4097.          (setq tag (get-text-property pos 'tag-name)
  4098.                state (eq (get-text-property pos 'tag-type) 'start))
  4099.          (if (null state) (setq last-tag (cons tag pos)))
  4100.          )
  4101.  
  4102.        (setq n (gethash tag h 0))
  4103.        (if (null state)
  4104.            (progn
  4105.              (when (> n 0) (puthash tag (1- n) h))
  4106.              (puthash tag (1- n) h2))
  4107.          (puthash tag (1+ n) h)
  4108.          (puthash tag (1+ n) h2))
  4109.        );when
  4110.      (setq pos (1+ pos))
  4111.      (when (null tag-pos)
  4112.        (setq tag-pos (next-single-property-change pos 'tag-beg buffer limit)))
  4113.      (when (null block-pos)
  4114.        (setq block-pos (next-single-property-change pos 'block-beg buffer limit)))
  4115.      (cond
  4116.       ((and (null tag-pos)
  4117.             (null block-pos))
  4118.        (setq pos nil)
  4119.        )
  4120.       ((or (null block-pos)
  4121.            (< tag-pos block-pos))
  4122.        (setq pos tag-pos)
  4123.        (setq tag-pos nil)
  4124.        )
  4125.       (t
  4126.        (setq pos block-pos)
  4127.        (setq block-pos nil)
  4128.        )
  4129.       )
  4130.      (when (or (null pos)
  4131.                (>= pos limit))
  4132.        (setq continue nil))
  4133.      );while
  4134. ;;    (message "hashtable=%S" h)
  4135.    (maphash (lambda (k v) (if (> v 0) (setq ret t))) h)
  4136.    (when (and (null ret)
  4137.               last-tag
  4138.               (> (hash-table-count h2) 1)
  4139.               (< (gethash (car last-tag) h2) 0))
  4140. ;;      (message "last-tag=%S" last-tag)
  4141.      (save-excursion
  4142.        (goto-char (cdr last-tag))
  4143.        (web-mode-match-html-tag)
  4144.        (when (not (= (point) (cdr last-tag)))
  4145.          (setq n (point))
  4146.          (back-to-indentation)
  4147.          (if (= n (point)) (setq ret (current-indentation))))
  4148.        ))
  4149.    ret))
  4150.  
  4151. (defun web-mode-ruby-indentation (pos line initial-column language-offset limit)
  4152.  "Calc indent column."
  4153.  (interactive)
  4154.  (unless limit (setq limit nil))
  4155.  (let (h out prev-line prev-indentation)
  4156.    (setq h (web-mode-previous-line pos limit))
  4157.    (setq out initial-column)
  4158.    (when h
  4159.      (setq prev-line (car h))
  4160.      (setq prev-indentation (cdr h))
  4161.      (cond
  4162.       ((string-match-p "^\\(end\\|else\\|elsif\\|when\\)" line)
  4163.        (setq out (- prev-indentation language-offset))
  4164.        )
  4165.       ((string-match-p "\\(when\\|if\\|else\\|elsif\\|unless\\|for\\|while\\|def\\|class\\)" prev-line)
  4166.        (setq out (+ prev-indentation language-offset))
  4167.        )
  4168.       (t
  4169.        (setq out prev-indentation)
  4170.        )
  4171.       )
  4172.      );when
  4173.    out
  4174.    ))
  4175.  
  4176. (defun web-mode-asp-indentation (pos line initial-column language-offset limit)
  4177.  "Calc indent column."
  4178.  (interactive)
  4179.  (unless limit (setq limit nil))
  4180.  (let (h out prev-line prev-indentation)
  4181.    (setq h (web-mode-previous-line pos limit))
  4182.    (setq out initial-column)
  4183.    (when h
  4184.      (setq prev-line (car h))
  4185.      (setq prev-indentation (cdr h))
  4186.      (cond
  4187.       ;; ----------------------------------------------------------------------
  4188.       ;; unindent
  4189.       ((string-match-p "\\<\\(\\(end \\(if\\|function\\|class\\|sub\\|with\\)\\)\\|else\\|elseif\\|next\\|loop\\)\\>" line)
  4190.        (setq out (- prev-indentation language-offset)))
  4191.       ;; ----------------------------------------------------------------------
  4192.       ;; select case statement
  4193.       ((string-match-p "\\<\\(select case\\)\\>" line)
  4194.        (setq out (- prev-indentation 0)))
  4195.       ((string-match-p "\\<\\(end select\\)" line)
  4196.        (setq out (- prev-indentation (* 2 language-offset))))
  4197.       ((and (string-match-p "\\<\\(case\\)\\>" line) (not (string-match-p "\\<\\(select case\\)\\>" prev-line)))
  4198.        (setq out (- prev-indentation language-offset)))
  4199.       ;; ----------------------------------------------------------------------
  4200.       ;; do nothing
  4201.       ((string-match-p "\\<\\(\\(end \\(if\\|function\\|class\\|sub\\|select\\|with\\)\\)\\|loop\\( until\\| while\\)?\\)\\>" prev-line)
  4202.        (setq out (+ prev-indentation 0)))
  4203.       ;; indent
  4204.       ((string-match-p "\\<\\(\\(select \\)?case\\|else\\|elseif\\|unless\\|for\\|class\\|with\\|do\\( until\\| while\\)?\\|while\\|\\(public \\|private \\)?\\(function\\|sub\\|class\\)\\)\\>" prev-line)
  4205.        (setq out (+ prev-indentation language-offset)))
  4206.       ;; single line if statement
  4207.       ((string-match-p "\\<if\\>.*\\<then\\>[ \t]*[[:alpha:]]+" prev-line)
  4208.        (setq out (+ prev-indentation 0)))
  4209.       ;; normal if statement
  4210.       ((string-match-p "\\<\\if\\>" prev-line)
  4211.        (setq out (+ prev-indentation language-offset)))
  4212.       (t
  4213.        (setq out prev-indentation))
  4214.       )
  4215.      );when
  4216.    out
  4217.    ))
  4218.  
  4219. (defun web-mode-previous-line (pos limit)
  4220.  "Previous line"
  4221.  (save-excursion
  4222.    (let (beg end line (continue t))
  4223.      (goto-char pos)
  4224.      (while continue
  4225.        (forward-line -1)
  4226.        (setq end (line-end-position))
  4227.        (setq line (buffer-substring-no-properties (point) end))
  4228.        (when (or (not (string-match-p "^[ \t]*$" line))
  4229.                  (bobp)
  4230.                  (<= (point) limit))
  4231.          (setq continue nil))
  4232.        )
  4233.      (if (<= (point) limit)
  4234.          ;;todo : affiner (le + 3 n est pas générique cf. <?php <% <%- etc.)
  4235.          (setq beg (if (< (+ limit 3) end) (+ limit 3) end))
  4236.        (setq beg (line-beginning-position))
  4237.        );if
  4238.      (setq line (buffer-substring-no-properties beg end))
  4239.      ;;      (message "line=%s" line)
  4240.      (cons line (current-indentation))
  4241.      )))
  4242.  
  4243. (defun web-mode-bracket-indentation (pos initial-column language-offset &optional limit)
  4244.  "Calc indent column."
  4245.  (interactive)
  4246.  (unless limit (setq limit nil))
  4247.  (save-excursion
  4248.    (let (offset n first-char block-info col block-column (continue t))
  4249.      (goto-char pos)
  4250.      (setq first-char (char-after)
  4251.            block-column initial-column)
  4252.      (while continue
  4253.        (forward-line -1)
  4254.        (back-to-indentation)
  4255.        (cond
  4256.         ((or (> limit (point))
  4257.              (bobp))
  4258.          (setq continue nil)
  4259.          )
  4260.         ((and (= (current-indentation) initial-column)
  4261.               (not (eolp)))
  4262.          (setq continue nil)
  4263.          (setq limit (point))
  4264.          )
  4265.         )
  4266.        )
  4267. ;;      (message "ic=%S point=%S limit=%S" initial-column (point) limit)
  4268.      (goto-char pos)
  4269.  
  4270.      (setq block-info (web-mode-count-opened-blocks pos limit))
  4271.      (setq col initial-column)
  4272. ;;      (message "bi=%S" block-info)
  4273.      (if (cddr block-info)
  4274.          (progn
  4275.            (setq col (car (cdr block-info)))
  4276.            )
  4277.        (setq n (car block-info))
  4278.        (setq col initial-column)
  4279. ;;        (message "initial-col=%S n=%S col=%S" initial-column n col)
  4280.        (if (member first-char '(?\} ?\) ?\])) (setq n (1- n)))
  4281.        (setq col (+ initial-column (* n language-offset)))
  4282.        );if
  4283.      (if (< col block-column) block-column col)
  4284.      )))
  4285.  
  4286. ;; return (opened-blocks . (col-num . arg-inline))
  4287. (defun web-mode-count-opened-blocks (pos &optional limit)
  4288.  "Count opened opened block at point."
  4289.  (interactive)
  4290.  (unless limit (setq limit nil))
  4291.  (save-excursion
  4292.    (goto-char pos)
  4293.    (let ((continue t)
  4294.          (match "")
  4295.          (case-found nil)
  4296.          (case-count 0)
  4297.          (queues (make-hash-table :test 'equal))
  4298.          (opened-blocks 0)
  4299.          (col-num 0)
  4300.          (regexp "[\]\[}{)(]\\|\\(break\\|case\\|default\\)")
  4301.          (num-opened 0)
  4302.          close-char n queue arg-inline arg-inline-checked char lines)
  4303.  
  4304.      (while (and continue (re-search-backward regexp limit t))
  4305.        (unless (web-mode-is-comment-or-string)
  4306.          (setq match (match-string-no-properties 0)
  4307.                char (char-after))
  4308.  
  4309.          (cond
  4310.  
  4311.           ((member char '(?\{ ?\( ?\[))
  4312.            (cond
  4313.             ((eq char ?\() (setq close-char ?\)))
  4314.             ((eq char ?\{) (setq close-char ?\}))
  4315.             ((eq char ?\[) (setq close-char ?\])))
  4316.  
  4317.            (setq queue (gethash char queues nil))
  4318.            (setq queue (push (cons (point) (web-mode-line-number)) queue))
  4319.            (puthash char queue queues)
  4320.            ;;(message "%c queue=%S" char queue)
  4321.  
  4322.            (setq queue (gethash close-char queues nil))
  4323.            (setq n (length queue))
  4324.            (cond
  4325.             ((> n 0)
  4326.              (setq queue (cdr queue))
  4327.              (puthash close-char queue queues)
  4328.              ;;(message "%c queue=%S" close-char queue)
  4329.              (setq queue (gethash char queues nil))
  4330.              (setq queue (cdr queue))
  4331.              (puthash char queue queues)
  4332.              ;;(message "%c queue=%S" char queue)
  4333.              )
  4334.             ((= n 0)
  4335.              (setq num-opened (1+ num-opened))
  4336.              ;;(message "num-opened=%S %S" num-opened (point))
  4337.              )
  4338.             )
  4339.  
  4340.            (when (and (= num-opened 1) (null arg-inline-checked))
  4341.              (setq arg-inline-checked t)
  4342. ;;              (when (not (member (char-after (1+ (point))) '(?\n ?\r ?\{)))
  4343.              (when (not (looking-at-p ".[ ]*$"))
  4344.                (setq arg-inline t
  4345.                      continue nil
  4346.                      col-num (1+ (current-column))))
  4347. ;;              (message "pt=%S" (point))
  4348.              )
  4349.  
  4350.            );case
  4351.  
  4352.           ((member char '(?\} ?\) ?\]))
  4353.            (setq queue (gethash char queues nil))
  4354.            (setq queue (push (point) queue))
  4355.            (puthash char queue queues)
  4356.            ;;            (message "%c queue=%S" char queue)
  4357.            )
  4358.  
  4359.           ((member match '("case" "default"))
  4360.            (setq case-found t
  4361.                  case-count (1+ case-count))
  4362.            )
  4363.  
  4364.           ((string= match "break")
  4365.            (setq case-count (1- case-count))
  4366.            )
  4367.  
  4368.           );cond
  4369.  
  4370.          );unless
  4371.        );while
  4372.  
  4373.      (unless arg-inline
  4374.        (maphash
  4375.         (lambda (char queue)
  4376.           (when (member char '(?\{ ?\( ?\[))
  4377.             ;;(message "%c => %S" char queue)
  4378.             (dolist (pair queue)
  4379.               (setq n (cdr pair))
  4380.               (unless (member n lines)
  4381.                 (push n lines))
  4382.               )
  4383.             );when
  4384.           )
  4385.         queues)
  4386.        (setq opened-blocks (length lines))
  4387.        (when (and case-found (> case-count 0))
  4388.          (goto-char pos)
  4389.          (back-to-indentation)
  4390.          (when (not (looking-at-p "case\\|}"))
  4391.            (setq opened-blocks (1+ opened-blocks))
  4392.            )
  4393.          )
  4394.        );unless
  4395.  
  4396. ;;      (message "opened-blocks(%S) col-num(%S) arg-inline(%S)" opened-blocks col-num arg-inline)
  4397.  
  4398.      (cons opened-blocks (cons col-num arg-inline))
  4399.  
  4400.      )))
  4401.  
  4402. (defun web-mode-count-char-in-string (char string)
  4403.  "Count char in string."
  4404.  (let ((n 0))
  4405.    (dotimes (i (length string))
  4406.      (if (eq (elt string i) char)
  4407.          (setq n (1+ n))))
  4408.    n))
  4409.  
  4410. (defun web-mode-scan-at-pos ()
  4411.  "web mode scan at point"
  4412.  (save-excursion
  4413.    (let (scan-beg scan-end (pos (point)))
  4414.      (cond
  4415.       ((web-mode-rsb-client "^[ ]*<")
  4416.        (setq scan-beg (point))
  4417.        (goto-char pos)
  4418.        (setq scan-end (if (web-mode-rsf-client "[[:alnum:] /\"]>[ ]*$") (point) (point-max)))
  4419.         ;;              (message "scan-end=%S" scan-end)
  4420.         ;;            (setq scan-end (point-max))
  4421.         )
  4422.        (t
  4423.         (setq scan-beg 1
  4424.               scan-end (point-max))
  4425.         )
  4426.        );cond
  4427.       ;;(message "scan-region (%S) > (%S)" scan-beg scan-end)
  4428.       ;;          (setq scan-end (point-max))
  4429.       (web-mode-scan-region scan-beg scan-end)
  4430.       );save-excursion
  4431.     ))
  4432.  
  4433. (defun web-mode-mark-and-expand ()
  4434.   "Mark and expand."
  4435.   (interactive)
  4436. ;;  (message "last-input-event=%S" last-input-event)
  4437.   (web-mode-mark (point)))
  4438.  
  4439. ;; todo : pb du engine=go ... selection d'un bloc
  4440. (defun web-mode-mark (pos)
  4441.   "Mark at point."
  4442.  
  4443.   (let ((beg pos) (end pos) prop reg-beg boundaries)
  4444.  
  4445.     (if mark-active
  4446.         (setq reg-beg (region-beginning))
  4447.       (setq web-mode-expand-initial-pos (point)))
  4448.  
  4449.     ;;    (message "regs=%S %S %S %S" (region-beginning) (region-end) (point-min) (point-max))
  4450.  
  4451.     ;;    (message "before=%S" web-mode-expand-previous-state)
  4452.  
  4453.     (cond
  4454.  
  4455.      ((and mark-active
  4456.            (= (region-beginning) (point-min))
  4457.            (or (= (region-end) (point-max)) (= (1+ (region-end)) (point-max))))
  4458.       (deactivate-mark)
  4459.       (goto-char (or web-mode-expand-initial-pos (point-min)))
  4460.       (recenter))
  4461.  
  4462.     ((and (member (get-text-property pos 'block-token) '(comment string))
  4463.           (not (string= web-mode-expand-previous-state "block-token")))
  4464.  
  4465.       (when (eq (get-text-property pos 'block-token) (get-text-property (1- pos) 'block-token))
  4466.         (setq beg (or (previous-single-property-change pos 'block-token) (point-min))))
  4467.       (when (eq (get-text-property pos 'block-token) (get-text-property (1+ pos) 'block-token))
  4468.         (setq end (next-single-property-change pos 'block-token)))
  4469.       (set-mark beg)
  4470.       (goto-char end)
  4471.       (exchange-point-and-mark)
  4472.       (setq web-mode-expand-previous-state "block-token"))
  4473.  
  4474.      ((and (eq (get-text-property pos 'block-side) t)
  4475.            (not (member web-mode-engine '(django go)))
  4476.            (setq boundaries (web-mode-in-code-block "{" "}" 'block-side))
  4477.            (not (string= web-mode-expand-previous-state "server-block")))
  4478.       (set-mark (car boundaries))
  4479.       (goto-char (cdr boundaries))
  4480.       ;;      (message "char=[%c]" (char-before (- (point) 1)))
  4481.       (if (eq ?\% (char-before (- (point) 1)))
  4482.           (setq web-mode-expand-previous-state "block-side")
  4483.         (setq web-mode-expand-previous-state "server-block"))
  4484.       (exchange-point-and-mark)
  4485.       )
  4486.  
  4487.      ((and (eq (get-text-property pos 'block-side) t)
  4488.            (not (string= web-mode-expand-previous-state "block-side")))
  4489.       (when (eq (get-text-property pos 'block-side) (get-text-property (1- pos) 'block-side))
  4490.         (setq beg (or (previous-single-property-change pos 'block-side) (point-min))))
  4491.       (when (eq (get-text-property pos 'block-side) (get-text-property (1+ pos) 'block-side))
  4492.         (setq end (next-single-property-change pos 'block-side)))
  4493.       (set-mark beg)
  4494.       (goto-char end)
  4495.       (exchange-point-and-mark)
  4496.       (setq web-mode-expand-previous-state "block-side"))
  4497.  
  4498.      ((and (member (get-text-property pos 'part-token) '(comment string))
  4499.            (not (string= web-mode-expand-previous-state "part-token")))
  4500.  
  4501.       (when (eq (get-text-property pos 'part-token) (get-text-property (1- pos) 'part-token))
  4502.         (setq beg (previous-single-property-change pos 'part-token)))
  4503.       (when (eq (get-text-property pos 'part-token) (get-text-property (1+ pos) 'part-token))
  4504.         (setq end (next-single-property-change pos 'part-token)))
  4505.       (set-mark beg)
  4506.       (goto-char end)
  4507.       (exchange-point-and-mark)
  4508.       (setq web-mode-expand-previous-state "part-token"))
  4509.  
  4510.      ((and (get-text-property pos 'part-side)
  4511.            (not (string= web-mode-expand-previous-state "client-part"))
  4512.            (setq boundaries (web-mode-in-code-block "{" "}" 'part-side)))
  4513.       (set-mark (car boundaries))
  4514.       (goto-char (cdr boundaries))
  4515.       (exchange-point-and-mark)
  4516.       (setq web-mode-expand-previous-state "client-part")
  4517.       )
  4518.  
  4519.      ((and (eq (get-text-property pos 'part-side) t)
  4520.            (not (string= web-mode-expand-previous-state "part-side")))
  4521.  
  4522.       (when (eq (get-text-property pos 'part-side) (get-text-property (1- pos) 'part-side))
  4523.         (setq beg (previous-single-property-change pos 'part-side)))
  4524.       (when (eq (get-text-property pos 'part-side) (get-text-property (1+ pos) 'part-side))
  4525.         (setq end (next-single-property-change pos 'part-side)))
  4526.       (set-mark beg)
  4527.       (goto-char end)
  4528.       (exchange-point-and-mark)
  4529.       (setq web-mode-expand-previous-state "part-side"))
  4530.  
  4531.      ;;     ((and (eq (get-text-property pos 'markup-type) 'attr)
  4532.      ((and (eq (get-text-property pos 'part-token) 'attr)
  4533.            (not (string= web-mode-expand-previous-state "html-attr")))
  4534.  
  4535.       ;; todo: tester que le car précédent n'est pas un
  4536.       (when (eq (get-text-property pos 'part-token) (get-text-property (1- pos) 'part-token))
  4537.         (setq beg (previous-single-property-change pos 'part-token)))
  4538.       (when (eq (get-text-property pos 'part-token) (get-text-property (1+ pos) 'part-token))
  4539.         (setq end (next-single-property-change pos 'part-token)))
  4540.       (set-mark beg)
  4541.       (goto-char end)
  4542.       (exchange-point-and-mark)
  4543.       (setq web-mode-expand-previous-state "html-attr"))
  4544.  
  4545.      ((and mark-active
  4546.            (eq ?\< (char-after)))
  4547.  
  4548.       (web-mode-element-parent)
  4549.       (if (= reg-beg (region-beginning))
  4550.           (mark-whole-buffer)
  4551.         (web-mode-element-select))
  4552.       )
  4553.  
  4554.      (t
  4555.       (web-mode-element-select)
  4556.       ;;(mark-whole-buffer)
  4557.       )
  4558.  
  4559.      ) ; cond
  4560.  
  4561. ;;    (message "after=%S" web-mode-expand-previous-state)
  4562.  
  4563.     ))
  4564.  
  4565. (defun web-mode-block-select ()
  4566.   "Select the current block."
  4567.   (interactive)
  4568.   (let (beg)
  4569.     (setq beg (web-mode-block-beginning-position (point)))
  4570.     (when beg
  4571.       (goto-char beg)
  4572.       (set-mark (point))
  4573.       (web-mode-block-end)
  4574.       (exchange-point-and-mark)
  4575.       )
  4576.     beg))
  4577.  
  4578. (defun web-mode-tag-select ()
  4579.   "Select the current HTML tag."
  4580.   (interactive)
  4581.   (let (beg)
  4582.     (setq beg (web-mode-tag-beginning-position (point)))
  4583.     (when beg
  4584.       (goto-char beg)
  4585.       (set-mark (point))
  4586.       (web-mode-tag-end)
  4587.       (exchange-point-and-mark)
  4588.       )
  4589.     beg))
  4590.  
  4591. (defun web-mode-element-content-select ()
  4592.   "Select the content of a HTML element."
  4593.   (interactive)
  4594.   (let (pos beg end)
  4595.     (web-mode-element-select)
  4596.     (when mark-active
  4597.       (setq pos (point))
  4598.       (deactivate-mark)
  4599.       (web-mode-tag-match)
  4600.       (setq end (point))
  4601.       (goto-char pos)
  4602.       (web-mode-tag-end)
  4603.       (set-mark (point))
  4604.       (goto-char end)
  4605.       (exchange-point-and-mark)
  4606.       )))
  4607.  
  4608. (defun web-mode-element-select ()
  4609.   "Select the current HTML element (including opening and closing tags)."
  4610.   (interactive)
  4611.   (let (type (pos (point)))
  4612.     (setq type (get-text-property pos 'tag-type))
  4613.     (if type
  4614.         (cond
  4615.          ((member type '(start void))
  4616.           (web-mode-tag-beginning)
  4617.           (set-mark (point))
  4618.           (web-mode-tag-match)
  4619.           (web-mode-tag-end)
  4620.           (exchange-point-and-mark))
  4621.          (t
  4622.           (web-mode-tag-match)
  4623.           (set-mark (point))
  4624.           (web-mode-tag-match)
  4625.           (web-mode-tag-end)
  4626.           (exchange-point-and-mark))
  4627.          );cond
  4628.       (web-mode-element-parent)
  4629.       (unless (= (point) pos) (web-mode-element-select))
  4630.       );if
  4631.     ))
  4632.  
  4633. (defun web-mode-element-kill ()
  4634.   "Kill the current HTML element."
  4635.   (interactive)
  4636.   (web-mode-element-select)
  4637.   (when mark-active
  4638.     (kill-region (region-beginning) (region-end))))
  4639.  
  4640. (defun web-mode-block-kill ()
  4641.   "Kill the current block."
  4642.   (interactive)
  4643.   (web-mode-block-select)
  4644.   (when mark-active
  4645.     (kill-region (region-beginning) (region-end))))
  4646.  
  4647. (defun web-mode-element-clone ()
  4648.   "Clone the current HTML element."
  4649.   (interactive)
  4650.   (let ((offset 0))
  4651.     (web-mode-element-select)
  4652.     (when mark-active
  4653.       (save-excursion
  4654.         (goto-char (region-beginning))
  4655.         (setq offset (current-column)))
  4656.       (kill-region (region-beginning) (region-end))
  4657.       (yank)
  4658.       (newline)
  4659.       (indent-line-to offset)
  4660.       (yank))))
  4661.  
  4662. (defun web-mode-element-rename ()
  4663.   "Rename the current HTML element."
  4664.   (interactive)
  4665.   (save-excursion
  4666.     (let (pos tag-name)
  4667.       (setq tag-name (read-from-minibuffer "Tag name? "))
  4668.       (when (and (> (length tag-name) 0)
  4669.                  (web-mode-element-beginning)
  4670.                  (looking-at "<\\([[:alnum:]]+\\)"))
  4671.         (setq pos (point))
  4672.         (unless (web-mode-is-void-element)
  4673.             (save-match-data
  4674.               (web-mode-tag-match)
  4675.               (if (looking-at "</[ ]*\\([[:alnum:]]+\\)")
  4676.                   (replace-match (concat "</" tag-name))
  4677.                 )))
  4678.         (goto-char pos)
  4679.         (replace-match (concat "<" tag-name))
  4680.         (web-mode-scan-at-pos)
  4681.         ))))
  4682.  
  4683. (defun web-mode-current-trimmed-line ()
  4684.   "Line at point, trimmed."
  4685.   (web-mode-trim (buffer-substring-no-properties
  4686.                   (line-beginning-position)
  4687.                   (line-end-position))))
  4688.  
  4689. (defun web-mode-trim (string)
  4690.   "Remove white spaces in beginning and ending of STRING."
  4691.   (replace-regexp-in-string "\\`[ \t\n]*" "" (replace-regexp-in-string "[ \t\n]*\\'" "" string)))
  4692.  
  4693. (defun web-mode-is-void-element (&optional tag)
  4694.   "Test if tag is a void tag."
  4695.   (if tag
  4696.       (car (member (downcase tag) web-mode-void-elements))
  4697.     (eq (get-text-property (point) 'tag-type) 'void)
  4698.     ))
  4699.  
  4700. (defun web-mode-fold-or-unfold ()
  4701.   "Toggle folding on an HTML element or a control block."
  4702.   (interactive)
  4703.   (web-mode-with-silent-modifications
  4704.    (save-excursion
  4705.      (let (beg-inside beg-outside end-inside end-outside overlay overlays regexp)
  4706.        (back-to-indentation)
  4707.        (setq overlays (overlays-at (point)))
  4708.        (cond
  4709.         ;; *** unfolding
  4710.         (overlays
  4711.          (setq overlay (car overlays))
  4712.          (setq beg-inside (overlay-start overlay)
  4713.                end-inside (overlay-end overlay))
  4714.          (remove-overlays beg-inside end-inside)
  4715.          (put-text-property beg-inside end-inside 'invisible nil)
  4716.          )
  4717.         ;; *** tag folding
  4718.         ((eq (get-text-property (point) 'tag-type) 'start)
  4719.          (setq beg-outside (point))
  4720.          (web-mode-tag-end)
  4721.          (setq beg-inside (point))
  4722.          (goto-char beg-outside)
  4723.          (when (web-mode-tag-match)
  4724.            (setq end-inside (point))
  4725.            (web-mode-tag-end)
  4726.            (setq end-outside (point)))
  4727.          )
  4728.         ;; *** block folding
  4729.         ((cdr (web-mode-is-active-block (point)))
  4730.          (setq beg-outside (point))
  4731.          (web-mode-block-end)
  4732.          (setq beg-inside (point))
  4733.          (goto-char beg-outside)
  4734.          (when (web-mode-tag-match)
  4735.            (setq end-inside (point))
  4736.            (web-mode-block-end)
  4737.            (setq end-outside (point)))
  4738.          )
  4739.         );cond
  4740.        (when end-outside
  4741.          ;;          (message "beg-out(%d) beg-in(%d) end-in(%d) end-out(%d)" beg-outside beg-inside end-inside end-outside)
  4742.          (setq overlay (make-overlay beg-outside end-outside))
  4743.          (overlay-put overlay 'face 'web-mode-folded-face)
  4744.          (put-text-property beg-inside end-inside 'invisible t)
  4745.          )
  4746.        ))))
  4747.  
  4748. (defun web-mode-toggle-comments ()
  4749.   "Toggle comments visbility"
  4750.   (interactive)
  4751.   (save-excursion
  4752.     (if web-mode-comments-invisible
  4753.         (remove-overlays))
  4754.     (setq web-mode-comments-invisible (null web-mode-comments-invisible))
  4755.     (let ((continue t)
  4756.           (pos (point-min))
  4757.           (visibility web-mode-comments-invisible)
  4758.           overlay end)
  4759.       (while continue
  4760.         (setq pos (next-single-property-change pos 'face))
  4761.         (if (null pos)
  4762.             (setq continue nil)
  4763.           (when (eq (get-text-property pos 'face) 'web-mode-comment-face)
  4764.             (setq end (next-single-property-change pos 'face))
  4765.             (put-text-property pos end 'invisible visibility)
  4766.             (when visibility
  4767.               (setq overlay (make-overlay pos end)))
  4768.             (goto-char pos)
  4769.             )
  4770.           )
  4771.         )
  4772.       );let
  4773.     ))
  4774.  
  4775. (defun web-mode-is-single-line-block (pos)
  4776.   "Is block at POS spread on a single line ?"
  4777.   (= (web-mode-line-number (web-mode-block-beginning-position pos))
  4778.      (web-mode-line-number (web-mode-block-end-position pos))))
  4779.  
  4780. (defun web-mode-comment-or-uncomment (&optional pos)
  4781.   "Comment or uncomment line(s), block or region at POS."
  4782.   (interactive)
  4783.   (save-excursion
  4784.     (unless pos (setq pos (if mark-active (region-beginning) (point))))
  4785.     (goto-char pos)
  4786.     (skip-chars-forward "[:space:]" (line-end-position))
  4787.     (if (web-mode-is-comment)
  4788.     (web-mode-uncomment (point))
  4789.       (web-mode-comment (point))))
  4790.   (web-mode-scan-region (point-min) (point-max)))
  4791.  
  4792. (defun web-mode-comment (pos)
  4793.   "Comment line(s) at point."
  4794.   (interactive)
  4795.   (save-excursion
  4796.     (let (ctx language sel beg end tmp block-side single-line-block)
  4797.  
  4798.       (setq block-side (get-text-property pos 'block-side))
  4799.       (setq single-line-block (web-mode-is-single-line-block pos))
  4800.  
  4801.       (cond
  4802.  
  4803.        ((and block-side
  4804.              (string= web-mode-engine "django")
  4805.              single-line-block)
  4806.         (web-mode-comment-django-block pos)
  4807.         )
  4808.  
  4809.        ((and block-side
  4810.              (string= web-mode-engine "dust")
  4811.              single-line-block)
  4812.         (web-mode-comment-dust-block pos)
  4813.         )
  4814.  
  4815.        ((and block-side
  4816.              (string= web-mode-engine "erb")
  4817.              single-line-block)
  4818.         (web-mode-comment-erb-block pos)
  4819.         )
  4820.  
  4821.        ((and block-side
  4822.              (string= web-mode-engine "aspx")
  4823.              single-line-block)
  4824.         (web-mode-comment-aspx-block pos)
  4825.         )
  4826.  
  4827.        ((and block-side
  4828.              (string= web-mode-engine "jsp")
  4829.              single-line-block)
  4830.         (web-mode-comment-jsp-block pos)
  4831.         )
  4832.  
  4833.        ((and block-side
  4834.              (string= web-mode-engine "go")
  4835.              single-line-block)
  4836.         (web-mode-comment-go-block pos)
  4837.         )
  4838.  
  4839.        ((and block-side
  4840.              (string= web-mode-engine "php")
  4841.              single-line-block)
  4842.         (web-mode-comment-php-block pos)
  4843.         )
  4844.  
  4845.        (t
  4846.  
  4847.         (setq ctx (web-mode-point-context
  4848.                    (if mark-active (region-beginning) (line-beginning-position))))
  4849.         ;;        (message "ctx=%S" ctx)
  4850.         (setq language (plist-get ctx :language))
  4851.  
  4852.         (if mark-active
  4853.             (setq beg (region-beginning)
  4854.                   end (region-end))
  4855.           (if (string= language "html")
  4856.               (progn
  4857.                 (back-to-indentation)
  4858.                 (web-mode-element-select))
  4859.             (end-of-line)
  4860.             (set-mark (line-beginning-position))
  4861.             );if
  4862.           (setq beg (region-beginning)
  4863.                 end (region-end))
  4864.           ); if mark-active
  4865.  
  4866.         (when (> (point) (mark))
  4867.           (exchange-point-and-mark))
  4868.  
  4869.         (if (eq (char-before end) ?\n)
  4870.             (setq end (1- end)))
  4871.  
  4872.         ;;     (message "language=%S beg=%S end=%S" language beg end)
  4873.         (setq sel (web-mode-trim (buffer-substring-no-properties beg end)))
  4874.         ;;      (message "[language=%s] sel=%s" language sel)
  4875.         (delete-region beg end)
  4876.         (deactivate-mark)
  4877.  
  4878.         (cond
  4879.  
  4880.          ((string= language "html")
  4881.  
  4882.           (cond
  4883.            ((and (= web-mode-comment-style 2) (string= web-mode-engine "django"))
  4884.             (web-mode-insert-and-indent (concat "{# " sel " #}"))
  4885.             )
  4886.            ((and (= web-mode-comment-style 2) (string= web-mode-engine "erb"))
  4887.             (web-mode-insert-and-indent (concat "<%# " sel " %>"))
  4888.             )
  4889.            ((and (= web-mode-comment-style 2) (string= web-mode-engine "aspx"))
  4890.             (web-mode-insert-and-indent (concat "<%-- " sel " --%>"))
  4891.             )
  4892.            ((and (= web-mode-comment-style 2) (string= web-mode-engine "smarty"))
  4893.             (web-mode-insert-and-indent (concat "{* " sel " *}"))
  4894.             )
  4895.            ((and (= web-mode-comment-style 2) (string= web-mode-engine "blade"))
  4896.             (web-mode-insert-and-indent (concat "{{-- " sel " --}}"))
  4897.             )
  4898.            ((and (= web-mode-comment-style 2) (string= web-mode-engine "razor"))
  4899.             (web-mode-insert-and-indent (concat "@* " sel " *@"))
  4900.             )
  4901.            (t
  4902.             (web-mode-insert-and-indent (concat "<!-- " sel " -->"))
  4903.             )
  4904.            )
  4905.  
  4906.           )
  4907.  
  4908.          ((member language '("php" "javascript" "css"))
  4909.           (web-mode-insert-and-indent (concat "/* " sel " */")))
  4910.  
  4911.          ((member language '("erb"))
  4912.           (web-mode-insert-and-indent (replace-regexp-in-string "^" "#" sel)))
  4913.  
  4914.          ((member language '("asp"))
  4915.           (web-mode-insert-and-indent (replace-regexp-in-string "^" "''" sel)))
  4916.  
  4917.          (t
  4918.           (web-mode-insert-and-indent (concat "/* " sel " */")))
  4919.  
  4920.          );cond
  4921.  
  4922.         );t
  4923.        );cond
  4924.  
  4925.       )))
  4926.  
  4927. (defun web-mode-looking-at-pos (regexp pos)
  4928.   "Performs a looking-at at POS."
  4929.   (save-excursion
  4930.     (goto-char pos)
  4931.     (looking-at regexp)
  4932.     ))
  4933.  
  4934. (defun web-mode-insert-text-at-pos (text pos)
  4935.   "Insert TEXT at POS."
  4936.   (save-excursion
  4937.     (goto-char pos)
  4938.     (insert text)
  4939.     ))
  4940.  
  4941. (defun web-mode-remove-text-at-pos (n pos)
  4942.   "Remove N chars at POS."
  4943.   (delete-region pos (+ pos n))
  4944.   )
  4945.  
  4946. (defun web-mode-uncomment-erb-block (pos)
  4947.   "Uncomment an erb block."
  4948.   (let (beg end)
  4949.     (setq beg (web-mode-block-beginning-position pos)
  4950.           end (web-mode-block-end-position pos))
  4951.     (web-mode-remove-text-at-pos 1 (+ beg 2))
  4952.     ))
  4953.  
  4954. (defun web-mode-comment-erb-block (pos)
  4955.   "Turn an erb block into a comment block."
  4956.   (let (beg end)
  4957.     (setq beg (web-mode-block-beginning-position pos)
  4958.           end (web-mode-block-end-position pos))
  4959.     (web-mode-insert-text-at-pos "#" (+ beg 2))
  4960.     ))
  4961.  
  4962. (defun web-mode-uncomment-django-block (pos)
  4963.   "Uncomment a django block."
  4964.   (let (beg end)
  4965.     (setq beg (web-mode-block-beginning-position pos)
  4966.           end (web-mode-block-end-position pos))
  4967.     (web-mode-remove-text-at-pos 1 (1- end))
  4968.     (web-mode-remove-text-at-pos 1 (1+ beg))
  4969.     ))
  4970.  
  4971. (defun web-mode-comment-django-block (pos)
  4972.   "Turn a django block into a comment block."
  4973.   (let (beg end)
  4974.     (setq beg (web-mode-block-beginning-position pos)
  4975.           end (web-mode-block-end-position pos))
  4976.     (web-mode-insert-text-at-pos "#" end)
  4977.     (web-mode-insert-text-at-pos "#" (1+ beg))
  4978.     ))
  4979.  
  4980. (defun web-mode-uncomment-dust-block (pos)
  4981.   "Uncomment a dust block."
  4982.   (let (beg end)
  4983.     (setq beg (web-mode-block-beginning-position pos)
  4984.           end (web-mode-block-end-position pos))
  4985.     (web-mode-remove-text-at-pos 1 (1- end))
  4986.     (web-mode-remove-text-at-pos 1 (1+ beg))
  4987.     ))
  4988.  
  4989. (defun web-mode-comment-dust-block (pos)
  4990.   "Turn a dust block into a comment block."
  4991.   (let (beg end)
  4992.     (setq beg (web-mode-block-beginning-position pos)
  4993.           end (web-mode-block-end-position pos))
  4994.     (web-mode-insert-text-at-pos "!" end)
  4995.     (web-mode-insert-text-at-pos "!" (1+ beg))
  4996.     ))
  4997.  
  4998. (defun web-mode-comment-aspx-block (pos)
  4999.   "Turn a aspx block into a comment block."
  5000.   (let (beg end)
  5001.     (setq beg (web-mode-block-beginning-position pos)
  5002.           end (web-mode-block-end-position pos))
  5003.     (web-mode-insert-text-at-pos "#" end)
  5004.     (web-mode-insert-text-at-pos "#" (1+ beg))
  5005.     ))
  5006.  
  5007. (defun web-mode-uncomment-aspx-block (pos)
  5008.   "Uncomment a aspx block."
  5009.   (let (beg end)
  5010.     (setq beg (web-mode-block-beginning-position pos)
  5011.           end (web-mode-block-end-position pos))
  5012.     (web-mode-remove-text-at-pos 1 (1- end))
  5013.     (web-mode-remove-text-at-pos 1 (1+ beg))
  5014.     ))
  5015.  
  5016. (defun web-mode-uncomment-jsp-block (pos)
  5017.   "Uncomment a jsp block."
  5018.   (let (beg end)
  5019.     (setq beg (web-mode-block-beginning-position pos)
  5020.           end (web-mode-block-end-position pos))
  5021.     (web-mode-remove-text-at-pos 2 (+ beg 2))
  5022.     ))
  5023.  
  5024. (defun web-mode-comment-jsp-block (pos)
  5025.   "Turn a jsp block into a comment block."
  5026.   (let (beg end)
  5027.     (setq beg (web-mode-block-beginning-position pos)
  5028.           end (web-mode-block-end-position pos))
  5029.     (web-mode-insert-text-at-pos "--" (+ beg 2))
  5030.     ))
  5031.  
  5032. (defun web-mode-uncomment-go-block (pos)
  5033.   "Uncomment a go block."
  5034.   (let (beg end)
  5035.     (setq beg (web-mode-block-beginning-position pos)
  5036.           end (web-mode-block-end-position pos))
  5037.     (web-mode-remove-text-at-pos 1 (+ beg 2))
  5038.     ))
  5039.  
  5040. (defun web-mode-comment-go-block (pos)
  5041.   "Turn a go block into a comment block."
  5042.   (let (beg end)
  5043.     (setq beg (web-mode-block-beginning-position pos)
  5044.           end (web-mode-block-end-position pos))
  5045.     (web-mode-insert-text-at-pos "/" (+ beg 2))
  5046.     ))
  5047.  
  5048. (defun web-mode-comment-php-block (pos)
  5049.   "Turn a php block into a comment block."
  5050.   (let (beg end)
  5051.     (setq beg (web-mode-block-beginning-position pos)
  5052.           end (web-mode-block-end-position pos))
  5053.     (web-mode-insert-text-at-pos "*/" (- end 1))
  5054.     (web-mode-insert-text-at-pos "/*" (+ beg (if (web-mode-looking-at-pos "<\\?php" beg) 5 3)))
  5055.     ))
  5056.  
  5057. (defun web-mode-uncomment (&optional pos)
  5058.   "Uncomment line(s) at point."
  5059.   (interactive)
  5060.   (unless pos (setq pos (point)))
  5061.   (let ((beg pos)
  5062.         (end pos)
  5063.         (sub2 "")
  5064.         comment prop)
  5065.  
  5066.     (cond
  5067.  
  5068.      ((and (get-text-property pos 'block-side)
  5069.            (string= web-mode-engine "django"))
  5070.         (web-mode-uncomment-django-block pos)
  5071.         )
  5072.  
  5073.      ((and (get-text-property pos 'block-side)
  5074.            (string= web-mode-engine "dust"))
  5075.         (web-mode-uncomment-dust-block pos)
  5076.         )
  5077.  
  5078.      ((and (get-text-property pos 'block-side)
  5079.            (string= web-mode-engine "erb"))
  5080.         (web-mode-uncomment-erb-block pos)
  5081.         )
  5082.  
  5083.      ((and (get-text-property pos 'block-side)
  5084.            (string= web-mode-engine "aspx"))
  5085.       (web-mode-uncomment-aspx-block pos)
  5086.       )
  5087.  
  5088.      ((and (get-text-property pos 'block-side)
  5089.            (string= web-mode-engine "jsp"))
  5090.       (web-mode-uncomment-jsp-block pos)
  5091.       )
  5092.  
  5093.      ((and (get-text-property pos 'block-side)
  5094.            (string= web-mode-engine "go"))
  5095.       (web-mode-uncomment-go-block pos)
  5096.       )
  5097.  
  5098.      (t
  5099.  
  5100.       (if (eq (get-text-property pos 'block-token) 'comment)
  5101.           (setq prop 'block-token)
  5102.         (setq prop 'part-token))
  5103.  
  5104.       (if (and (not (bobp))
  5105.                (eq (get-text-property pos prop) (get-text-property (- pos 1) prop)))
  5106.           (setq beg (previous-single-property-change pos prop)))
  5107.  
  5108.       (if (and (not (eobp))
  5109.                (eq (get-text-property pos prop) (get-text-property (+ pos 1) prop)))
  5110.           (setq end (next-single-property-change pos prop)))
  5111.  
  5112.       ;;    (message "beg(%d) end(%d)" beg end)
  5113.  
  5114.       (when (> (- end beg) 4)
  5115.  
  5116.         (setq comment (buffer-substring-no-properties beg end))
  5117.         ;;    (message "before[%s]" comment)
  5118.  
  5119.         (setq sub2 (substring comment 0 2))
  5120.  
  5121.         (cond
  5122.  
  5123.          ((member sub2 '("<!" "<%"))
  5124.           (setq comment (replace-regexp-in-string "\\(^<[!%]--[ ]?\\|[ ]?--[%]?>$\\)" "" comment)))
  5125.  
  5126.          ((string= sub2 "{#")
  5127.           (setq comment (replace-regexp-in-string "\\(^{#[ ]?\\|[ ]?#}$\\)" "" comment)))
  5128.  
  5129.          ((string= sub2 "/*")
  5130.           (setq comment (replace-regexp-in-string "\\(^/\\*[ ]?\\|[ ]?\\*/$\\)" "" comment)))
  5131.  
  5132.          ((string= sub2 "//")
  5133.           (setq comment (replace-regexp-in-string "\\(^//\\)" "" comment)))
  5134.  
  5135.          )
  5136.  
  5137.         ;;    (message "after[%s]" comment)
  5138.  
  5139.         (delete-region beg end)
  5140.         (web-mode-insert-and-indent comment)
  5141.         (goto-char beg)
  5142. ;;        (back-to-indentation)
  5143.  
  5144.         );;when
  5145.  
  5146.       ))
  5147.     ))
  5148.  
  5149. (defun web-mode-snippet-names ()
  5150.   "Return list a snippet names."
  5151.   (interactive)
  5152.   (let (codes
  5153.         (counter 0)
  5154.         snippet
  5155.         (l (length web-mode-snippets)))
  5156.     (while (< counter l)
  5157.       (setq snippet (nth counter web-mode-snippets))
  5158.       (setq counter (1+ counter))
  5159.       (add-to-list 'codes (list (nth 0 snippet) counter)))
  5160.     ;;    (message "%S" codes)
  5161.     codes))
  5162.  
  5163. (defun web-mode-snippet-insert (code)
  5164.   "Insert snippet."
  5165.   (interactive
  5166.    (list (completing-read
  5167.           "Snippet: "
  5168.           (web-mode-snippet-names))))
  5169.   (let (beg
  5170.         (continue t)
  5171.         (counter 0)
  5172.         end
  5173.         sel
  5174.         snippet
  5175.         (l (length web-mode-snippets))
  5176.         pos)
  5177.     (when mark-active
  5178.       (setq sel (web-mode-trim
  5179.                  (buffer-substring-no-properties
  5180.                   (region-beginning) (region-end))))
  5181.       (delete-region (region-beginning) (region-end)))
  5182.     (while (and continue (< counter l))
  5183.       (setq snippet (nth counter web-mode-snippets))
  5184.       (when (string= (nth 0 snippet) code)
  5185.         (setq continue nil))
  5186.       (setq counter (1+ counter)))
  5187.     (when (and (null continue)
  5188.                (nth 1 snippet))
  5189.       (setq beg (point-at-bol))
  5190.       (insert (nth 1 snippet))
  5191.       (setq pos (point))
  5192.       (when sel
  5193.         (insert sel)
  5194.         (setq pos (point)))
  5195.       (if (nth 2 snippet) (insert (nth 2 snippet)))
  5196.       (setq end (point-at-eol))
  5197.       (goto-char pos)
  5198.       (indent-region beg end))
  5199.     ))
  5200.  
  5201. (defun web-mode-insert-and-indent (text)
  5202.   "Insert and indent text."
  5203.   (interactive)
  5204.   (let (beg end)
  5205.     (setq beg (point-at-bol))
  5206.     (insert text)
  5207.     (setq end (point-at-eol))
  5208.     (indent-region beg end)))
  5209.  
  5210. (defun web-mode-tag-match (&optional pos)
  5211.   "Match tag."
  5212.   (interactive)
  5213.   (unless pos (setq pos (point)))
  5214.   (let (init)
  5215.     (goto-char pos)
  5216.     (setq init (point))
  5217.     (when (> (current-indentation) (current-column))
  5218.       (back-to-indentation))
  5219.     (setq pos (point))
  5220.     (cond
  5221.      ((web-mode-is-comment-or-string)
  5222.       (goto-char init))
  5223.      ((and (get-text-property pos 'block-side)
  5224.            (web-mode-block-beginning)
  5225.            (looking-at-p web-mode-active-block-regexp))
  5226.       (funcall web-mode-engine-control-matcher))
  5227.      ((member (get-text-property pos 'tag-type) '(start end))
  5228.       (web-mode-tag-beginning)
  5229.       (web-mode-match-html-tag))
  5230.      (t
  5231.       (goto-char init))
  5232.      )
  5233.     ))
  5234.  
  5235. (defun web-mode-match-html-tag (&optional pos)
  5236.   "Fetch HTML block."
  5237.   (unless pos (setq pos (point)))
  5238.   (let (tag regexp)
  5239.     (setq tag (get-text-property pos 'tag-name))
  5240.     (setq regexp (concat "</?" tag))
  5241.     (if (eq (get-text-property pos 'tag-type) 'end)
  5242.         (web-mode-fetch-html-opening-tag regexp pos)
  5243.       (web-mode-fetch-html-closing-tag regexp pos))
  5244.     t))
  5245.  
  5246. (defun web-mode-fetch-html-opening-tag (regexp pos)
  5247.   "Fetch opening HTML block."
  5248.   (let ((counter 1) (n 0))
  5249.     (while (and (> counter 0) (re-search-backward regexp nil t))
  5250.       (when (get-text-property (point) 'tag-beg)
  5251.         (setq n (1+ n))
  5252.         (if (eq (get-text-property (point) 'tag-type) 'end)
  5253.             (setq counter (1+ counter))
  5254.           (setq counter (1- counter))))
  5255.       )
  5256.     (if (= n 0) (goto-char pos))
  5257.     ))
  5258.  
  5259. (defun web-mode-fetch-html-closing-tag (regexp pos)
  5260.   "Fetch closing HTML closing block."
  5261.   (let ((counter 1) (n 0))
  5262.     (web-mode-tag-end)
  5263.     (while (and (> counter 0) (re-search-forward regexp nil t))
  5264.       (when (get-text-property (match-beginning 0) 'tag-beg)
  5265.         (setq n (1+ n))
  5266.         (if (eq (get-text-property (point) 'tag-type) 'end)
  5267.             (setq counter (1- counter))
  5268.           (setq counter (1+ counter))))
  5269.       )
  5270.     (if (> n 0)
  5271.         (web-mode-tag-beginning)
  5272.       (goto-char pos))
  5273.     ))
  5274.  
  5275. (defun web-mode-match-underscore-block ()
  5276.   "Fetch underscore block."
  5277.   (let (open)
  5278.     (cond
  5279.  
  5280.      ((looking-at-p "<%[ ]*}")
  5281.       (search-forward "}")
  5282.       (backward-char)
  5283.       (setq open (web-mode-opening-paren-position))
  5284.       (when open
  5285.         (goto-char open)
  5286.         (web-mode-block-beginning)
  5287.         )
  5288.       )
  5289.  
  5290.      ((web-mode-block-ends-with "{[ ]*%>")
  5291.       (web-mode-block-end)
  5292.       (search-backward "{")
  5293.       (setq open (web-mode-closing-paren-position))
  5294.       (when open
  5295.         (goto-char open)
  5296.         (web-mode-block-beginning)
  5297.         )
  5298.       )
  5299.  
  5300.      );cond
  5301.  
  5302.     ))
  5303.  
  5304.  
  5305. (defun web-mode-match-php-block ()
  5306.   "Fetch PHP block."
  5307.   (let (regexp match)
  5308.     (cond
  5309.  
  5310.      ((looking-at-p "<\\?\\(php\\)?[ ]*}")
  5311.       (let (open)
  5312.         (search-forward "}")
  5313.         (backward-char)
  5314.         (setq open (web-mode-opening-paren-position))
  5315.         (when open
  5316.           (goto-char open)
  5317.           (web-mode-block-beginning)
  5318.           )
  5319.         ))
  5320.  
  5321.      ((looking-at-p "<\\?php.+{[ ]*\\?>")
  5322.       (let (close)
  5323.         (web-mode-block-end)
  5324.         (search-backward "{")
  5325.         (setq close (web-mode-closing-paren-position))
  5326.         (when close
  5327.           (goto-char close)
  5328.           (web-mode-block-beginning)
  5329.           )
  5330.         ))
  5331.  
  5332.      (t
  5333.       (looking-at web-mode-active-block-regexp)
  5334.       (setq match (match-string-no-properties 3))
  5335.       (setq regexp (concat "<\\?\\(php[ ]+\\|[ ]*\\)?\\(end\\)?\\("
  5336.                          (if (member match '("else" "elseif")) "if" match)
  5337.                          "\\)"))
  5338.       (if (or (string= "end" (match-string-no-properties 2))
  5339.               (member match '("else" "elseif")))
  5340.           (web-mode-fetch-opening-php-block regexp)
  5341.         (web-mode-fetch-closing-php-block regexp))
  5342.       );t
  5343.  
  5344.      );cond
  5345.     t))
  5346.  
  5347. (defun web-mode-fetch-opening-php-block (regexp)
  5348.   "Fetch PHP opening block."
  5349.   (let ((counter 1))
  5350.     (while (and (> counter 0) (re-search-backward regexp nil t))
  5351.       (if (string= "end" (match-string-no-properties 2))
  5352.           (setq counter (1+ counter))
  5353.         (setq counter (1- counter)))
  5354.       )
  5355.     ))
  5356.  
  5357. (defun web-mode-fetch-closing-php-block (regexp)
  5358.   "Fetch PHP closing block."
  5359.   (let ((counter 1))
  5360.     (web-mode-block-end)
  5361.     (while (and (> counter 0) (re-search-forward regexp nil t))
  5362.       (if (string= "end" (match-string-no-properties 2))
  5363.           (setq counter (1- counter))
  5364.         (setq counter (1+ counter))
  5365.         )
  5366.       )
  5367.     (web-mode-block-beginning)
  5368.     ))
  5369.  
  5370. (defun web-mode-match-erb-block ()
  5371.   "Fetch ERB block."
  5372.   (let (regexp chunk)
  5373.     (setq chunk (buffer-substring-no-properties (+ (point) 3)
  5374.                                                 (- (web-mode-block-end-position) 2)))
  5375.     (setq regexp web-mode-active-block-regexp)
  5376.     (if (string-match-p "else\\|end" chunk)
  5377.         (web-mode-fetch-opening-erb-block regexp)
  5378.       (web-mode-fetch-closing-erb-block regexp))
  5379.     t))
  5380.  
  5381. (defun web-mode-fetch-opening-erb-block (regexp)
  5382.   "Fetch erb opening block."
  5383.   (let ((counter 1) match)
  5384.     (while (and (> counter 0) (web-mode-rsb regexp nil t))
  5385.       (setq match (match-string-no-properties 1))
  5386.       (cond
  5387.        ((string= "else" match)
  5388.         )
  5389.        ((not (string= "end" match))
  5390.         (setq counter (1- counter)))
  5391.        (t
  5392.         (setq counter (1+ counter)))
  5393.        )
  5394.       )
  5395.     ))
  5396.  
  5397. (defun web-mode-fetch-closing-erb-block (regexp)
  5398.   "Fetch erb closing block."
  5399.   (let ((counter 1) match)
  5400.     (web-mode-block-end)
  5401.     (while (and (> counter 0) (web-mode-rsf regexp nil t))
  5402.       (setq match (match-string-no-properties 1))
  5403.       (cond
  5404.        ((string= "else" match)
  5405.         )
  5406.        ((not (string= "end" match))
  5407.         (setq counter (1+ counter)))
  5408.        (t
  5409.         (setq counter (1- counter)))
  5410.        )
  5411.       )
  5412.     (web-mode-block-beginning)
  5413.     ))
  5414.  
  5415. ;;tt
  5416.  
  5417. (defun web-mode-match-template-toolkit-block ()
  5418.   "Fetch TEMPLATE-TOOLKIT block."
  5419.   (let (regexp chunk)
  5420.     (setq chunk (buffer-substring-no-properties (+ (point) 3)
  5421.                                                 (- (web-mode-block-end-position) 2)))
  5422.     (setq regexp web-mode-active-block-regexp)
  5423.     (if (string-match-p "else\\|end\\|END" chunk)
  5424.         (web-mode-fetch-opening-template-toolkit-block regexp)
  5425.       (web-mode-fetch-closing-template-toolkit-block regexp))
  5426.     t))
  5427.  
  5428. (defun web-mode-fetch-opening-template-toolkit-block (regexp)
  5429.   "Fetch template-toolkit opening block."
  5430.   (let ((counter 1) match)
  5431.     (while (and (> counter 0) (web-mode-rsb regexp nil t))
  5432.       (setq match (match-string-no-properties 1))
  5433.       (cond
  5434.        ((member match '("else" "ELSE" "elsif" "ELSIF"))
  5435.         )
  5436.        ((not (member match '("end" "END")))
  5437.         (setq counter (1- counter)))
  5438.        (t
  5439.         (setq counter (1+ counter)))
  5440.        )
  5441.       )
  5442.     ))
  5443.  
  5444. (defun web-mode-fetch-closing-template-toolkit-block (regexp)
  5445.   "Fetch template-toolkit closing block."
  5446.   (let ((counter 1) match)
  5447.     (web-mode-block-end)
  5448.     (while (and (> counter 0) (web-mode-rsf regexp nil t))
  5449.       (setq match (match-string-no-properties 1))
  5450.       (cond
  5451.        ((member match '("else" "ELSE" "elsif" "ELSIF"))
  5452.         )
  5453.        ((not (member match '("end" "END")))
  5454.         (setq counter (1+ counter)))
  5455.        (t
  5456.         (setq counter (1- counter)))
  5457.        )
  5458.       )
  5459.     (web-mode-block-beginning)
  5460.     ))
  5461.  
  5462.  
  5463. (defun web-mode-match-blade-block ()
  5464.   "Fetch blade block."
  5465.   (let (beg end match regexp)
  5466.     (looking-at web-mode-active-block-regexp)
  5467.     (setq match (match-string-no-properties 2))
  5468.     (setq regexp (cond
  5469.                   ((member match '("else" "elseif")) "@\\(end\\)?\\(if\\)")
  5470.                   ((string= match "stop") "@\\(section\\|stop\\)")
  5471.                   ((string= match "section") "@\\(endsection\\|stop\\|section\\)")
  5472.                   (t (concat "@\\(end\\)?\\(" match "\\)"))))
  5473.     (if (or (string= "end" (match-string-no-properties 1))
  5474.             (member match '("else" "elseif" "stop")))
  5475.         (web-mode-fetch-opening-blade-block regexp)
  5476.       (web-mode-fetch-closing-blade-block regexp))
  5477.     t))
  5478.  
  5479. (defun web-mode-fetch-opening-blade-block (regexp)
  5480.   "Fetch blade opening block."
  5481.   (let ((counter 1))
  5482.     (while (and (> counter 0) (web-mode-rsb regexp nil t))
  5483.       (if (member (match-string-no-properties 1) '("end" "endsection" "stop"))
  5484.           (setq counter (1+ counter))
  5485.         (setq counter (1- counter)))
  5486.       )
  5487.     ))
  5488.  
  5489. (defun web-mode-fetch-closing-blade-block (regexp)
  5490.   "Fetch blade closing block."
  5491.   (let ((counter 1))
  5492.     (web-mode-block-end)
  5493.     (while (and (> counter 0) (web-mode-rsf regexp nil t))
  5494.       (if (member (match-string-no-properties 1) '("end" "endsection" "stop"))
  5495.           (setq counter (1- counter))
  5496.         (setq counter (1+ counter)))
  5497.       )
  5498.     (goto-char (match-beginning 0))
  5499.     ))
  5500.  
  5501. (defun web-mode-match-django-block ()
  5502.   "Fetch django block."
  5503.   (let (match regexp)
  5504.     (looking-at web-mode-active-block-regexp)
  5505.     (setq match (match-string-no-properties 2))
  5506.     (setq regexp (concat "{%[-]?[ ]+\\(end\\)?\\("
  5507.                          (cond
  5508.                           ((member match '("else" "elseif" "elif")) "if")
  5509.                           ((member match '("empty")) "for")
  5510.                           (t match))
  5511.                          "\\)"))
  5512.     (if (or (string= "end" (match-string-no-properties 1))
  5513.             (member match '("else" "elseif" "elif" "empty")))
  5514.         (web-mode-fetch-opening-django-block regexp)
  5515.       (web-mode-fetch-closing-django-block regexp))
  5516.     t))
  5517.  
  5518. (defun web-mode-fetch-opening-django-block (regexp)
  5519.   "Fetch django opening block."
  5520.   (let ((counter 1))
  5521.     (while (and (> counter 0) (web-mode-rsb regexp nil t))
  5522.       (if (string= "end" (match-string-no-properties 1))
  5523.           (setq counter (1+ counter))
  5524.         (setq counter (1- counter)))
  5525.       )
  5526.     ))
  5527.  
  5528. (defun web-mode-fetch-closing-django-block (regexp)
  5529.   "Fetch django closing block."
  5530.   (let ((counter 1))
  5531.     (web-mode-block-end)
  5532.     (while (and (> counter 0) (web-mode-rsf regexp nil t))
  5533.       (if (string= "end" (match-string-no-properties 1))
  5534.           (setq counter (1- counter))
  5535.         (setq counter (1+ counter)))
  5536.       )
  5537.     (web-mode-block-beginning)
  5538.     ))
  5539.  
  5540. (defun web-mode-match-smarty-block ()
  5541.   "Fetch smarty block."
  5542.   (let (match regexp)
  5543.     (looking-at web-mode-active-block-regexp)
  5544.     (setq match (match-string-no-properties 1))
  5545.     (setq regexp (concat "{/?" (if (string= match "else") "if" match)))
  5546.     (if (or (eq ?\/ (aref (match-string-no-properties 0) 1))
  5547.             (string= match "else"))
  5548.         (web-mode-fetch-opening-smarty-block regexp)
  5549.       (web-mode-fetch-closing-smarty-block regexp))
  5550.     t))
  5551.  
  5552. (defun web-mode-fetch-opening-smarty-block (regexp)
  5553.   "Fetch smarty opening block."
  5554.   (let ((counter 1))
  5555.     (while (and (> counter 0) (web-mode-rsb regexp nil t))
  5556.       (if (eq ?\/ (aref (match-string-no-properties 0) 1))
  5557.           (setq counter (1+ counter))
  5558.         (setq counter (1- counter)))
  5559.       )
  5560.     ))
  5561.  
  5562. (defun web-mode-fetch-closing-smarty-block (regexp)
  5563.   "Fetch smarty closing block."
  5564.   (let ((counter 1))
  5565.     (web-mode-block-end)
  5566.     (while (and (> counter 0) (web-mode-rsf regexp nil t))
  5567.       (if (eq ?\/ (aref (match-string-no-properties 0) 1))
  5568.           (setq counter (1- counter))
  5569.         (setq counter (1+ counter)))
  5570.       )
  5571.     (web-mode-block-beginning)
  5572.     ))
  5573.  
  5574. (defun web-mode-match-dust-block ()
  5575.   "Fetch dust block."
  5576.   (let (match regexp (continue t))
  5577.     (looking-at web-mode-active-block-regexp)
  5578.     (cond
  5579.      ((string= (match-string-no-properties 0) "{:else")
  5580.       (while continue
  5581.         (if (web-mode-block-previous)
  5582.             (when (cdr (web-mode-is-active-block (point)))
  5583.               (setq continue nil))
  5584.           (setq continue nil)
  5585.           )
  5586.         );while
  5587.       )
  5588.      (t
  5589.       (setq match (match-string-no-properties 1))
  5590.       (setq regexp (concat "{[#/:?@><+^]?" match))
  5591.       (if (eq ?\/ (aref (match-string-no-properties 0) 1))
  5592.           (web-mode-fetch-opening-dust-block regexp)
  5593.         (web-mode-fetch-closing-dust-block regexp)))
  5594.      );cond
  5595.     t))
  5596.  
  5597. (defun web-mode-fetch-opening-dust-block (regexp)
  5598.   "Fetch dust opening block."
  5599.   (let ((counter 1))
  5600.     (while (and (> counter 0) (web-mode-rsb regexp nil t))
  5601.       (if (eq ?\/ (aref (match-string-no-properties 0) 1))
  5602.           (setq counter (1+ counter))
  5603.         (setq counter (1- counter)))
  5604.       )
  5605.     ))
  5606.  
  5607. (defun web-mode-fetch-closing-dust-block (regexp)
  5608.   "Fetch dust closing block."
  5609.   (let ((counter 1))
  5610.     (web-mode-block-end)
  5611.     (while (and (> counter 0) (web-mode-rsf regexp nil t))
  5612.       (if (eq ?\/ (aref (match-string-no-properties 0) 1))
  5613.           (setq counter (1- counter))
  5614.         (setq counter (1+ counter)))
  5615.       )
  5616.     (web-mode-block-beginning)
  5617.     ))
  5618.  
  5619. (defun web-mode-match-closure-block ()
  5620.   "Fetch closure block."
  5621.   (let (match regexp (continue t))
  5622.     (looking-at web-mode-active-block-regexp)
  5623.     (cond
  5624.      ((member (match-string-no-properties 0) '("{else" "{elseif"))
  5625.       (while continue
  5626.         (if (web-mode-block-previous)
  5627.             (when (looking-at-p "{if")
  5628.               (setq continue nil))
  5629.           (setq continue nil)
  5630.           )
  5631.         );while
  5632.       )
  5633.      ((member (match-string-no-properties 0) '("{ifempty"))
  5634.       (while continue
  5635.         (if (web-mode-block-previous)
  5636.             (when (looking-at-p "{foreach")
  5637.               (setq continue nil))
  5638.           (setq continue nil)
  5639.           )
  5640.         );while
  5641.       )
  5642.      ((member (match-string-no-properties 0) '("{case" "{default"))
  5643.       (while continue
  5644.         (if (web-mode-block-previous)
  5645.             (when (looking-at-p "{switch")
  5646.               (setq continue nil))
  5647.           (setq continue nil)
  5648.           )
  5649.         );while
  5650.       )
  5651.      (t
  5652.       (setq match (match-string-no-properties 1))
  5653.       (setq regexp (concat "{/?" match))
  5654.       (if (eq ?\/ (aref (match-string-no-properties 0) 1))
  5655.           (web-mode-fetch-opening-closure-block regexp)
  5656.         (web-mode-fetch-closing-closure-block regexp)))
  5657.      );cond
  5658.     t))
  5659.  
  5660. (defun web-mode-fetch-opening-closure-block (regexp)
  5661.   "Fetch closure opening block."
  5662.   (let ((counter 1))
  5663.     (while (and (> counter 0) (web-mode-rsb regexp nil t))
  5664.       (if (eq ?\/ (aref (match-string-no-properties 0) 1))
  5665.           (setq counter (1+ counter))
  5666.         (setq counter (1- counter)))
  5667.       )
  5668.     ))
  5669.  
  5670. (defun web-mode-fetch-closing-closure-block (regexp)
  5671.   "Fetch closure closing block."
  5672.   (let ((counter 1))
  5673.     (web-mode-block-end)
  5674.     (while (and (> counter 0) (web-mode-rsf regexp nil t))
  5675.       (if (eq ?\/ (aref (match-string-no-properties 0) 1))
  5676.           (setq counter (1- counter))
  5677.         (setq counter (1+ counter)))
  5678.       )
  5679.     (web-mode-block-beginning)
  5680.     ))
  5681.  
  5682.  
  5683. (defun web-mode-match-velocity-block ()
  5684.   "Fetch velocity block."
  5685.   (let (regexp match)
  5686.     (looking-at web-mode-active-block-regexp)
  5687.     (setq match (match-string-no-properties 1))
  5688.     (setq regexp web-mode-active-block-regexp)
  5689.     (if (member match '("else" "elseif" "end"))
  5690.         (web-mode-fetch-opening-velocity-block regexp)
  5691.       (web-mode-fetch-closing-velocity-block regexp))
  5692.     t))
  5693.  
  5694. (defun web-mode-fetch-opening-velocity-block (regexp)
  5695.   "Fetch velocity opening block."
  5696.   (let ((counter 1) match)
  5697.     (while (and (> counter 0) (web-mode-rsb regexp nil t))
  5698.       (setq match (match-string-no-properties 1))
  5699.       (cond
  5700.        ((string= "end" match)
  5701.         (setq counter (1+ counter)))
  5702.        ((string= "else" match)
  5703.         )
  5704.        (t
  5705.         (setq counter (1- counter)))
  5706.        )
  5707.       )
  5708.     ))
  5709.  
  5710. (defun web-mode-fetch-closing-velocity-block (regexp)
  5711.   "Fetch velocity closing block."
  5712.   (let ((counter 1) match)
  5713.     (web-mode-block-end)
  5714.     (while (and (> counter 0) (web-mode-rsf regexp nil t))
  5715.       (setq match (match-string-no-properties 1))
  5716.       (cond
  5717.        ((string= "end" match)
  5718.         (setq counter (1- counter)))
  5719.        ((string= "else" match)
  5720.         )
  5721.        (t
  5722.         (setq counter (1+ counter)))
  5723.        )
  5724.       )
  5725.     (goto-char (match-beginning 0))
  5726.     ))
  5727.  
  5728. (defun web-mode-match-ctemplate-block ()
  5729.   "Fetch ctemplate block."
  5730.   (let (regexp)
  5731.     (looking-at web-mode-active-block-regexp)
  5732.     (setq regexp (concat "{{[#^/]" (match-string-no-properties 1)))
  5733.     (if (looking-at-p "{{/")
  5734.         (web-mode-fetch-opening-ctemplate-block regexp)
  5735.       (web-mode-fetch-closing-ctemplate-block regexp))
  5736.     t))
  5737.  
  5738. (defun web-mode-fetch-opening-ctemplate-block (regexp)
  5739.   "Fetch ctemplate opening block."
  5740.   (let ((counter 1))
  5741.     (while (and (> counter 0) (web-mode-rsb regexp nil t))
  5742.       (if (eq ?\/ (aref (match-string-no-properties 0) 2))
  5743.           (setq counter (1+ counter))
  5744.         (setq counter (1- counter)))
  5745.       )
  5746.     ))
  5747.  
  5748. (defun web-mode-fetch-closing-ctemplate-block (regexp)
  5749.   "Fetch ctemplate closing block."
  5750.   (let ((counter 1))
  5751.     (web-mode-block-end)
  5752.     (while (and (> counter 0) (web-mode-rsf regexp nil t))
  5753.       (if (eq ?\/ (aref (match-string-no-properties 0) 2))
  5754.           (setq counter (1- counter))
  5755.         (setq counter (1+ counter)))
  5756.       )
  5757.     (web-mode-block-beginning)
  5758.     ))
  5759.  
  5760. (defun web-mode-match-go-block ()
  5761.   "Fetch go block."
  5762.   (let (regexp match)
  5763.     (looking-at web-mode-active-block-regexp)
  5764.     (setq match (match-string-no-properties 1))
  5765.     (setq regexp web-mode-active-block-regexp)
  5766.     (if (member match '("end" "else"))
  5767.         (web-mode-fetch-opening-go-block regexp)
  5768.       (web-mode-fetch-closing-go-block regexp))
  5769.     t))
  5770.  
  5771. (defun web-mode-fetch-opening-go-block (regexp)
  5772.   "Fetch go opening block."
  5773.   (let ((counter 1) match)
  5774.     (while (and (> counter 0) (web-mode-rsb regexp nil t))
  5775.       (setq match (match-string-no-properties 1))
  5776.       (cond
  5777.        ((string= "end" match)
  5778.         (setq counter (1+ counter)))
  5779.        ((string= "else" match)
  5780.         )
  5781.        (t
  5782.         (setq counter (1- counter)))
  5783.        )
  5784.       )
  5785.     ))
  5786.  
  5787. (defun web-mode-fetch-closing-go-block (regexp)
  5788.   "Fetch go closing block."
  5789.   (let ((counter 1) match)
  5790.     (web-mode-block-end)
  5791.     (while (and (> counter 0) (web-mode-rsf regexp nil t))
  5792.       (setq match (match-string-no-properties 1))
  5793.       (cond
  5794.        ((string= "end" match)
  5795.         (setq counter (1- counter))
  5796.         )
  5797.        ((string= "else" match)
  5798.         )
  5799.        (t
  5800.         (setq counter (1+ counter))
  5801.         )
  5802.        )
  5803.       )
  5804.     (web-mode-block-beginning)
  5805.     ))
  5806.  
  5807. (defun web-mode-match-jsp-block ()
  5808.   "Fetch jsp block."
  5809.   (let (regexp)
  5810.     (cond
  5811.      ((looking-at-p "<% }")
  5812.       (let (open)
  5813.         (search-forward "}")
  5814.         (backward-char)
  5815.         (setq open (web-mode-opening-paren-position))
  5816.         (when open
  5817.           (goto-char open)
  5818.           (web-mode-block-beginning))
  5819.         ))
  5820.      (t
  5821.       (looking-at web-mode-active-block-regexp)
  5822.       (setq regexp (concat "<\\(/?" (match-string-no-properties 1) "\\)\\>"))
  5823.       (if (eq ?\/ (aref (match-string-no-properties 0) 1))
  5824.           (web-mode-fetch-opening-jsp-block regexp)
  5825.         (web-mode-fetch-closing-jsp-block regexp)))
  5826.      )
  5827.     t))
  5828.  
  5829. (defun web-mode-fetch-opening-jsp-block (regexp)
  5830.   "Fetch jsp opening block."
  5831.   (let ((counter 1))
  5832.     (while (and (> counter 0) (web-mode-rsb regexp nil t))
  5833.       (cond
  5834.        ((eq ?\/ (aref (match-string-no-properties 1) 0))
  5835.         (setq counter (1+ counter)))
  5836.        (t
  5837.         (setq counter (1- counter)))
  5838.        )
  5839.       )
  5840.     ))
  5841.  
  5842. (defun web-mode-fetch-closing-jsp-block (regexp)
  5843.   "Fetch jsp closing block."
  5844.   (let ((counter 1))
  5845.     (web-mode-block-end)
  5846.     (while (and (> counter 0) (web-mode-rsf regexp nil t))
  5847.       (cond
  5848.        ((eq ?\/ (aref (match-string-no-properties 1) 0))
  5849.         (setq counter (1- counter)))
  5850.        (t
  5851.         (setq counter (1+ counter)))
  5852.        )
  5853.       )
  5854.     (web-mode-block-beginning)
  5855.     ))
  5856.  
  5857. (defun web-mode-match-freemarker-block ()
  5858.   "Fetch freemarker block."
  5859.   (let (regexp match tag char)
  5860.     (looking-at "[<[]/?\\([[:alpha:]]+:[[:alpha:]]+\\|[@#][[:alpha:]._]+\\)")
  5861.     (setq match (match-string-no-properties 0)
  5862.           tag (match-string-no-properties 1)
  5863.           char (if (string= (substring (match-string-no-properties 0) 0 1) "<") "<" "\\["))
  5864.  
  5865.     (cond
  5866.      ((member tag '("#else" "#elseif"))
  5867.       (setq match (concat char "/#if")
  5868.             tag "#if")
  5869.       )
  5870.      ((string= tag "#break")
  5871.       (setq match (concat char "/#case")
  5872.             tag "#case"))
  5873.      );cond
  5874.     (setq regexp (concat char "\\(/?" tag "\\)\\>"))
  5875. ;;    (message "tag=%S regexp=%S" tag regexp)
  5876.     (if (eq ?\/ (aref match 1))
  5877.         (web-mode-fetch-opening-freemarker-block regexp)
  5878.       (web-mode-fetch-closing-freemarker-block regexp))
  5879.     t))
  5880.  
  5881. (defun web-mode-fetch-opening-freemarker-block (regexp)
  5882.   "Fetch freemarker opening block."
  5883.   (let ((counter 1))
  5884.     (while (and (> counter 0) (web-mode-rsb regexp nil t))
  5885.       (cond
  5886.        ((eq ?\/ (aref (match-string-no-properties 1) 0))
  5887.         (setq counter (1+ counter)))
  5888.        (t
  5889.         (setq counter (1- counter)))
  5890.        )
  5891.       )
  5892.     ))
  5893.  
  5894. (defun web-mode-fetch-closing-freemarker-block (regexp)
  5895.   "Fetch freemarker closing block."
  5896.   (let ((counter 1))
  5897.     (web-mode-block-end)
  5898.     (while (and (> counter 0) (web-mode-rsf regexp nil t))
  5899.       (cond
  5900.        ((eq ?\/ (aref (match-string-no-properties 1) 0))
  5901.         (setq counter (1- counter)))
  5902.        (t
  5903.         (setq counter (1+ counter)))
  5904.        )
  5905.       )
  5906.     (web-mode-block-beginning)
  5907.     ))
  5908.  
  5909. (defun web-mode-element-close ()
  5910.   "Close HTML element."
  5911.   (interactive)
  5912.   (let (jump epp ins tag)
  5913.     (setq epp (web-mode-element-parent-position))
  5914.     (when epp
  5915.       (setq tag (get-text-property epp 'tag-name))
  5916.       (cond
  5917.        ((looking-back "</")
  5918.         (setq ins tag))
  5919.        ((looking-back "<")
  5920.         (setq ins (concat "/" tag)))
  5921.        (t
  5922.         (setq ins (concat "</" tag)))
  5923.        )
  5924.       (unless (looking-at-p "[ ]*>")
  5925.         (setq ins (concat ins ">")))
  5926.       (insert ins)
  5927.       (save-excursion
  5928.         (search-backward "<")
  5929.         (setq jump (looking-back (concat "<" tag ">"))))
  5930.       (when jump
  5931.         (search-backward "<"))
  5932.       );when epp
  5933.     epp
  5934.     ))
  5935.  
  5936. (defun web-mode-tags-pos ()
  5937.   (save-excursion
  5938.     (let (start-beg start-end end-beg end-end (pos (point)))
  5939.       (cond
  5940.        ((eq (get-text-property pos 'tag-type) 'start)
  5941.         (setq start-beg (web-mode-tag-beginning-position pos)
  5942.               start-end (web-mode-tag-end-position pos))
  5943.         (when (web-mode-match-html-tag)
  5944.           (setq end-beg (point)
  5945.                 end-end (web-mode-tag-end-position (point))))
  5946. ;;        (message "%S %S %S %S" start-beg start-end end-beg end-end)
  5947.         )
  5948.        ((eq (get-text-property pos 'tag-type) 'end)
  5949.         (setq end-beg (web-mode-tag-beginning-position pos)
  5950.               end-end (web-mode-tag-end-position pos))
  5951.         (when (web-mode-match-html-tag)
  5952.           (setq start-beg (point)
  5953.                 start-end (web-mode-tag-end-position (point))))
  5954.         )
  5955.        )
  5956.       (if (and start-beg end-beg)
  5957.           (cons (cons start-beg (1+ start-end))
  5958.                 (cons end-beg (1+ end-end)))
  5959.         nil)
  5960.       )))
  5961.  
  5962. (defun web-mode-make-tag-overlays ()
  5963.   (unless web-mode-start-tag-overlay
  5964.     (setq web-mode-start-tag-overlay (make-overlay 1 1)
  5965.           web-mode-end-tag-overlay (make-overlay 1 1))
  5966.     (overlay-put web-mode-start-tag-overlay
  5967.                  'face
  5968.                  'web-mode-current-element-highlight-face)
  5969.     (overlay-put web-mode-end-tag-overlay
  5970.                  'face
  5971.                  'web-mode-current-element-highlight-face)))
  5972.  
  5973. (defun web-mode-delete-tag-overlays ()
  5974.   (when web-mode-start-tag-overlay
  5975.     (delete-overlay web-mode-start-tag-overlay)
  5976.     (delete-overlay web-mode-end-tag-overlay)))
  5977.  
  5978. (defun web-mode-hightlight-current-element ()
  5979.   (let ((ctx (web-mode-tags-pos)))
  5980. ;;    (message "ctx=%S" ctx)
  5981.     (if (null ctx)
  5982.         (web-mode-delete-tag-overlays)
  5983.       (web-mode-make-tag-overlays)
  5984.       (move-overlay web-mode-start-tag-overlay (caar ctx) (cdar ctx))
  5985.       (move-overlay web-mode-end-tag-overlay (cadr ctx) (cddr ctx)))
  5986.     ))
  5987.  
  5988. (defun web-mode-on-after-change (beg end len)
  5989.   "Handles auto-pairing, auto-closing, and region-refresh after buffer alteration."
  5990.  
  5991. ;;  (message "pos=%d, beg=%d, end=%d, len=%d, cur=%d" (point) beg end len (current-column))
  5992. ;;  (backtrace)
  5993.  
  5994.   (setq web-mode-expand-initial-pos nil
  5995.         web-mode-expand-previous-state "")
  5996.  
  5997.   (let ((pos (point)) self-insertion chunk auto-closed atomic-insertion)
  5998.  
  5999.     (setq atomic-insertion (and (= len 0)
  6000.                                 (= 1 (- end beg))))
  6001.  
  6002.     (if (not (= (point-max) (+ (buffer-size) 1)))
  6003.  
  6004.        (setq web-mode-is-narrowed t)
  6005.  
  6006.       ;;-- auto-closing and auto-pairing
  6007.       (when (and (> pos 3)
  6008.                  (not (get-text-property pos 'part-side))
  6009.                  atomic-insertion)
  6010.  
  6011.         ;;-- auto-closing
  6012.         (when (and (> web-mode-tag-auto-close-style 0)
  6013.                    (setq chunk (buffer-substring-no-properties (- beg 1) end))
  6014.                    (or (and (= web-mode-tag-auto-close-style 2)
  6015.                             (string-match-p "[[:alnum:]]>" chunk))
  6016.                        (string= "</" chunk)))
  6017.           (when (web-mode-element-close)
  6018.             (setq auto-closed t
  6019.                   self-insertion t))
  6020.           )
  6021.  
  6022.         ;;-- auto-pairing
  6023.         (when (and (not web-mode-disable-auto-pairing)
  6024.                    (not self-insertion))
  6025.           (let ((i 0) expr after pos-end (l (length web-mode-auto-pairs)))
  6026.             (setq pos-end (if (> (+ end 10) (line-end-position))
  6027.                               (line-end-position)
  6028.                             (+ end 10)))
  6029.             (setq chunk (buffer-substring-no-properties (- beg 2) end)
  6030.                   after (buffer-substring-no-properties end pos-end))
  6031.             (while (and (< i l) (not self-insertion))
  6032.               (setq expr (elt web-mode-auto-pairs i))
  6033.               (when (string= (elt expr 0) chunk)
  6034.                 (unless (string-match-p (elt expr 2) after)
  6035.                   (insert (elt expr 1))
  6036.                   (goto-char (+ pos (elt expr 3)))
  6037.                   (setq self-insertion t))
  6038.                 );when
  6039.               (setq i (1+ i))
  6040.               );while
  6041.             );let
  6042.           );when
  6043.  
  6044.         );end auto-pairing auto-closing
  6045.  
  6046.       ;;-- region-refresh
  6047.       ;;      (save-match-data
  6048.       (cond
  6049.  
  6050.        ;; ((and nil (web-mode-is-html-text beg)
  6051.        ;;       atomic-insertion
  6052.        ;;       (not self-insertion)
  6053.        ;;       (not (member (char-before) web-mode-electric-chars)))
  6054.        ;;  (message "no invalidation %c" (char-before))
  6055.        ;;  )
  6056.  
  6057.        ((and web-mode-has-any-large-part
  6058.              atomic-insertion
  6059.              (not self-insertion)
  6060.              (or (member (get-text-property beg 'part-language)
  6061.                          '(css
  6062.                            ;;javascript json
  6063.                            ))
  6064.                  (member web-mode-content-type '("css"
  6065.                                                  ;;"javascript" "json"
  6066.                                                  ))))
  6067.         (if (or (string= web-mode-content-type "css")
  6068.                 (eq (get-text-property beg 'part-language) 'css))
  6069.             (web-mode-invalidate-css-region beg end)
  6070.           (web-mode-invalidate-javascript-region beg end))
  6071.         )
  6072.  
  6073.        ((and nil
  6074.              web-mode-has-any-large-block
  6075.              atomic-insertion
  6076.              (not self-insertion)
  6077.              (get-text-property beg 'block-side)
  6078.              (member web-mode-engine '("asp")))
  6079.         (web-mode-invalidate-asp-region beg end)
  6080.         )
  6081.  
  6082.        (t
  6083.         (web-mode-scan-region (or (web-mode-previous-tag-at-bol-pos beg)
  6084.                                   (point-min))
  6085.                               (or (web-mode-next-tag-at-eol-pos end)
  6086.                                   (point-max))))
  6087.        )
  6088.       ;;        );save-match-data
  6089.  
  6090.       ;;-- auto-indentation
  6091.       (when (and (not web-mode-disable-auto-indentation)
  6092.                  (or auto-closed
  6093.                      (and (> end (point-min))
  6094.                           (get-text-property (1- end) 'tag-end)
  6095.                           (get-text-property (line-beginning-position) 'tag-beg))))
  6096.         (indent-for-tab-command)
  6097.         )
  6098.  
  6099.       );if narrowed
  6100.     ))
  6101.  
  6102. (defun web-mode-invalidate-css-region (pos-beg pos-end)
  6103.   "Invalidate css region (only when one char has been inserted)"
  6104.   (save-excursion
  6105.     (let (pair part-beg part-end)
  6106.       (if (string= web-mode-content-type "css")
  6107.           (setq part-beg (point-min)
  6108.                 part-end (point-max))
  6109.         (setq part-beg (web-mode-part-beginning-position pos-beg)
  6110.               part-end (web-mode-part-end-position pos-beg)))
  6111.       (setq pair (web-mode-css-current-rule pos-beg part-beg part-end))
  6112. ;;      (message "css region : %S > %S" (car pair) (cdr pair))
  6113.       (web-mode-scan-region (car pair) (cdr pair) "css")
  6114.       )))
  6115.  
  6116. (defun web-mode-invalidate-javascript-region (pos-beg pos-end)
  6117.   "Invalidate javascript region (only when one char has been inserted)"
  6118.   (save-excursion
  6119.     (let (beg end part-beg part-end lang is-token-char)
  6120.       (goto-char pos-beg)
  6121.       (setq is-token-char (not (null (member (char-before) '(?\" ?\' ?\/ ?\< ?\*)))))
  6122. ;;      (message "%S %c(%S)" pos-beg (char-before) is-token-char)
  6123.      (if (member web-mode-content-type '("javascript" "json"))
  6124.          (setq part-beg (point-min)
  6125.                part-end (point-max)
  6126.                lang web-mode-content-type)
  6127.        (setq part-beg (web-mode-part-beginning-position pos-beg)
  6128.              part-end (web-mode-part-end-position pos-beg)
  6129.              lang (symbol-name (get-text-property pos-beg 'part-language))))
  6130.      (cond
  6131.       ((and (not is-token-char)
  6132.             (get-text-property (1- pos-beg) 'part-token))
  6133. ;;        (message "nothing")
  6134.        )
  6135.       ((and (not is-token-char)
  6136.             (progn (back-to-indentation) (setq beg (point)))
  6137.             (if (>= beg part-beg) beg part-beg)
  6138.             (progn (goto-char pos-end) (end-of-line) (setq end (point)))
  6139.             (if (<= end part-end) end part-end))
  6140.        ;;            (message "%S" (buffer-substring-no-properties beg end))
  6141.        (web-mode-scan-part beg end lang)
  6142.        )
  6143.       ;;        (message "%S" (buffer-substring-no-properties part-beg part-end))
  6144.       (t
  6145.        (web-mode-scan-part part-beg part-end lang))
  6146.       )
  6147.      )))
  6148.  
  6149. ;; todo : gestion du remove-text-properties (ne pas toucher à pas mal de properties : block-beg, part-side etc.)
  6150. (defun web-mode-invalidate-asp-region (pos-beg pos-end)
  6151.  "Invalidate asp region."
  6152.  (save-excursion
  6153.    (let (beg end part-beg part-end)
  6154.      (setq part-beg (web-mode-block-beginning-position pos-beg)
  6155.            part-end (web-mode-block-end-position pos-beg))
  6156.      (if (and part-beg part-end
  6157.               (progn (goto-char pos-beg) t)
  6158.               (not (member (char-after) '(?\" ?\' ?\/)))
  6159.               (progn (back-to-indentation) t)
  6160.               (setq beg (point))
  6161.               (if (>= beg part-beg) beg part-beg)
  6162.               (progn (goto-char pos-end) t)
  6163.               (progn (end-of-line) t)
  6164.               (setq end (point))
  6165.               (if (<= end part-end) end part-end))
  6166.            (web-mode-scan-region beg end "asp")
  6167.        (web-mode-scan-region part-beg part-end "asp")
  6168.        )
  6169.      )))
  6170.  
  6171. (defun web-mode-apostrophes-replace ()
  6172.  "Replace ' with ’."
  6173.  (interactive)
  6174.  (save-excursion
  6175.    (let ((min (point-min)) (max (point-max)))
  6176.      (when mark-active
  6177.        (setq min (region-beginning)
  6178.              max (region-end))
  6179.        (deactivate-mark))
  6180.      (goto-char min)
  6181.      (while (web-mode-rsf-content "\\([[:alpha:]]\\)'\\([[:alpha:]]\\)" max)
  6182.        (replace-match "\\1’\\2")
  6183.        );while
  6184.      )))
  6185.  
  6186. (defun web-mode-entities-replace ()
  6187.  "Replace HTML entities ie. &eacute; becomes é"
  6188.   (interactive)
  6189.   (save-excursion
  6190.     (let (name pair (min (point-min)) (max (point-max)))
  6191.       (when mark-active
  6192.         (setq min (region-beginning)
  6193.               max (region-end))
  6194.         (deactivate-mark))
  6195.       (goto-char min)
  6196.       (while (web-mode-rsf-content "&\\([[:alpha:]]\\{2,8\\}\\);" max)
  6197.         (setq name (match-string 1))
  6198.         (setq pair (assoc name web-mode-html-entities))
  6199. ;;        (message "pos=%S name=%S pair=%S" (point) name pair)
  6200.         (when pair
  6201.           (replace-match (cdr pair)))
  6202.         );while
  6203.       )))
  6204.  
  6205. (defun web-mode-xml-replace ()
  6206.   "Replace &, > and < in HTML content."
  6207.   (interactive)
  6208.   (save-excursion
  6209.     (let (expr (min (point-min)) (max (point-max)))
  6210.       (when mark-active
  6211.         (setq min (region-beginning)
  6212.               max (region-end))
  6213.         (deactivate-mark))
  6214.       (goto-char min)
  6215.       (while (web-mode-rsf-content "[&<>]" max)
  6216.         (replace-match (cdr (assq (char-before) web-mode-xml-chars)) t t))
  6217.       )))
  6218.  
  6219. (defun web-mode-quotes-replace ()
  6220.   "Replace dumb quotes."
  6221.   (interactive)
  6222.   (save-excursion
  6223.     (let (expr (min (point-min)) (max (point-max)))
  6224.       (when mark-active
  6225.         (setq min (region-beginning)
  6226.               max (region-end))
  6227.         (deactivate-mark))
  6228.       (goto-char min)
  6229.       (setq expr (concat (car web-mode-smart-quotes) "\\2" (cdr web-mode-smart-quotes)))
  6230.       (while (web-mode-rsf-content "\\(\"\\)\\(.\\{1,200\\}\\)\\(\"\\)" max)
  6231.         (replace-match expr)
  6232.         );while
  6233.       )))
  6234.  
  6235. (defun web-mode-xpath (&optional pos)
  6236.   "HTML path"
  6237.   (interactive)
  6238.   (unless pos (setq pos (point)))
  6239.   (save-excursion
  6240.     (goto-char pos)
  6241.     (let (path)
  6242.       (while (web-mode-element-parent (point))
  6243.         (setq path (cons (get-text-property (point) 'tag-name) path))
  6244.         )
  6245.       (message "/%s" (mapconcat 'identity path "/"))
  6246.       )))
  6247.  
  6248. (defun web-mode-block-ends-with (regexp)
  6249.   "Check if current ends with regexp"
  6250.   (save-excursion
  6251.     (and (web-mode-block-end)
  6252.          (looking-back regexp))
  6253.     ))
  6254.  
  6255. ;;-- position -----------------------------------------------------------------------
  6256.  
  6257. (defun web-mode-opening-paren-position (&optional pos limit)
  6258.   "Fetch opening paren."
  6259.   (save-restriction
  6260.     ;;    (unless paren (setq paren "("))
  6261.     (unless pos (setq pos (point)))
  6262.     (unless limit (setq limit nil))
  6263.     (goto-char pos)
  6264.     (let ((continue t)
  6265.           (n -1)
  6266.           block-side
  6267.           paren
  6268.           (pairs '((")" . "[)(]")
  6269.                    ("]" . "[\]\[]")
  6270.                    ("}" . "[}{]")))
  6271.           pt
  6272.           regexp)
  6273.       (setq paren (string (char-after)))
  6274.       ;;      (message "paren=%S" paren)
  6275.       (setq regexp (cdr (assoc paren pairs)))
  6276.       (if (null regexp) (setq continue nil))
  6277.       (setq block-side (get-text-property pos 'block-side))
  6278.       (while (and continue (re-search-backward regexp limit t))
  6279.         (unless (or (web-mode-is-comment-or-string)
  6280.                     (and block-side (not (get-text-property (point) 'block-side))))
  6281.           ;;          (message "pos=%S pt=%S" pos (point))
  6282.           (if (not (string= (string (char-after)) paren))
  6283.               (progn
  6284.                 (setq n (1+ n))
  6285.                 (if (= n 0)
  6286.                     (setq continue nil
  6287.                           pt (point))))
  6288.             (setq n (1- n)))
  6289.           ;;          (message "n=%S" n)
  6290.           );unless
  6291.         )
  6292.       pt
  6293.       )))
  6294.  
  6295. (defun web-mode-closing-paren-position (&optional pos limit)
  6296.   "Fetch opening paren."
  6297.   (save-excursion
  6298.     (unless pos (setq pos (point)))
  6299.     (unless limit (setq limit nil))
  6300.     (goto-char pos)
  6301.     (let ((continue t)
  6302.           paren
  6303.           (n 0)
  6304.           (pairs '(("(" . "[)(]")
  6305.                    ("[" . "[\]\[]")
  6306.                    ("{" . "[}{]")))
  6307.           pt
  6308.           block-side
  6309.           regexp)
  6310.       (setq paren (string (char-after)))
  6311.       (setq regexp (cdr (assoc paren pairs)))
  6312.       (if (null regexp) (setq continue nil))
  6313.       (setq block-side (get-text-property pos 'block-side))
  6314.       (while (and continue (re-search-forward regexp limit t))
  6315.         (unless (or (web-mode-is-comment-or-string)
  6316.                     (and block-side (not (get-text-property (point) 'block-side))))
  6317.           ;;          (message "char-before=%S pt=%S" (string (char-before)) (point))
  6318.           (if (string= (string (char-before)) paren)
  6319.               (setq n (1+ n))
  6320.             (setq n (1- n))
  6321.             (when (= n 0)
  6322.               (setq continue nil
  6323.                     pt (1- (point))))
  6324.             )
  6325.           ;;        (message "pt=%S char=%S n=%S" (point) (string (char-before)) n)
  6326.           )
  6327.         )
  6328.       ;;      (message "n=%S pt=%S" n pt)
  6329.       pt
  6330.       )))
  6331.  
  6332. (defun web-mode-opening-paren-block-position (pos limit)
  6333.   "Is opened code line."
  6334.   (save-excursion
  6335.     (goto-char pos)
  6336.     (let (c
  6337.           n
  6338.           pt
  6339.           (continue t)
  6340.           (pairs '((")" . "(")
  6341.                    ("]" . "[")
  6342.                    ("}" . "{")))
  6343.           (h (make-hash-table :test 'equal))
  6344.           (regexp "[\]\[)(}{]"))
  6345.       (while (and continue (re-search-backward regexp limit t))
  6346.         (unless (web-mode-is-comment-or-string)
  6347.           (setq c (string (char-after)))
  6348.           (cond
  6349.            ((member c '("(" "{" "["))
  6350.             (setq n (gethash c h 0))
  6351.             (if (= n 0)
  6352.                 (setq continue nil
  6353.                       pt (point))
  6354.               (puthash c (1+ n) h)
  6355.               ))
  6356.            (t
  6357.             (setq c (cdr (assoc c pairs)))
  6358.             (setq n (gethash c h 0))
  6359.             (puthash c (1- n) h))
  6360.            );cond
  6361.           );unless
  6362.         );while
  6363.       ;;      (message "h=%S pt=%S" h pt)
  6364.       pt
  6365.       )))
  6366.  
  6367. (defun web-mode-previous-tag-at-bol-pos (pos)
  6368.   "Line beginning with and HTML tag. BOL is returned or nil."
  6369.   (save-excursion
  6370.     (goto-char pos)
  6371.     (setq pos nil)
  6372.     (let ((continue t))
  6373.       (back-to-indentation)
  6374.       (if (get-text-property (point) 'tag-beg)
  6375.           (setq pos (line-beginning-position))
  6376.         (while continue
  6377.           (forward-line -1)
  6378.           (setq pos (point))
  6379.           (when (bobp)
  6380.             (setq continue nil))
  6381.           (back-to-indentation)
  6382.           (if (get-text-property (point) 'tag-beg)
  6383.               (setq continue nil)
  6384.             (setq pos nil))
  6385.           );while
  6386.         );if
  6387.       pos)))
  6388.  
  6389. (defun web-mode-next-tag-at-eol-pos (pos)
  6390.   "Line ending with an HTML tag. EOL is returned or nil."
  6391.   (save-excursion
  6392.     (goto-char pos)
  6393.     (let ((continue t))
  6394.       (while continue
  6395.         (end-of-line)
  6396.         (setq pos (point))
  6397.         (when (eobp)
  6398.           (setq continue nil))
  6399.         (skip-chars-backward " ")
  6400.         (if (and (> (point) (point-min))
  6401.                  (get-text-property (1- (point)) 'tag-end))
  6402.             (setq continue nil)
  6403.           (setq pos nil))
  6404.         (if continue (forward-line))
  6405.         );while
  6406.       pos)))
  6407.  
  6408. (defun web-mode-tag-match-position (&optional pos)
  6409.   "Match tag position."
  6410.   (unless pos (setq pos (point)))
  6411.   (save-excursion
  6412.     (web-mode-tag-match pos)
  6413.     (if (= pos (point)) nil (point))))
  6414.  
  6415. (defun web-mode-tag-beginning-position (&optional pos)
  6416.   "Beginning position of the current tag. POINT is at <."
  6417.   (unless pos (setq pos (point)))
  6418.   (let (beg)
  6419.     (cond
  6420.      ((get-text-property pos 'tag-beg)
  6421.       (setq beg pos))
  6422.      ((and (> pos 1) (get-text-property (1- pos) 'tag-beg))
  6423.       (setq beg (1- pos)))
  6424.      ((get-text-property pos 'tag-name)
  6425.       (setq beg (1- (previous-single-property-change pos 'tag-beg)))
  6426.       (when (not (get-text-property beg 'tag-beg))
  6427.         (setq beg nil)))
  6428.      (t
  6429.       (setq beg nil))
  6430.      );cond
  6431.     beg))
  6432.  
  6433. (defun web-mode-tag-end-position (&optional pos)
  6434.   "End position of the current tag. POINT is at >."
  6435.   (unless pos (setq pos (point)))
  6436.   (let (end)
  6437.     (cond
  6438.      ((get-text-property pos 'tag-end)
  6439.       (setq end pos))
  6440.      ((get-text-property pos 'tag-name)
  6441.       (setq end (next-single-property-change pos 'tag-end))
  6442.       (when (not (get-text-property end 'tag-end))
  6443.         (setq end nil)))
  6444.      (t
  6445.       (setq end nil))
  6446.      );cond
  6447.     end))
  6448.  
  6449. (defun web-mode-part-end-position (&optional pos)
  6450.   "End position of the current part."
  6451.   (unless pos (setq pos (point)))
  6452.   (cond
  6453.    ((member web-mode-content-type '("css" "javascript" "json"))
  6454.     (setq pos (point-max)))
  6455.    ((not (get-text-property pos 'part-side))
  6456.     (setq pos nil))
  6457.    (t
  6458.     (setq pos (next-single-property-change pos 'tag-beg))
  6459.     (if (not (get-text-property pos 'tag-beg))
  6460.         (setq pos nil)
  6461.       (setq pos (1- pos)))
  6462.     )
  6463.    );cond
  6464.   pos)
  6465.  
  6466. (defun web-mode-part-beginning-position (&optional pos)
  6467.   "Beginning of pat"
  6468.   (unless pos (setq pos (point)))
  6469.   (cond
  6470.    ((member web-mode-content-type '("css" "javascript" "json"))
  6471.     (setq pos (point-min)))
  6472.    ((not (get-text-property pos 'part-side))
  6473.     (setq pos nil))
  6474.    (t
  6475.     (setq pos (previous-single-property-change pos 'tag-end))
  6476.     (when (or (= pos (point-min))
  6477.               (not (get-text-property (1- pos) 'tag-end)))
  6478.       (setq pos nil)))
  6479.    );cond
  6480.   pos)
  6481.  
  6482. (defun web-mode-element-beginning-position (&optional pos)
  6483.   "Beginning of element pos."
  6484.   (unless pos (setq pos (point)))
  6485.   (cond
  6486.    ((null (get-text-property pos 'tag-type))
  6487.     (setq pos (web-mode-element-parent-position)))
  6488.    ((eq (get-text-property pos 'tag-type) 'end)
  6489.     (setq pos (web-mode-tag-match-position pos))
  6490.     (setq pos (if (get-text-property pos 'tag-beg) pos nil)))
  6491.    ((member (get-text-property pos 'tag-type) '(start void))
  6492.     (setq pos (web-mode-tag-beginning-position pos)))
  6493.    (t
  6494.     (setq pos nil))
  6495.    );cond
  6496.   pos)
  6497.  
  6498. (defun web-mode-element-end-position (&optional pos)
  6499.   "End of element pos."
  6500.   (unless pos (setq pos (point)))
  6501.   (cond
  6502.    ((null (get-text-property pos 'tag-type))
  6503.     (setq pos (web-mode-element-parent-position pos))
  6504.     (when pos
  6505.       (setq pos (web-mode-tag-match-position pos))
  6506.       (when pos (setq pos (web-mode-tag-end-position pos)))
  6507.       )
  6508.     )
  6509.    ((member (get-text-property pos 'tag-type) '(end void))
  6510.     (setq pos (web-mode-tag-end-position pos))
  6511.     )
  6512.    ((member (get-text-property pos 'tag-type) '(start))
  6513.     (setq pos (web-mode-tag-match-position pos))
  6514.     (when pos (setq pos (web-mode-tag-end-position pos))))
  6515.    (t
  6516.     (setq pos nil))
  6517.    );cond
  6518.   pos)
  6519.  
  6520. (defun web-mode-element-child-position (&optional pos)
  6521.   "Child element pos."
  6522.   (save-excursion
  6523.     (let (child close)
  6524.       (unless pos (setq pos (point)))
  6525.       (goto-char pos)
  6526.       (cond
  6527.        ((eq (get-text-property pos 'tag-type) 'start)
  6528.         (web-mode-match-html-tag)
  6529.         (setq close (point))
  6530.         (goto-char pos)
  6531.         )
  6532.        ((eq (get-text-property pos 'tag-type) 'void)
  6533.         )
  6534.        ((eq (get-text-property pos 'tag-type) 'end)
  6535.         (web-mode-tag-beginning)
  6536.         (setq close (point))
  6537.         (web-mode-match-html-tag)
  6538.         )
  6539.        ((web-mode-element-parent-position pos)
  6540.         (setq pos (point))
  6541.         (web-mode-match-html-tag)
  6542.         (setq close (point))
  6543.         (goto-char pos)
  6544.         )
  6545.        );cond
  6546.       (when (and close
  6547.                  (web-mode-element-next)
  6548.                  (< (point) close))
  6549.         (setq child (point))
  6550.         )
  6551.       child
  6552.       )))
  6553.  
  6554. (defun web-mode-element-parent-position (&optional pos)
  6555.   "Parent element pos."
  6556.   (let (n
  6557.         tag-type
  6558.         tag-name
  6559.         (continue t)
  6560.         (h (make-hash-table :test 'equal)))
  6561.     (save-excursion
  6562.       (if pos (goto-char pos))
  6563.       (while (and continue (web-mode-tag-previous))
  6564.         (setq pos (point))
  6565.         (setq tag-type (get-text-property pos 'tag-type)
  6566.               tag-name (get-text-property pos 'tag-name))
  6567.         (setq n (gethash tag-name h 0))
  6568.         (when (member tag-type '(end start))
  6569.           (if (eq tag-type 'end)
  6570.               (puthash tag-name (1- n) h)
  6571.             (puthash tag-name (1+ n) h)
  6572.             (when (= n 0) (setq continue nil))
  6573.             );if
  6574.           );when
  6575.         );while
  6576.       );save-excursion
  6577.     (if (null continue) pos nil)
  6578.     ))
  6579.  
  6580. (defun web-mode-block-beginning-position (&optional pos)
  6581.   "web-mode-block-beginning-position"
  6582.   (unless pos (setq pos (point)))
  6583. ;;  (message "web-mode-block-beginning-position=%S" pos)
  6584.   (cond
  6585.    ((or (and (get-text-property pos 'block-side)
  6586.              (= pos (point-min)))
  6587.         (get-text-property pos 'block-beg))
  6588.     )
  6589.    ((and (> pos (point-min))
  6590.          (get-text-property (1- pos) 'block-beg))
  6591.     (setq pos (1- pos))
  6592.     )
  6593.    ((get-text-property pos 'block-side)
  6594.     (setq pos (previous-single-property-change pos 'block-beg))
  6595.     (setq pos (if pos (1- pos) (point-min)))
  6596. ;;    (setq pos (if pos pos (point-min)))
  6597.     )
  6598.    (t
  6599.     (setq pos nil))
  6600.    );cond
  6601. ;;  (message "web-mode-block-beginning-position=%S" pos)
  6602.   pos)
  6603.  
  6604. (defun web-mode-block-end-position (&optional pos)
  6605.   "web-mode-block-end-position"
  6606.   (unless pos (setq pos (point)))
  6607.   (cond
  6608.    ((get-text-property pos 'block-end)
  6609.     )
  6610.    ((get-text-property pos 'block-side)
  6611.     (setq pos (or (next-single-property-change pos 'block-end)
  6612.                   (point-max)))
  6613.     )
  6614.    (t
  6615.     (setq pos nil))
  6616.    );cond
  6617.   pos)
  6618.  
  6619. (defun web-mode-block-previous-position (&optional pos)
  6620.   "web-mode-block-previous-position"
  6621.   (unless pos (setq pos (point)))
  6622.   (cond
  6623.    ((get-text-property pos 'block-side)
  6624.     (setq pos (web-mode-block-beginning-position pos))
  6625.     (when (and pos (> pos (point-min)))
  6626.       (setq pos (1- pos))
  6627.       (while (and (> pos (point-min))
  6628.                   (eq (char-after pos) ?\n))
  6629.         (setq pos (1- pos))
  6630.         )
  6631.       ;;            (message "pos=%S  <%c>" pos (char-after pos))
  6632.       (if (get-text-property pos 'block-side)
  6633.           (setq pos (web-mode-block-beginning-position pos))
  6634.         (setq pos (previous-single-property-change pos 'block-side))
  6635.         (when (and pos (> pos (point-min)))
  6636.           (setq pos (web-mode-block-beginning-position (1- pos))))
  6637.         );if
  6638.       );when
  6639.     )
  6640.    (t
  6641.     (setq pos (previous-single-property-change pos 'block-side))
  6642.     (when (and pos (> pos (point-min)))
  6643.       (setq pos (web-mode-block-beginning-position (1- pos))))
  6644.     )
  6645.    );conf
  6646.   pos)
  6647.  
  6648. (defun web-mode-block-next-position (&optional pos)
  6649.   "web-mode-block-next-position"
  6650.   (unless pos (setq pos (point)))
  6651.   (if (get-text-property pos 'block-side)
  6652.       (if (= pos (point-min))
  6653.           (set pos (point-min))
  6654.         (setq pos (web-mode-block-end-position pos))
  6655.         (when (and pos (> (point-max) pos))
  6656.           (setq pos (1+ pos))
  6657.           (if (not (get-text-property pos 'block-side))
  6658.               (setq pos (next-single-property-change pos 'block-side)))
  6659.           );when
  6660.         )
  6661.     (setq pos (next-single-property-change pos 'block-side)))
  6662.   pos)
  6663.  
  6664. ;;--- /positions
  6665.  
  6666. ;;--- nav
  6667.  
  6668. (defun web-mode-tag-beginning (&optional pos)
  6669.   "Fetch html tag beg."
  6670.   (interactive)
  6671.   (unless pos (setq pos (point)))
  6672.   (setq pos (web-mode-tag-beginning-position pos))
  6673.   (when pos (goto-char pos))
  6674.   pos)
  6675.  
  6676. (defun web-mode-tag-end (&optional pos)
  6677.   "Fetch html tag end."
  6678.   (interactive)
  6679.   (unless pos (setq pos (point)))
  6680.   (setq pos (web-mode-tag-end-position pos))
  6681.   (when pos
  6682.     (setq pos (1+ pos))
  6683.     (goto-char pos))
  6684.   pos)
  6685.  
  6686. (defun web-mode-tag-previous (&optional pos)
  6687.   "Fetch previous tag."
  6688.   (interactive)
  6689.   (unless pos (setq pos (point)))
  6690.   (if (bobp)
  6691.       (setq pos nil)
  6692.     (when (get-text-property pos 'tag-beg)
  6693.       (setq pos (1- pos)))
  6694.     (setq pos (previous-single-property-change pos 'tag-beg))
  6695.     (when pos
  6696.       (setq pos (1- pos))
  6697.       (goto-char pos))
  6698.     )
  6699.   pos)
  6700.  
  6701. (defun web-mode-tag-next (&optional pos)
  6702.   "Fetch next tag. Might be HTML comment or server tag (ie. JSP)."
  6703.   (interactive)
  6704.   (unless pos (setq pos (point)))
  6705.   (if (eobp)
  6706.       (setq pos nil)
  6707.     (when (get-text-property pos 'tag-beg)
  6708.       (setq pos (1+ pos)))
  6709.     (setq pos (next-single-property-change pos 'tag-beg))
  6710.     (when pos (goto-char pos)))
  6711.   pos)
  6712.  
  6713. (defun web-mode-element-previous ()
  6714.   "Fetch previous element."
  6715.   (interactive)
  6716.   (let (continue ret (pos (point)) (props '(start void)))
  6717.     (setq continue (not (bobp)))
  6718.     (while continue
  6719.       (setq ret (web-mode-tag-previous))
  6720.       (when (or (null ret)
  6721.                 (member (get-text-property (point) 'tag-type) props))
  6722.         (setq continue nil)
  6723.         )
  6724.       );while
  6725.     (unless ret (goto-char pos))
  6726.     ret))
  6727.  
  6728. (defun web-mode-element-next ()
  6729.   "Fetch next element."
  6730.   (interactive)
  6731.   (let (continue ret (pos (point)) (props '(start void)))
  6732.     (setq continue (not (eobp)))
  6733.     (while continue
  6734.       (setq ret (web-mode-tag-next))
  6735.       (when (or (null ret)
  6736.                 (member (get-text-property (point) 'tag-type) props))
  6737.         (setq continue nil)
  6738.         )
  6739.       );while
  6740.     (unless ret (goto-char pos))
  6741.     ret))
  6742.  
  6743. (defun web-mode-element-sibling-next ()
  6744.   "Fetch next element."
  6745.   (interactive)
  6746.   (let (parent ret (pos (point)))
  6747.     (save-excursion
  6748.       (cond
  6749.        ((not (get-text-property pos 'tag-type))
  6750.         (when (and (web-mode-element-parent)
  6751.                    (web-mode-match-html-tag)
  6752.                    (web-mode-element-next))
  6753.           (setq ret (point))
  6754.           )
  6755.         )
  6756.        ((eq (get-text-property pos 'tag-type) 'start)
  6757.         (when (and (web-mode-match-html-tag)
  6758.                    (web-mode-element-next))
  6759.           (setq ret (point))
  6760.           )
  6761.         )
  6762.        (t
  6763.         (when (web-mode-element-next)
  6764.           (setq ret (point))
  6765.           )
  6766.         )
  6767.        );cond
  6768.  
  6769.       );save
  6770.     (if ret (goto-char ret))
  6771.     ))
  6772.  
  6773.  
  6774. (defun web-mode-element-beginning (&optional pos)
  6775.   "Move to beginning of element."
  6776.   (interactive)
  6777.   (unless pos (setq pos (point)))
  6778.   (setq pos (web-mode-element-beginning-position pos))
  6779.   (when pos (goto-char pos))
  6780.   pos)
  6781.  
  6782. (defun web-mode-element-end (&optional pos)
  6783.   "Move to end of element."
  6784.   (interactive)
  6785.   (unless pos (setq pos (point)))
  6786.   (setq pos (web-mode-element-end-position pos))
  6787.   (when pos
  6788.     (setq pos (1+ pos))
  6789.     (goto-char pos))
  6790.   pos)
  6791.  
  6792. (defun web-mode-element-parent (&optional pos)
  6793.   "Fetch parent element."
  6794.   (interactive)
  6795.   (unless pos (setq pos (point)))
  6796.   (setq pos (web-mode-element-parent-position pos))
  6797.   (when pos (goto-char pos))
  6798.   pos)
  6799.  
  6800. (defun web-mode-element-child (&optional pos)
  6801.   "Fetch child element."
  6802.   (interactive)
  6803.   (unless pos (setq pos (point)))
  6804.   (setq pos (web-mode-element-child-position pos))
  6805.   (when pos (goto-char pos))
  6806.   pos)
  6807.  
  6808. (defun web-mode-element-traverse ()
  6809.   "Traverse html dom tree."
  6810.   (interactive)
  6811.   (cond
  6812.    ((web-mode-element-child)
  6813.     )
  6814.    ((web-mode-element-sibling-next)
  6815.     )
  6816.    ((web-mode-element-parent)
  6817.     (unless (web-mode-element-sibling-next)
  6818.       (goto-char (point-min)))
  6819.     )
  6820.    );cond
  6821.   )
  6822.  
  6823. (defun web-mode-block-previous (&optional pos)
  6824.   "web-mode-prev-server-block"
  6825.   (interactive)
  6826.   (unless pos (setq pos (point)))
  6827.   (setq pos (web-mode-block-previous-position pos))
  6828.   (when pos (goto-char pos))
  6829.   pos)
  6830.  
  6831. (defun web-mode-block-next (&optional pos)
  6832.   "web-mode-next-server-block"
  6833.   (interactive)
  6834.   (unless pos (setq pos (point)))
  6835.   (setq pos (web-mode-block-next-position pos))
  6836.   (when pos (goto-char pos))
  6837.   pos)
  6838.  
  6839. (defun web-mode-block-beginning (&optional pos)
  6840.   "web-mode-block-beg"
  6841.   (interactive)
  6842.   (unless pos (setq pos (point)))
  6843.   (setq pos (web-mode-block-beginning-position pos))
  6844.   (when pos (goto-char pos))
  6845.   pos)
  6846.  
  6847. (defun web-mode-block-end (&optional pos)
  6848.   "web-mode-block-beg"
  6849.   (interactive)
  6850.   (unless pos (setq pos (point)))
  6851.   (setq pos (web-mode-block-end-position pos))
  6852.   (when pos
  6853.     (setq pos (1+ pos))
  6854.     (goto-char pos))
  6855.   pos)
  6856.  
  6857. ;;--- /nav ----------------------------------------------------------------------
  6858.  
  6859. ;;--- search
  6860.  
  6861. (defun web-mode-rsf-balanced (regexp-open regexp-close &optional limit noerror)
  6862.   "web-mode-rsf-balanced in client."
  6863.   (unless noerror (setq noerror t))
  6864.   (let ((continue t)
  6865.         (level 1)
  6866.         ret
  6867.         (regexp (concat regexp-open "\\|" regexp-close)))
  6868. ;;    (message "regexp=%S" regexp)
  6869.     (while continue
  6870.       (setq ret (re-search-forward regexp limit noerror))
  6871. ;;      (message "regexp=%S ret=%S pos=%S" regexp ret (point))
  6872.       (cond
  6873.        ((null ret)
  6874.         (setq continue nil)
  6875.         )
  6876.        (t
  6877. ;;        (message "%S" (match-string-no-properties 0))
  6878.         (if (string-match-p regexp-open (match-string-no-properties 0))
  6879.             (setq level (1+ level))
  6880.           (setq level (1- level)))
  6881.         (when (< level 1)
  6882.           (setq continue nil)
  6883.           )
  6884.         );t
  6885.        );cond
  6886.       );while
  6887.     ret))
  6888.  
  6889. (defun web-mode-sb-client (regexp &optional limit noerror)
  6890.   "search-backward in client."
  6891.   (unless noerror (setq noerror t))
  6892.   (let ((continue t) ret)
  6893.     (while continue
  6894.       (setq ret (search-backward regexp limit noerror))
  6895.       (if (or (null ret)
  6896.               (not (get-text-property (point) 'block-side)))
  6897.           (setq continue nil))
  6898.       )
  6899.     ret))
  6900.  
  6901. (defun web-mode-rsb-client (regexp &optional limit noerror)
  6902.   "re-search-backward in client."
  6903.   (unless noerror (setq noerror t))
  6904.   (let ((continue t) ret)
  6905.     (while continue
  6906.       (setq ret (re-search-backward regexp limit noerror))
  6907.       (if (or (null ret)
  6908.               (not (get-text-property (point) 'block-side)))
  6909.           (setq continue nil))
  6910.       )
  6911.     ret))
  6912.  
  6913. (defun web-mode-rsf-client (regexp &optional limit noerror)
  6914.   "re-search-forward in client."
  6915.   (unless noerror (setq noerror t))
  6916.   (let ((continue t) ret)
  6917.     (while continue
  6918.       (setq ret (re-search-forward regexp limit noerror))
  6919.       (if (or (null ret)
  6920.               (not (get-text-property (match-beginning 0) 'block-side)))
  6921.           (setq continue nil))
  6922.       );while
  6923.     ret))
  6924.  
  6925. (defun web-mode-sf-client (expr &optional limit noerror)
  6926.   "search-forward in client."
  6927.   (unless noerror (setq noerror t))
  6928.   (let ((continue t) ret)
  6929.     (while continue
  6930.       (setq ret (search-forward expr limit noerror))
  6931.       (if (or (null ret)
  6932.               (not (get-text-property (- (point) (length expr)) 'block-side)))
  6933.           (setq continue nil))
  6934.       )
  6935.     ret))
  6936.  
  6937. (defun web-mode-rsb (regexp &optional limit noerror)
  6938.   "re-search-backward not in comment or string."
  6939.   (unless noerror (setq noerror t))
  6940.   (let ((continue t) ret)
  6941.     (while continue
  6942.       (setq ret (re-search-backward regexp limit noerror))
  6943.       (if (or (null ret)
  6944.               (not (web-mode-is-comment-or-string)))
  6945.           (setq continue nil)))
  6946.     ret))
  6947.  
  6948. (defun web-mode-rsf (regexp &optional limit noerror)
  6949.   "re-search-forward not in comment or string."
  6950.   (unless noerror (setq noerror t))
  6951.   (let ((continue t) ret)
  6952.     (while continue
  6953.       (setq ret (re-search-forward regexp limit noerror))
  6954.       (if (or (null ret)
  6955.               (not (web-mode-is-comment-or-string)))
  6956.           (setq continue nil))
  6957.       )
  6958.     ret))
  6959.  
  6960. (defun web-mode-sb (expr &optional limit noerror)
  6961.   "re-search-backward not in comment or string."
  6962.   (unless noerror (setq noerror t))
  6963.   (let ((continue t) ret)
  6964.     (while continue
  6965.       (setq ret (search-backward expr limit noerror))
  6966.       (if (or (null ret)
  6967.               (not (web-mode-is-comment-or-string)))
  6968.           (setq continue nil)))
  6969.     ret))
  6970.  
  6971. (defun web-mode-sf (expr &optional limit noerror)
  6972.   "re-search-backward not in comment or string."
  6973.   (unless noerror (setq noerror t))
  6974.   (let ((continue t) ret)
  6975.     (while continue
  6976.       (setq ret (search-forward expr limit noerror))
  6977.       (if (or (null ret)
  6978.               (not (web-mode-is-comment-or-string)))
  6979.           (setq continue nil)))
  6980.     ret))
  6981.  
  6982. (defun web-mode-rsb-html (regexp &optional limit noerror)
  6983.   "re-search-backward only in html."
  6984.   (unless noerror (setq noerror t))
  6985.   (let ((continue t) ret)
  6986.     (while continue
  6987.       (setq ret (re-search-backward regexp limit noerror))
  6988.       (if (or (null ret)
  6989.               (not (web-mode-is-part-token-or-server)))
  6990.           (setq continue nil)))
  6991.     ret))
  6992.  
  6993. (defun web-mode-rsf-html (regexp &optional limit noerror)
  6994.   "re-search-forward only in html."
  6995.   (unless noerror (setq noerror t))
  6996.   (let ((continue t) ret)
  6997.     (while continue
  6998.       (setq ret (re-search-forward regexp limit noerror))
  6999.       (if (or (null ret)
  7000.               (not (web-mode-is-part-token-or-server)))
  7001.           (setq continue nil)))
  7002.     ret))
  7003.  
  7004. (defun web-mode-rsf-content (regexp &optional limit noerror)
  7005.   "re-search-forward only in html content."
  7006.   (unless noerror (setq noerror t))
  7007.   (let ((continue t) ret beg end)
  7008.     (while continue
  7009.       (setq ret (re-search-forward regexp limit noerror)
  7010.             beg (if (null ret) (point) (match-beginning 0))
  7011.             end (if (null ret) (point) (match-end 0)))
  7012. ;;      (message "pt=%S" pos)
  7013.       (if (or (null ret)
  7014.               (and (web-mode-is-html-text beg)
  7015.                    (web-mode-is-html-text end)))
  7016.           (setq continue nil)))
  7017.     ret))
  7018.  
  7019. (defun web-mode-is-html-tag (&optional pos)
  7020.   "Is point in an html tag."
  7021.   (unless pos (setq pos (point)))
  7022.   (member (get-text-property pos 'tag-type) '(start end void)))
  7023.  
  7024. (defun web-mode-is-comment-or-string-line ()
  7025.   "Detect if current line is in a comment or in a string."
  7026.   (save-excursion
  7027.     (let ((continue t) (counter 0))
  7028.       (beginning-of-line)
  7029.       (while (and continue (not (eolp)))
  7030.         (if (web-mode-is-comment-or-string)
  7031.             (setq counter (1+ counter))
  7032.           (when (not (eq ?\s (following-char)))
  7033.             (setq continue nil
  7034.                   counter 0))
  7035.           );if
  7036.         (forward-char)
  7037.         );while
  7038.       (> counter 0)
  7039.       )))
  7040.  
  7041. (defun web-mode-is-part-token-or-server (&optional pos)
  7042.   "Detect if POS is in a comment, a string or in server script."
  7043.   (unless pos (setq pos (point)))
  7044.   (or (get-text-property pos 'block-side)
  7045.       (not (null (member (get-text-property pos 'part-token) '(string comment))))))
  7046.  
  7047. (defun web-mode-is-part-token-line ()
  7048.   "Detect if current line has only client tokens (string/comment) or server blocks."
  7049.   (save-excursion
  7050.     (let ((continue t) (counter 0))
  7051.       (beginning-of-line)
  7052.       (while (and continue (not (eolp)))
  7053.         (if (web-mode-is-part-token-or-server)
  7054.             (setq counter (1+ counter))
  7055.           (when (not (eq ?\s (following-char)))
  7056.             (setq continue nil
  7057.                   counter 0))
  7058.           );if
  7059.         (forward-char)
  7060.         );while
  7061.       (> counter 0)
  7062.       )))
  7063.  
  7064. (defun web-mode-is-html-text (&optional pos)
  7065.   "Is point in a html text."
  7066.   (unless pos (setq pos (point)))
  7067.   (not (or (get-text-property pos 'part-side)
  7068.            (get-text-property pos 'tag-type)
  7069.            (get-text-property pos 'block-side)
  7070.            )))
  7071.  
  7072. (defun web-mode-is-comment-or-string (&optional pos)
  7073.   "Detect if point is in a comment or in a string."
  7074.   (unless pos (setq pos (point)))
  7075.   (or (memq (get-text-property pos 'block-token) '(string comment))
  7076.       (memq (get-text-property pos 'part-token) '(string comment))))
  7077.  
  7078. (defun web-mode-is-comment (&optional pos)
  7079.   "Detect if point is in a comment."
  7080.   (unless pos (setq pos (point)))
  7081.   (or (eq (get-text-property pos 'block-token) 'comment)
  7082.       (eq (get-text-property pos 'part-token) 'comment)))
  7083.  
  7084. ;;--- end search
  7085.  
  7086. (defun web-mode-reload ()
  7087.   "Reload web-mode."
  7088.   (interactive)
  7089.   (web-mode-with-silent-modifications
  7090.    (setq web-mode-time nil)
  7091.    (put-text-property (point-min) (point-max) 'invisible nil)
  7092.    (remove-overlays)
  7093.    (unload-feature 'web-mode)
  7094.    (setq web-mode-disable-css-colorization t)
  7095.    (web-mode)
  7096.    (if (fboundp 'web-mode-hook)
  7097.        (web-mode-hook))))
  7098.  
  7099. (defun web-mode-trace (msg)
  7100.   "Benchmark."
  7101.   (interactive)
  7102.   (when nil
  7103.     (when (null web-mode-time) (setq web-mode-time (current-time)))
  7104.     (setq sub (time-subtract (current-time) web-mode-time))
  7105.     (message "%18s: time elapsed = %Ss %9Sµs" msg (nth 1 sub) (nth 2 sub))
  7106.     ))
  7107.  
  7108. (provide 'web-mode)
  7109.  
  7110. ;;; web-mode.el ends here
  7111.  
  7112.  
  7113. ;; ;;todo: a supprimer
  7114. ;; (defun web-mode-tag-previous2 (&optional regexp)
  7115. ;;   "Fetch previous tag."
  7116. ;;   (interactive)
  7117. ;;   (unless regexp (setq regexp web-mode-tag-regexp))
  7118. ;;   (let ((continue t) ret)
  7119. ;;     (while continue
  7120. ;;       (setq ret (re-search-backward regexp nil t))
  7121. ;;       (if (or (null ret)
  7122. ;;               (get-text-property (point) 'tag-beg))
  7123. ;;           (setq continue nil))
  7124. ;;       );while
  7125. ;;     ret))
  7126. ;; ;;todo : a supprimer
  7127. ;; (defun web-mode-element-previous2 ()
  7128. ;;   "Fetch previous element."
  7129. ;;   (interactive)
  7130. ;;   (web-mode-tag-previous "<[[:alpha:]]"))
  7131.  
  7132.  
  7133. ;; (defvar web-mode-django-filters
  7134. ;;   (eval-when-compile
  7135. ;;     (regexp-opt
  7136. ;;      '("add" "addslashes" "capfirst" "center" "cut"
  7137. ;;        "date" "default" "default_if_none" "dictsort"
  7138. ;;        "dictsortreversed" "divisibleby"
  7139. ;;        "escape" "escapejs" "filesizeformat" "first"
  7140. ;;        "fix_ampersands" "floatformat"
  7141. ;;        "force_escape" "format_integer" "format_number"
  7142. ;;        "get_digit" "humanize" "iriencode" "join"
  7143. ;;        "last" "length" "length_is" "linebreaks" "linebreaksbr" "linenumbers"
  7144. ;;        "ljust" "lower" "make_list"
  7145. ;;        "phonenumeric" "pluralize" "pprint"
  7146. ;;        "random" "random_num" "random_range" "removetags" "rjust"
  7147. ;;        "safe" "safeseq" "slice" "slugify" "stringformat" "striptags"
  7148. ;;        "time" "timesince" "timeuntil" "title" "trans" "truncatechars" "truncatewords"
  7149. ;;        "truncatewords_html" "unordered_list" "upper" "urlencode"
  7150. ;;        "urlize" "urlizetrunc"
  7151. ;;        "wordcount" "wordwrap" "yesno")))
  7152. ;;   "Django filters.")
Add Comment
Please, Sign In to add comment