Pergunta

I want fold php block in php template file.

  <html>
<?php
  $bar = foo();
  echo $bar;
?>
  <h1><?php echo $title; ?></h1>
  </html>

to >>>>

  <html>
  {{PHP}}
  <h1>{{PHP}}</h1>
  </html>

First, I try to use font-lock-add-keywords, it failed. Many thanks to @Gilles for (support? advice? I don't know which word should be here, sorry).

(eval-after-load 'php-mode
  '(progn
     (setq font-lock-multiline t)
     (font-lock-add-keywords
      'php-mode `(("\\(<?php .* ?>\\)("
                   (0 (progn (compose-region (match-beginning 1)
                                             (match-end 1) "の")
                             nil)))))))

Then, I try below, It works.

(defun lot/php-hide ()
  "compose php block in buffer"
  (interactive)
  (beginning-of-buffer)
  (while (re-search-forward "\\(<\\?php\\(.\\|\n\\)*?\\?>\\)" nil t)
    ;; (make-overlay (match-beginning 0) (match-end 0))
    ;; (hide-region-hide)
    ;; 'hide-region-hide' doesn't work, so try compose-region
    (compose-region (match-beginning 0)
                    (match-end 0)
                    ;; "{{PHP}}" ; use word can't work perfect.
                    "の"
                    )
    )
  )

Show me the error if have, Thank you XD

Foi útil?

Solução

There's a simple mistake in your regexp: ? is a special character, but you want to match it literally, so you need a backslash before it. Note that string literal quoting and regexp quoting are orthogonal, so the regexp backslash needs to be doubled in a string literal.

Additionally, regexps are greedy, so the .* part may match more than you intended if you have another occurence of ?>( later on the line. If you replace . by [\n>], this will prevent the match from extending beyond the first >. If you use Emacs ≥23, you can use a non-greedy operator instead, to stop the match as early as possible: .*?.

"\\(<\\?php [^\n>]* \\?>\\)("

This will show things like <?php foo bar?>( as Ƥ(.

The backslashed parentheses \(\) in a regexp delimit a group; (match-beginning 1) and (match-end 1) return the boundary positions for the first (and only) group.

The documentation of regexps is in the Emacs manual.

If you want the match to extend across multiple lines, you need [^>]* or \\(.\\|\n\\)*? in the regexp. Additionally, you must tell the Font Lock library to extend its searches on multiple lines (by default, it limits all searches at the end of the line, for efficiency reasons). Use this:

 (eval-after-load 'php-mode
   '(progn
      (setq font-lock-multiline t)
      (font-lock-add-keywords …)))

Outras dicas

So, you want to input a P and it should output something like <?php xxx; xxx; ?>? Did I understand your question correctly?

In that case, check out yasnippet (more info on emacswiki). It lets you define your own snippets (the syntax is really easy) like P, let it have placeholders (so you can replace xxx; and xxx; with something else when calling the snippet) and such. It's really handy. Just create a new snippet (the name of the file dictates it's shortcut, ie, name it P it this example) and input something like:

# name: My own P-snippet.
# --
<?php ${first}; ${second}; ?>

No need to make own font-locks, no need to use regexp. Just create a new snippet. After creating (and loading it, I usually restart emacs since I'm lazy) your snippet, open up a php-mode buffer, type P and press tab. Magic! :)

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top