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


7

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

emacs --daemon

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

emacsclient filename.ext

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

emacsclient -c filename.ext

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

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


Когда я делаю 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

Это то, что я после, но у меня ошибка 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

Этот ответ нуждается в большем количестве голосов!
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

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")))))

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.


0

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

emacs () { pgrep -xiq emacs && emacsclient -n $@ || emacsclient -n -c --alternate-editor="" $@; }

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

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

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.