Como iniciar o emacs com um diretório user-emacs personalizado

58

Estou trabalhando em uma configuração personalizada e pequena do Emacs que quero compartilhar com alguns amigos como um repositório git para que eles usem como linha de base para suas próprias configurações futuras.

Para isso, preciso de uma maneira de testar minha configuração e a solução mais simples que posso encontrar é algo como:

$ emacs --eval "(setq user-emacs-directory \"~/Code/my_custom_emacs.d/\")"

Mas não consigo fazê-lo funcionar.

Qualquer ajuda muito apreciada.

Mattias Bengtsson
fonte
3
Li o Apêndice C Argumentos de linha de comando para invocação do Emacs, mas não encontrei uma opção simples de linha de comando para iniciar o Emacs com um .emacs.ddiretório personalizado , a menos que você mude HOME, o que me parece problemático. As pessoas forneceram soluções alternativas abaixo, mas, para mim, isso soa como uma solicitação de recurso bastante razoável para o próprio Emacs.
David J.
5
@DavidJames Você está certo: na verdade, há um item da lista de desejos sobre isso no rastreador de erros do Emacs.
Ffevotte 6/03
2
Atualização: parece que esse recurso não interessa muito aos desenvolvedores do Emacs: a solicitação foi marcada wontfixe fechada no rastreador de erros.
ffevotte
@Francesco: Eu tento uma abordagem dinâmica que permite colocar o diretório Emacs do usuário fora de "~". Pode ser que você tente.
antonio

Respostas:

39

A abordagem básica que eu uso para isso é modificar $HOME, executando:

env HOME=/path/to/dir emacs

Você então usa /path/to/dir/.emacs.d

Você também pode vincular os arquivos ou diretórios importantes neste diretório inicial falso de volta aos reais, para que o Emacs os veja.

phils
fonte
2
Isso funciona perfeito!
Mattias Bengtsson
8
De acordo com o Manual do Emac - Apêndice C Argumentos da linha de comando para invocação do Emacs - Variáveis ​​de ambiente - Variáveis ​​gerais , o HOME define "O local dos seus arquivos na árvore de diretórios; usado para a expansão de nomes de arquivos começando com um til (~)". Alterar o HOME parece uma receita para problemas mais tarde, quando você deseja navegar rapidamente ou encontrar arquivos da sua pasta pessoal real .
David J.
2
David James: Sim, isso é um pequeno aborrecimento com essa abordagem. Como mencionado, você deseja copiar ou vincular o link que você precisa ver no Emacs em HOME, e se você quiser visitar seu diretório pessoal real, precisará usar o caminho absoluto (ou poderá adicionar um link simbólico também) )
php phils
3
Você também pode tentar restaurar o HOME original no Emacs durante a inicialização. Eu não tentei isso, mas parece que vale a pena investigar.
phils
11
@ phils: Eu tentei o que você sugere.
antonio
39

A maneira que eu uso para manter vários .emacs.ddiretórios em paralelo é a seguinte.

  1. O emacs é iniciado assim:

    alias emacs='emacs -q --load "/path/to/init.el"'
    
  2. Cada init.elarquivo começa assim, para configurar corretamente as variáveis user-init-filee user-emacs-directory:

    (setq user-init-file (or load-file-name (buffer-file-name)))
    (setq user-emacs-directory (file-name-directory user-init-file))
    

Descobri que isso funciona de maneira muito confiável nos últimos meses. Aqui estão algumas observações:

  • quebra emacs-init-time, o que apenas informa o tempo necessário para carregar a configuração padrão do sistema, mas não o seu próprio arquivo init. Se você estiver interessado em comparar seu tempo de inicialização, precisará fazê-lo de outra maneira (veja, por exemplo, Como faço para medir o desempenho do código elisp? ).

  • não é equivalente a uma inicialização normal e você precisará cuidar de alguns pontos específicos. Em particular:

    • after-init-hooké executado antes do arquivo init ser carregado.
    • O *scratch*buffer é criado antes do carregamento do arquivo init. Você precisará alterar seu modo explicitamente (em vez de usar initial-major-mode).
    • Você precisará ligar explicitamente package-initialize; isso não será feito automaticamente
  • o caminho para init.elpode ser escolhido arbitrariamente; em particular, o diretório em que init.elreside não precisa ser nomeado .emacs.d. Eu uso isso para ter, por exemplo, .emacs.d.23acompanhamento .emacs.d.24, a fim de poder alternar entre diferentes versões do emacs (o sistema que estou usando no trabalho está ultrapassado, e não consigo instalar o emacs 24 em todas as máquinas que uso).

  • esse fluxo de trabalho não requer modificação do ambiente (e especialmente do HOMEenvvar), o que pode ser desejável se você executar programas no emacs, que podem ser afetados pelo ambiente modificado).

ffevotte
fonte
11
Isso (com efeito) altera a ordem de execução normal, se você estiver considerando o --loadarquivo ed como o arquivo init. Para iniciantes, parece-me que a inicialização normal (padrão) do pacote não ocorrerá e after-init-hookserá executada antes que o arquivo init (falso) seja avaliado. Com certeza você pode contornar essas coisas, mas lembre-se de que não é exatamente a mesma coisa que o Emacs usando o caminho especificado como o arquivo init.
Phd #
2
@ phils sim, você está certo. Isso realmente altera a ordem de execução normal e não é equivalente ao uso de um arquivo init regular. Eu editei minha resposta para refletir sobre o seu ponto after-init-hook. Mas tenho que dizer que, embora eu use essa técnica o tempo todo, nunca encontrei nenhum problema com after-init-hook(mas não a uso explicitamente, e talvez tenha sorte de ter os pacotes que utilizo não confiam nela) . O que você quer dizer com "inicialização normal (padrão) do pacote não ocorrerá"?
Ffevotte
11
Quero dizer que command-linenão vai ligar package-initializenessa situação. Você precisaria chamá-lo manualmente no arquivo init falso.
Phd #
11
@phils obrigado. Eu adicionei isso à resposta, além de mencionar que o modo principal principal também deve ser tratado especificamente.
Ffevotte 11/12/14
Isso funcionou perfeitamente .. Obrigado !!!
Stryker
15

Você pode ligar ~/.emacs.d , é isso que eu faço

  1. Tente manter minha configuração do emacs ~/.emacs.dorientada, ou seja, todos os arquivos de configuração relacionados ao emacs devem residir nessa pasta

  2. Então, eu tenho uma ~/.emacs_configspasta onde todas as pastas de configuração (basicamente uma pasta com um init.ele o restante da configuração) vivem, então minha pasta de configuração pessoal será ~/emacs_configs/iqbal, uma distribuição de prelúdio estará em~/emacs_configs/prelude

  3. Muito cedo na minha configuração pessoal do emacs, defino o user-emacs-directorycaminho completo para a minha configuração usando o seguinte

    (setq user-emacs-directory (file-truename "~/.emacs.d/"))
    
  4. Então, finalmente, faço o link simbólico ~/.emacs.dpara a configuração que realmente quero usar, por exemplo. para usar minha configuração eu vou fazer ln -s ~/emacs_configs/iqbal .emacs.d. Se você quiser experimentar algumas configurações, basta copiar a pasta de configuração ~/emacs_configs/whatever_namee alterar o link simbólico

A vantagem da terceira etapa é que o emacs iniciado com minha configuração pessoal pode ser executado sem afetar, mesmo que eu mude o .emacs.dlink simbólico enquanto o emacs está em execução.

Outra vantagem é que os HOMEprogramas externos não alterados com os quais o emacs pode precisar para interagir não são afetados

Iqbal Ansari
fonte
11
Isso significa que podemos ajustar todas as configurações separadas do emacs para (setq user-emacs-directory (file-truename "~/.emacs.d/"))que elas possam ser executadas sem afetar simultaneamente?
user1011471
11
Na teoria, sim, mas na prática pode haver algumas bibliotecas que codificam o caminho para o ~/.emacs.dinvés de usá-lo user-emacs-directory. Encontrei pelo menos uma dessas bibliotecas, mas infelizmente não consigo lembrar o nome.
Iqbal Ansari
7

Uma configuração que não muda HOMEou funciona com links simbólicos pode ser encontrada na minha resposta https://emacs.stackexchange.com/a/20508/934 . Com esta configuração, você pode alterar a user-emacs-directoryconfiguração de uma variável de ambiente:

EMACS_USER_DIRECTORY=~/.emacsenv.d/spacemacs emacs

e isso ainda funciona com o daemon.

Uwe Koloska
fonte
5

Encontrei esta solução interessante do EmacsWiki :

emacs -q -l ~/my-init-file.el

(não exatamente usando um diretório personalizado, mas funciona bem porque você provavelmente tem um único arquivo de entrada)

phunehehe
fonte
Para sua informação, isso é redundante com um comentário de @Francesco de 2 anos atrás.
21718 Bryce
3

Defina seu var antes de carregar seu arquivo init:

emacs -q --eval '(setq alt-conf t)' --load ~/.emacs

Então, no seu arquivo init (neste caso ~/.emacs):

(defvar alt-conf nil)

(if alt-conf
    (let ((default-directory "~/src/elisp-test/"))
      (normal-top-level-add-subdirs-to-load-path)
      (various-alt-config-stuff)
      (message "Alternate conf"))
  (message "Regular conf"))
yPhil
fonte
Muito elegante, meu sistema favorito, pois tudo permanece no domínio do Emacs, como deveria. Obrigado.
GSL
1

Expandindo a resposta do @phils, criei este pequeno script de shell (chamado testrun.sh) para testar minha nova configuração do emacs. Isso também pode fazer sentido em outros casos (por exemplo, ao testar alterações no seu init.el que podem quebrar o emacs).

#!/bin/bash

cd $(dirname "${BASH_SOURCE[0]}")
[ -d .testrun ] || mkdir .testrun
cd .testrun
[ -h .emacs.d ] || ln -s .. .emacs.d

env HOME=`pwd` emacs

rm .emacs.d
cd ..
rm -rf .testrun
Mattias Bengtsson
fonte
1

Aqui está um pequeno script baseado na resposta e no comentário de @ Phil sobre a alteração da HOMEvariável de ambiente e a restauração no Emacs.

#!/bin/bash

# Use it like this:
#   /path/to/this/script  EMACS_USER_DIRECTORY  [OTHER EMACS ARGS]

# You can never be too careful
set -e

# First arg = emacs user directory
#   (get a canonical, absolute path)
EMACS_USER_DIRECTORY=$(readlink -f "$1")
shift
if [ ! -d "${EMACS_USER_DIRECTORY}" ]; then
    echo "Non-existent directory: '${EMACS_USER_DIRECTORY}'"
    exit 1
fi

# Bootstrap directory
BOOTSTRAP=$(mktemp --directory --tmpdir .emacs-bootstrap.XXXXXX)
mkdir "${BOOTSTRAP}/.emacs.d"

# Bootstrap init file
cat >"${BOOTSTRAP}/.emacs.d/init.el" <<EOF
  ;; # Correctly set-up emacs-user-directory
  (setq user-emacs-directory "${EMACS_USER_DIRECTORY}/")
  (setq user-init-file (concat user-emacs-directory "init.el"))

  ;; # Reset the HOME environment variable
  (setenv "HOME" "${HOME}")

  ;; # Load the real init file and clean-up afterwards
  (unwind-protect (load user-init-file)
    (delete-directory "${BOOTSTRAP}" :recursive))
EOF

# Forward remaining arguments to emacs
exec env HOME="${BOOTSTRAP}" emacs "$@"
ffevotte
fonte
1

Se o caso de uso estiver compartilhando o diretório ".emacs.d" de configuração do emacs único entre todos os usuários de uma máquina Linux, esta solução https://emacs.stackexchange.com/a/4258/5488 funcionaria na maioria dos casos, mas em alguns casos cases O emacs tenta gravar arquivos temporários no diretório user-emacs (como o arquivo .ido.last). Nesses casos, se o diretório de configuração compartilhado tiver permissão de gravação para todos os usuários, ele funcionará, mas pode não ser a solução desejada, pois cada usuário do sistema pode não querer compartilhar o mesmo diretório para armazenar arquivos temporários. Nesse caso, a seguinte solução será a melhor opção.

O arquivo de configuração compartilhado comum .emacs.d / init.el deve começar com

;; should come before calling package-initialize as it will populate
;; everything under common config "~/.emacs.d/elpa"
(setq user-init-file (or load-file-name (buffer-file-name)))
(setq package-user-dir (concat (file-name-directory user-init-file) "elpa"))

(package-initialize)

Faça com que a configuração compartilhada .emacs.d tenha permissão de leitura para todos os usuários (não precisa ter permissões de gravação)

another_user $ emacs -q --load /path/to/shared/config/.emacs.d/init.el

Todo usuário terá seu próprio diretório "~ / .emacs.d /", mas apenas será usado para salvar os arquivos temporários, mas os pacotes e outras configurações serão carregadas no diretório de configuração compartilhado.

Talespin_Kit
fonte