Como posso inserir automaticamente um protótipo em foo.h em foo.c?

11

Suponha que eu esteja escrevendo um programa C em um arquivo foo.c:

int add_numbers(int x, int y, int z) {
    // Very complex implementation here.
    return x + y + z;
}

Eu quero um comando que irá inserir um protótipo de função correspondente em foo.h:

int add_numbers(int x, int y, int z);

Existe alguma solução Emacs para isso?

Wilfred Hughes
fonte

Respostas:

9

ATUALIZAÇÃO : Criei o pacote Semantic Refactor que resolve completamente esse problema e muito mais. Você pode ver as demos para ver como elas funcionam. O texto restante desta resposta, após esta frase, é antigo e o coloca apenas por razões históricas.

RESPOSTA ANTIGA :

Você pode usar senator-copy-tagpara copiar com precisão a assinatura da função e colar novamente no arquivo de origem. senator-copy-tagOs comandos Senator e estão disponíveis quando você ativa semantic-mode:

(semantic-mode 1)

Semântico é um pacote interno do Emacs.

Você pode combinar o Senador Semântico com o Projétil em um comando para inserir o protótipo de função em outro arquivo (arquivo com o mesmo nome, mas com extensão diferente) de qualquer lugar do seu projeto. Se houver apenas um outro arquivo, o comando será inserido imediatamente nesse arquivo; se mais de um, você será solicitado a selecionar um arquivo; se não houver, você será solicitado a fornecer os arquivos inteiros no seu projeto. Depois de selecionar um arquivo, um prompt oferece uma lista de tags semânticas no buffer atual que você pode optar por inserir depois.

Enviei um PR para o Emacs Refactor . Código completo, se você quiser experimentar sem esperar pelo PR: clique aqui .

Aqui está uma demonstração (começa quando você vê START DEMOna parte inferior):

projétil-semântico-inserir-função-protótipo

Você também pode usar apenas o Senador para copiar e funcionar o protótipo. Desde que point esteja em qualquer lugar dentro da assinatura da função ou do corpo da função, run senator-copy-tag, que é vinculado C-c , M-wpor padrão, ele copia toda a função: a assinatura e o corpo. No entanto, você pode colar apenas a assinatura se desejar executando o comando senator-yank-tag, que está vinculado C-c , C-ypor padrão. Pressionar C-ycole toda a assinatura da função junto com seu corpo. senator-copy-tagfunciona mesmo com a assinatura da função expandida em várias linhas como esta:

void 
func(int a,
     int b, 
     int c)
{
    .....
}

Embora essa abordagem não seja inserida diretamente no buffer com o mesmo nome, é mais aplicável em outros casos. Seu caso de uso funcionará apenas se você tiver dois arquivos no mesmo diretório e com o mesmo nome, mas com extensões diferentes. E se a declaração e a definição da função precisarem permanecer em arquivos diferentes com nomes diferentes?

EDIT2 : Aqui está um exemplo para inserção inteligente do protótipo de função usando tags semânticas. Atualmente, você só pode inserir com base nas posições relativas ("antes" e "depois") das tags semânticas de nível superior. Vou atualizar para o usuário fazer para ser capaz de inserir em qualquer lugar onde tags semânticas estão disponíveis, com mais posições (ou seja, quando uma tag é um Class, ele deve oferecer posições adicionais: public, projectede private). A demonstração começa quando você vê START DEMOna parte inferior:

projétil-semântica-inserir-função-protótipo2

Bônus : se você deseja gerar uma lista de definições de funções vazias em um .cpparquivo a partir de um arquivo de cabeçalho, use member-functions.el . Mas em breve, substituirei por Semantic + Projectile.

Tu Do
fonte
3

O comando a seguir deve fazer isso. Ele passou nos meus testes e não possui dependências externas.

(defun endless/copy-proto-to-header-file ()
  (interactive)
  (save-excursion
    ;; c-mode's `beginning-of-defun' should be robust enough.
    (beginning-of-defun)
    (let ((l (point)))
      (search-forward-regexp " *{")
      (let ((proto (buffer-substring l (match-beginning 0))))
        (ff-find-other-file)
        ;; If other file is already open, we don't want to move point.
        (save-excursion
          (goto-char (point-max))
          ;; Do some more movement here if you want.
          (insert "\n" proto ";"))))))
Malabarba
fonte
2

Eu acho que o seguinte deve funcionar (funciona para mim):

(defun c-copy-function-signature-to-header ()
  (interactive)
  (save-excursion
    (let ((last-point -1))
      (while (/= (point) last-point)
        (setq last-point (point))
        (sp-backward-up-sexp))
      (kill-ring-save (point) (line-beginning-position))
      (ff-find-other-file)
      (yank)
      ;; clean whitespace between closing paren and opening curly 
      (delete-trailing-whitespace
        (line-beginning-position)
        (line-end-position))
      (insert ";")))

Isso requer smartparens, embora você possa hackear sua própria cópia sp-backward-up-sexpse isso for inaceitável.

Observe também que isso colocará o cabeçalho onde quer que você tenha deixado o (point)último no cabeçalho. Como você não especificou onde queria, achei que provavelmente era melhor. Obviamente, se você deseja anexar no final, pode colocar um (end-of-buffer)antes do (yank). É claro que você pode adicionar coisas mais sofisticadas, como criar uma nova linha perto do ponto e puxá-la para lá, mas isso é do seu gosto.

PythonNut
fonte