emacsclient: создайте фрейм, если фрейм не существует

7

Я запускаю сервер Emacs, используя

emacs --daemon

затем откройте файлы, используя

emacsclient filename.ext

но первый файл должен быть открыт с помощью

emacsclient -c filename.ext

для того, чтобы создать новый кадр, который может быть использован последующими файлами без использования -c флаг командной строки для emacsclient.

Я хочу автоматизировать это. msgstr "если фрейма emacs нет, emacsclient должен создать фрейм, иначе он должен использовать текущий фрейм" Как это можно сделать?

Idlecool
источник
Когда я делаю man emacsclient это не говорит мне о -c вариант. Знаете ли вы, какие версии демонстрируют такое поведение?
dmckee
@dmckee emacsclient -c является новым для значительно улучшенного Emacsclient в Emacs 23
Gilles

Ответы:

7

Вы можете сначала создать фрейм, если его еще нет, а затем открыть файл в уже существующем фрейме. Вот фрагмент кода, который создает рамку на начальном экране, если на оконном дисплее не было открыто ни одной рамки. Вы можете настроить это несколькими способами, например, проверить, есть ли уже рамка на дисплее с помощью x-display-list, Тебе нужно (require 'cl) в вашем `.emacs. Это может потребовать некоторой адаптации для работы на Windows или Aqua.

emacsclient -e '(unless (find-if (lambda (f)
                                   (let ((p (frame-parameters f)))
                                     (assq '\''window-system p)))
                                 (frame-list))
                  (make-frame-on-display (getenv "DISPLAY")))'
emacsclient filename.ext
Gilles
источник
Это то, что я после, но у меня ошибка Symbol’s function definition is void: find-if, Есть идеи почему? (Запуск GNU Emacs 25.2.2.)
aioobe
@aioobe У тебя есть (require 'cl) в вашем файле инициализации? Если не добавить это.
Gilles
6

Вот скрипт emacs-client.sh, который я использую под Linux, чтобы сделать именно то, что вы просите

#!/bin/sh

xprop -name emacs >/dev/null 2>/dev/null
if [ "$?" = "1" ]; then
    emacsclient -c -n -a "" "$@"
else
    emacsclient -n -a "" "$@"
fi
dimitri
источник
Этот ответ нуждается в большем количестве голосов!
Arash
Это кажется запутанным, когда вы убиваете фрейм emacs. В этот момент сервер emacs все еще работает, и строка xprop возвращает 0, поэтому он не открывает новый кадр после первого раза. Я что-то пропустил?
demented hedgehog
1
Решение Джима Ханзикера, похоже, не та же проблема.
demented hedgehog
5

Это похоже на решение Дмитрия, но он обрабатывает случай, когда emacs был запущен как emacs --daemon, emacs --daemon делает скрытое окно, которое вызывает xprop дать ложный положительный результат при проверке существующего окна.

#!/bin/bash

emacsclient -n -e "(if (> (length (frame-list)) 1) 't)" | grep t
if [ "$?" = "1" ]; then
    emacsclient -c -n -a "" "$@"
else
    emacsclient -n -a "" "$@"
fi
Jim Hunziker
источник
2

Я думаю, что добавление функции Жиля к server-switch-hook может делать то, что вы хотите. К сожалению, я не могу получить emacs --daemon работает, чтобы проверить это.

(add-hook 'server-switch-hook
          (lambda ()
            (unless (find-if (lambda (f)
                               (let ((p (frame-parameters f)))
                                 (assq 'window-system p)))
                             (frame-list))
              (make-frame-on-display (getenv "DISPLAY")))))
Ivan Andrus
источник
2

Мое решение состоит в том, чтобы форсировать создание фрейма после запуска демона:

function em() {
  emacs --bg-daemon --display=:0
  # Forces emacs to notice I'm using X as well.
  emacsclient --create-frame --display=:0 --no-wait
}

и тогда мне никогда не придется использовать --create-frame.

Jean-Marc E
источник
0

В OSX я просто определяю эту функцию (аналогично подходу Джима Ханзикера)

emacs () { pgrep -xiq emacs && emacsclient -n $@ || emacsclient -n -c --alternate-editor="" $@; }
ws6079
источник
0

Ответ Джима Ханзикера мне не совсем подходит (в некоторых ситуациях frame-list возвращает два элемента, даже если X-кадра нет). Предполагая, что вы используете только один DISPLAY, работает следующее:

#!/bin/bash

emacsclient -n -e "(null (cl-remove-if (lambda (frame) (null (display-graphic-p frame))) (frame-list)))" | grep >/dev/null nil
if [ "$?" = "1" ]; then
    emacsclient -c -n -a "" "$@"
else
    emacsclient -n -a "" "$@"
fi
brettk
источник
0

Еще одна версия, которая также работает в режиме tty / console:

#!/bin/bash                                                                                                                          

emacsclient -n -e "(if (> (length (frame-list)) 1) 't)" | grep t                                                                     
if [ "$?" = "1" ]; then                                                                                                              
    if [ "$DISPLAY" = "" ]; then                                                                                                     
        emacsclient -c -a "" "$@"                                                                                                    
    else                                                                                                                             
        emacsclient -c -n -a "" "$@"                                                                                                 
    fi                                                                                                                               
else                                                                                                                                 
    if [ "$DISPLAY" = "" ]; then                                                                                                     
        emacsclient -a "" "$@"
    else
        emacsclient -n -a "" "$@"
    fi
fi

(На основании ответа Джима Хунзикерса)

Zitrax
источник