1

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

lot
  • 335
  • 3
  • 9

2 Answers2

2

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! :)

monotux
  • 3,657
  • 28
  • 30
  • Thank you , I'm sorry for my english :P I want find a regexp to match the and compose it. Then my php template is more clear like as:

    Ƥ

    . the Ƥ is block.
    – lot Dec 23 '10 at 03:02
  • 2
    You can avoid to restart emacs by issuing the command `M-x yas/reload-all` – Luca Martini Dec 23 '10 at 09:13
2

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 …)))
Gilles 'SO- stop being evil'
  • 104,111
  • 38
  • 209
  • 254
  • Thank you :) I want match across multiple lines and use : <\?php\(.\|^J\)*?\?>. It work well at "Regexp I-search". But it doesn't work in lisp: "<\\?php\\(.\\|^J\\)*?\\?>". – lot Dec 23 '10 at 02:56
  • 1
    @lot: Make sure you use the right number of backslashes (your comment is missing some, but maybe that's due to Stack Overflow's weird handling of backslashes in comments), and set `font-lock-multiline`. – Gilles 'SO- stop being evil' Dec 23 '10 at 08:34