Como destacar palavras-chave específicas dentro de strings / aspas?

7

Eu tenho outra sintaxe destacando palavras-chave SQL dentro de strings (aspas internas) no VIM. Se parece com isso:

insira a descrição da imagem aqui

Em seguida, no Emacs com modo PHP, tudo entre aspas ( ') será considerado uma string pelo bloqueio da fonte:

insira a descrição da imagem aqui

Como você pode ver, o primeiro exemplo com outras propriedades de fonte (sem palavras-chave cursivas) é mais claro. As palavras-chave são muito mais fáceis de distinguir.

Quando estou pesquisando minhas font facepropriedades:

 (font-lock-string-face ((t (:foreground "#536991" :slant italic)))) 

Então, eu estou me perguntando como eu poderia dizer que outra face dentro de um font-lock-string-facedeve ser aplicada, se corresponder às palavras-chave específicas.

Qualquer sugestão será apreciada.

ReneFroger
fonte
Mais uma vez, no modo PHP, como em emacs.stackexchange.com/questions/19002/… ? E você tem o hack dessa resposta em execução? Você deve adicionar uma observação sobre o modo principal atual na pergunta.
Tobias
@ Tobias, o StackExchange não me notificou que recebi uma resposta sua! Lamento muito a minha resposta tardia, veja o link da minha resposta. E você está certo, eu adicionei o modo PHP. Mas acredito que a solução pode não estar relacionada ao modo principal, pois está direcionada apenas para as faces da fonte.
ReneFroger

Respostas:

11

O seguinte snippet elisp deve funcionar. Os detalhes importantes são:

  • As strings são tratadas pelo realce da sintaxe e não pela correspondência de padrões (ou seja, realce da palavra-chave). Isso tem uma prioridade muito alta. Portanto, é necessário substituí-lo explicitamente pelo valor tdo sinalizador MATCHER OVERRIDE (consulte o documento de font-lock-keywords).
  • Não se pode usar um regexp como palavra-chave MATCHER, pois é necessário verificar apenas as palavras-chave SQL nas cadeias. O código abaixo fornece php-sql-keyword-matcherpara esse fim. O teste para seqüências de caracteres é feito via syntax-ppss(consulte o documento para esta função).

Observe que eu só tenho uma exibição de classe color. Então eu não pude testar as outras classes. Suponho que você tenha uma outra classe de exibição, pois as strings são exibidas em itálico no seu exemplo. Se você não obtiver o resultado esperado, personalize o rosto php-sql-keyword-face.

(require 'sql) ;; for sql-keywords
(require 'php-mode) ;; for php-mode-hook

(defvar php-sql-keywords (concat "\\<" (mapconcat 'car sql-mode-ansi-font-lock-keywords "\\|") "\\>")
  "SQL keywords for php-mode stolen from `sql-mode-ansi-font-lock-keywords'.")

(defun php-sql-keyword-matcher (end)
  "Search for SQl keywords within PHP strings."
  (let (pos (case-fold-search t))
    (while (and (setq pos (re-search-forward php-sql-keywords end t))
                (null (nth 3 (syntax-ppss pos)))))
    (when pos (message "Found keyword at %s" pos))
    pos))

(defface php-sql-keyword-face
  '((((class grayscale))  :slant nil :inherit font-lock-string-face)
    (((class color)) :slant italic :inherit font-lock-string-face)
    (t :slant nil :inherit font-lock-string-face))
  "Face to highlight SQL keywords within PHP strings."
  :group 'php-sql)

(defcustom php-sql-keyword-face 'php-sql-keyword-face
  "Face to highlight SQL keywords within PHP strings."
  :type 'face
  :group 'php-sql)

(defun php-add-sql-keyword-matcher ()
  "Hook to add fontification of sql-keywords in strings."
  (font-lock-add-keywords
   nil
   '((php-sql-keyword-matcher 0 php-sql-keyword-face t))
   'append))

(add-hook 'php-mode-hook 'php-add-sql-keyword-matcher)

Nota: Não insira apenas imagens de textos necessários para a reconstrução do problema. O texto ascii pode facilitar possíveis auxiliares na reconstrução do problema. No caso de alguém ter uma solução melhor, insiro a versão ASCII do texto aqui:

$sSql = 'SELECT T05.foo
             T07.bar

         FROM db_pgm_intranet.inttbl_keyuser_proces_keyuser T05

             INNER JOIN db_pgm_intranet.inttbl_keyuser_keyuser T07
             ON    T07.nKkuID = T01.nKpkKeyuserID

             LEFT JOIN db_pgm_intranet.inttbl_keyuser_applicate T07
             ON   T06.nKpaProcesID = T07.nKapID';

E aqui uma imagem do texto como parece quando eu o carrego no emacs com o modo PHP:

Imagem do arquivo php com palavras-chave em itálico em strings sql

Na classe de exibição, as colorstrings não estão em itálico, mas têm uma cor diferente. Portanto, escolhi a fonte em itálico para as palavras-chave SQL nas cadeias.

Os comentários indicam algumas dificuldades com esta resposta. Foi indicado que a solução não funcionaria com a fonte padrão definida como Consolas. Acabei de o testar e no meu sistema também funciona com a fonte Consola como padrão:

Destaque de palavras-chave SQL em strings php com fontes Consolas como padrão.

Na ajuda para font-lock-add-keywordsencontrei o seguinte texto:

Por exemplo:

(font-lock-add-keywords 'c-mode
  '(("\\<\\(FIXME\\):" 1 'font-lock-warning-face prepend)
    ("\\<\\(and\\|or\\|not\\)\\>" . 'font-lock-keyword-face)))

adiciona dois fontification padrões para o modo C, para fontify 'FIXME:' palavras, mesmo em comentários, e para fontify and, ore notpalavras como palavras-chave.

O primeiro caso " FIXME" é o interessante. Aqui eles usam prependcomo sinalizador de substituição.

Tobias
fonte
11
Tobias, você tentou me ajudar novamente. Não posso agradecer o suficiente. Estudei a documentação de variáveis ​​font-lock-keywords (22.6.2 fontification com base em pesquisa). Parece que preciso definir o subexp-highlightersinalizador de substituição como true. Mas vejo que você já fez isso (php-sql-keyword-matcher 0 php-sql-keyword-face t). Então, eu copiei o código em uma configuração vazia do Emacs apenas com o modo PHP integrado, avaliei o buffer e criei um novo buffer com o texto ASCII que você mesmo reconstruiu! Apesar de sua excelente explicação detalhada, infelizmente não vejo texto cursivo ou texto diferente.
ReneFroger 01/01
Além disso, quando coloco meu cursor na string e chamo php-sql-keyword-matcher(adicionei (interactive)a ela)., Recebo um erro, portanto, suponho que não se destina a chamadas interativas. Depois de avaliar seu código e colar o texto ASCII no buffer de rascunho com o modo PHP ativado, não vejo diferença entre as palavras-chave SQL e o restante das strings. Se você precisar de uma captura de tela, das informações de depuração, gostaria de adicionar mais informações, pois meu conhecimento sobre o Elisp ainda não é suficiente. Eu gostei muito de sua ajuda em meus casos, e pela maneira, os melhores votos para 2016.
ReneFroger
11
A origem mais provável do problema é que jit-ockdesiste de algum erro. jit-locknão resgata erros, mas desativa o manipulador que causa o erro e continua seu trabalho. No entanto, ele deixa uma mensagem de erro no buffer de mensagem. Portanto, inicie um novo emacs, tente suas coisas e observe com muito cuidado o buffer de mensagens. AFAIK, você não pode capturar esse tipo de erro via depurador. A interrupção jit-lockdo erro pode ter consequências com fio, como bloqueio morto. Presumo que seja novamente alguma função ausente. Vou tentar novamente com -Q. A propósito, felicidades para você também.
Tobias
11
Posso confirmar que o trecho de código funciona bem emacs -Qaqui na minha casa com a interface X11. Vou tentar novamente no modo de consola ...
Tobias
qual versão do Emacs você usa então? Eu uso o Emacs 25.50 no Ubuntu e não há modo PHP M-x php-modena configuração vazia do Emacs. Foi por isso que embarquei no modo PHP com uma configuração vazia ainda.
ReneFroger