LINUX.ORG.RU

Мой .emacs.d - IDE для Common Lisp (работает из коробки)

 , , , ,


2

5

Вобщем, причесал тут свои конфиги Емакса, и выложил на гитхаб.

https://github.com/Lovesan/.emacs.d

Для работы потребуется более-менее новый Emacs, такой как 29.1

Ну и SBCL (но в init.el можно раскомментить строчку и прописать свою реализацию, типа ecl). Если еще этого не сделали, также рекомендую загрузить в SBCL quicklisp чтобы библиотеки можно было вообще в пару кликов ставить.

Как только Emacs с такой конфигурацией запускается, он открывает:

  • REPL
  • scratch.lisp файл (какой это файл и где он лежит, можно поменять в init.el)
  • и открывает боковую панельку с tree-view директории scratch.lisp файла.

Дальше можно писать код, или нажать например в REPL запятую(,), и вводить команды SLIME-repl(для начала можно набрать help). inb4 побочные окошки, типа хелпа, закрываются кнопкой q на клавиатуре.

Вощем, включены SLIME, Magit(это интерфейс для гита в емаксе) и всякая мелочь для удобства. Тулбар выключен, менюха оставлена.

Для структурного редактирования кода на лиспе(включая Emacs Lisp), установлен пакет Lispy. Я раньше пользовался parinfer, но он меня окончательно достал. Lispy удобнее и к тому же легче конфигурируется.

SLIME там уже в принципе прилично настроенный, в частности даже есть немного подсветки синтаксиса для моей библиотеки bike

Но самая основная проблема которую я решил за вас(не благодарите), это поменял кейбиндинги Емакса на нормальные.

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

Итак, что я сделал, это я с помощью библиотеки rebinder.el, перенаправил префикс-сочетания C-x и C-c на C-e и C-d соответственно.

Это позволило сделать из емакса нормальный редактор кода. Да, в принципе, не хватало бы еще табов и прочих GUI-плюшек, но зато зацените, без всяких кривых CUA-mode, им наконец-то можно пользоваться.

Биндинги такие:

  • Ctrl+Q - выход из Емакса.

  • Меню/Apps (это такая кнопка рядом с правым контролом) - вызов расширенной команды по имени(типа то что в емаксе называют M-x)

Редактирование:

  • Ctrl+X - вырезать
  • Ctrl+C - копировать
  • Ctrl+V - вставка
  • Ctrl+Z - отмена
  • Ctrl+Y - вернуть
  • Ctrl+A - выделить весь текст

Также, я немного похакал так называемый killring и систему выделения текста, что еще больше приблизило Emacs к нормальным редакторам.

Управление буферами(такое обобщение понятия файла в емаксе):

  • Ctrl+O - открыть файл
  • Ctrl+S - сохранить буфер
  • Ctrl+W - закрыть текущий буфер
  • Alt+влево - предыдущий буфер
  • Alt+вправо - следующий буфер
  • F2 - открыть список буферов
  • Ctrl+PageDown - включает оверлей ace-window, который позволяет быстро переключаться между тайлами емакса(называемыми window). Он над каждым тайлом показывает цифру, которую надо нажать чтобы на него перейти.
  • F8 - показать/скрыть Neotree (это панелька с деревом файлов слева). Кстати в neotree теперь по Ctrl+клик мышью можно менять корень дерева файлов.

Поиск:

  • Ctrl+F - поиск вперед по тексту
  • Ctrl+Shift+F - поиск взад по тексту

Также в окошке поиска можно перемещаться стрелками, так стрелки вправо-влево управляют поиском вперед/назад по тексту, а стрелки вверх-вниз - просмотр история поиска.

Мышку кстати тоже в некоторой степени перебиндил, в частности доп. кнопки mouse-4 и mouse-5 (их обычно в современных ОС вешают на вперед/назад) управляют навигацией по буферам. В принципе, они позволяют выбирать следующий/предыдущий буфер, как Alt+влево/вправо, но с некоторыми нюансами, описанными ниже.

Кейбиндинги для Emacs Lisp и для SLIME:

  • F12 - Перейти к определению. Также, это можно сделать, клинкув на символ мышью, при этом зажимая Control(как во всех современных IDE).
  • F11 - Вернуться назад в стеке определений. Также это делается mouse-4, т.е. мышевой кнопкой «назад».
  • mouse-5 - Кнопка мыши «вперед» работает как своего рода «Redo» по отношению к предыдущей команду, т.е. она опять ныряет в стек определений, если перед этим из него был выход предыдущей командой.
  • F5 - Вычисляет выражение стоящее прямо перед курсором. Т.е. если есть форма (+ 1 2 3), курсор нужно ставить сразу после закрывающей скобки.
  • Alt-вверх - интеллектуальный переход наверх по S-выражению, с использованием Lispy.
  • Alt-вниз - интеллектуальный переход к следующему S-выражению, с использованием Lispy.

Кейбиндинги специально для SLIME:

  • F1 - информация о символе. Если вызывать на пустом месте, в командной строке нужно будет ввести имя символа. Если нажать над символом, то опишут его.
  • F3 - поиск по символам. Выведет список символов и краткое описание. Ищет только по тем символам, которые связаны с функциями, переменными, классами, итд.
  • F4 - Скрыть/показать REPL в текущем тайловом окне.
  • F6 - Скомпилировать и загрузить текущий файл

Пока что больше кастомных кейбиндингов нет, и все остальные на своих местах, но еще раз, надо помнить, что префикс-сочетание С-x перевешано на С-e, а С-c на С-d, так что меняйте это в уме, если где-то в документации по тому же Magit это видите. Но кстати с такими префиксами, работать со всем дефолтом даже удобнее, не так устают пальцы. А, еще в Lispy отрубил клавишу e, чтобы не мешалась, и еще там несколько мелочей в нем отрубил или поправил.

Ксатит вот где можно еще почитать по SLIME, Lispy и Magit:

★★
Ответ на: комментарий от lovesan

в этом фишка программируемости Emacs, что он это позволяет.

В теории да, а на практике получается как у тебя, приколхоженое сбоку нечто. Потому что перелопатить все у всех кишка тонка. Проще уж действительно всё выкинуть и написать с нуля на CL.

они стандартные для современных клавиатур, для работы с текстом

Ты удивишься, но на современных клавиатурах есть специальные кнопки для этого: delete, insert. И они даже работают. Везде. И даже в emacs, внезапно.

no-such-file ★★★★★
()

Нахрен вообще этот Emacs нужен? Взял книгу по нему и уже второй раз бросаю на первых главах с таким вопросом. Авторы книг по Лиспам рекомендуют именно его, но пердолиться с конфигами вообще никакого желания: отпердолился. Для всего остального давно использую базовую Zver CD сборку Vim’а.

Pwner
()

Это позволило сделать из емакса нормальный редактор кода.

У каждого увожаемого пацана, который умеет немного в elisp это понятие своё xD

Кроме кривого убогого CUA mode, щас в емаксе по сути распространены только вим-кейбиндинги и дефолт, и вот эти оба это натурально звиздец, одно хуже другого. Одно родом из 70х, и вообще трешак для терминала, а второе это для клавиатур старых-лисп машин, которые используют только позеры. И вот это - реально звиздец.

Ты просто нубас в настройка клавиатур, признай. Номальные пацаны, которых ты тут позерами обзываешь, навсегда решили Emacs pinky, скопировав расположение с оригинала и добавив Dvorak, чтобы двумя лапами жать кнопы. В Dvorak сочетания по умолчанию намного приятнее.

Поехавшие и позеры могут закомментить в init.el форму (require ’lvsn-keys)

Эк, дядь, так нельзя. Поехавшие и позеры сами с усами и могут накрутить чего хотят и без Лавсана. И получается, что у тебя аудитория только запустившая Emacs. Вот она откроет твой конфиг и натырит, что понравится себе.

Проблема еще в отсутствии консистентности примерно со всеми остальными редакторами и программами. Мышечная память рубится от постоянных переключений.

А тут ты попался. Readline используется по умолчанию везде. И в Mac вообще по умолчанию, даже в FF. Ты что, в консоль ссышь?

Позже ты отвечаешь про «терминалы - говно из 70». Запишем - Лавсан нубло. То-то Wmenu сделали в Sway по образу Dmenu. И с Vertico пацаны по проекту открывают файл на раз-два и по буферам (где не закрыто ничего, зачем?) парой символов. Как выше писали, модно-молодёжно перебирать, допустим, S-Tab, Tab назад-вперёд, если у тебя до пяти, а дальше онанизм. А если Emacs в server-mode? А если только в маленьком проекте у меня открыто до 15 файлов? А если я использую (desktop-save-mode 1)? Понабирались говна и распостраняют. Это тебе не IDE, где каждый открытый файл помогает выжирать память.

Ладно, проехали. Лучше бы помог сообществу и причесал новый LSP сервер под Eglot. Похоже это особенно актуально с будущими ограничениями MS (вроде будут блокировать VS и VSCode). Да, сложновато, так как Eglot теперь в core, а рассылки у нас…

masterOf
()
Ответ на: комментарий от Pwner

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

Он расширяемый, и его можно приспосабливать под задачу. Подобное нормально сделать смогли только в Atom и VSCode, и то не совсем. Это значит что тебе не нужно ждать от большой корпорации IDE для какого-либо языка, а в теории можешь сам написать. Или хотя бы поправить что не нравится. Для лиспа рекомендуют именно потому что для лиспа бесплатная IDE есть только в емаксе, называется SLIME.

lovesan ★★
() автор топика
Ответ на: комментарий от no-such-file

В теории да, а на практике получается как у тебя, приколхоженое сбоку нечто. Потому что перелопатить все у всех кишка тонка.

На практике, у меня вменяемая конфигурация, с которой можно хоть как-то жить. А не наркомания, которая всех нормальных людей отталкивает.

То что я не дописал, я просто вызываю как команду.

lovesan ★★
() автор топика
Ответ на: комментарий от lovesan

Выпей таблеток

(require ’use-package) - это ты правильно. :ensure t везде прописывать, это по нашему, по колхозному. Зато на критику сразу посылаешь пить таблетки. Чем дальше я смотрю, тем больше проглядывает нуб.

anonymous
()
Ответ на: комментарий от lovesan

В Emacs несколько реализаций табов. Все они кроме одного хуже, чем в NeoVim/VSCode/IntelliJ IDEA. Но одна реализация табов даже лучше, чем в вышеперечисленных при условии сильной кастомизации: tabbar-mode. Могу скинуть свой конфиг.

Kostafey
()

Но самая основная проблема которую я решил за вас(не благодарите), это поменял кейбиндинги Емакса на нормальные.

Установил evil-mode?

Извините, не смог не воспользоваться такой масштабной подводкой. Вообще, меня Kakoune порадовал, жаль для него пока ничего нет кроме собственно текстового редактора.

Gentooshnik ★★★★★
()
Ответ на: комментарий от Pwner

Нахрен вообще этот Emacs нужен?

Редактировать текст. И решать задачи, сводимые к редактуре текста. Т.е. почти вообще все задачи, кроме графики-музыки и прочего такого.

ugoday ★★★★★
()
Ответ на: комментарий от anonymous

Чем дальше я смотрю, тем больше проглядывает нуб.

А это происходит почти во всех темах, которые затрагивает ТС. Например, человек обильно поливал помоями плюсы, называя каждого неосилятором «нормальных» языков и выпускником сельской школы, пока не принес собственный код на плюсах, где оказалось, что все его слова в первую очередь были на 100% применимы к нему же самому.

Человек будто не может вырасти из образа 16летнего эджи бунтаря, либо же пытается отыгрывать кого-то вроде Тео/Линуса(жесткого и справедливого), но отыгрывалка не выросла(

anonymous
()
Ответ на: комментарий от lovesan

А вы перефорсом не занимайтесь, лучше обьясните почему позорно ушли от ответа, когда вас справедливо прижали вот тут.

Разве это поведение человека образ которого вы пытаетесь имитировать?

anonymous
()
Ответ на: комментарий от Kostafey

tabbar-mode

Если имеется в виду tab-bar-mode, то удваиваю. Крайне годная штука — практически несколько независимых воркспейсов можно организовать. Один проект в одном табе, другой в другом, орг-моде с заметками в третьем — лепота. Добавить desktop.el, чтобы вручную это всё не сохранять/восстанавливать при перезапуске емакса — и вообще рай на земле.

А ведь думал, что табы ненужны, пока не попробовал из любопытства.

Nervous ★★★★★
()
Ответ на: комментарий от Pwner

Нахрен вообще этот Emacs нужен?

org-mode. Ну и с лиспами он традиционно хорошо дружит. И вообще он шикарный и винтажный.

Авторы книг по Лиспам рекомендуют именно его, но пердолиться с конфигами вообще никакого желания

Именно для лиспов там вообще ничего практически не надо делать, поставил geiser/SLIME/SLY/CIDER и алга.

Nervous ★★★★★
()
Последнее исправление: Nervous (всего исправлений: 2)
Ответ на: комментарий от Nervous

Нет, имелся в виду не встроенный tab-bar-mode. Он мне как-раз не зашел. Подозреваю, при большом желании можно было бы кастомизировать под себя, как-то попробовал было даже но забросил на полдороги, т.к. tabbar-mode всем устраивает. Последняя на сегдняшний момент версия в MELPA от 2018 года.

https://github.com/dholm/tabbar

Kostafey
()
Ответ на: комментарий от lovesan

В паблике это лежит давно: https://github.com/kostafey/kostafeys-emacs-confik.

Но там искать нужно будет что к чему, лучше приведу тут с комментариями:

(require 'tabbar)

(tabbar-mode t)

; Их отключение сильно место экономит
;; Hide forward and back buttons
(customize-set-variable 'tabbar-scroll-right-button '(("") ""))
(customize-set-variable 'tabbar-scroll-left-button '(("") ""))
(customize-set-variable 'tabbar-buffer-home-button '(("") ""))

; Я думаю, тут комментарии излишни, единственное, что можно
; упомянуть, что порядок буферов в списке может не совпадать
; с порядком табов, а это очень удобно визуально переключаться
; между ближайшими видимыми буферами/табами
(if (require 'tabbar nil 'noerror)
    (progn
      (global-set-key (kbd "C-<next>") 'tabbar-forward-tab)
      (global-set-key (kbd "C-<prior>") 'tabbar-backward-tab))
  (progn
    (global-set-key (kbd "C-<next>") 'next-buffer)
    (global-set-key (kbd "C-<prior>") 'previous-buffer)))

; Всякие спецбуферы типа *lsp-log* выводятся в отдельной 
; группе табов (чтобы было меньше шума).
; Единственное исключение - буферы типа *temp-1*, *temp-2*  и.д.,
; которые я использую для заметок.
(setq tabbar-buffer-groups-function
      '(lambda ()
         (list
          (cond
           ((and (find (aref (buffer-name (current-buffer)) 0) " *")
                 (not (string-match
                       "^\\*temp\\(-[0-9]+\\)?\\*$"
                       (buffer-name b))))
            "*")
           (t "All Buffers")))))

; Фильтрация буферов для отображения в табах
(setq tabbar-buffer-list-function
      '(lambda ()
         (delq nil
               (mapcar #'(lambda (b)
                           (cond
                            ;; Always include the current buffer.
                            ((eq (current-buffer) b) b)
                            ((buffer-file-name b) b)
                            ((char-equal ?\  (aref (buffer-name b) 0)) nil)
                            ((buffer-live-p b) b)))
                       (-filter
                        (lambda (b) (or (eq (current-buffer) b)
                                   (buffer-file-name b)
                                   (string-match
                                    "^\\*temp\\(-[0-9]+\\)?\\*$"
                                    (buffer-name b))))
                        (buffer-list))))))

; Отключить табы для спецбуферов, если мы делим окно вертикально,
; сохранив при этом ключи для навигации по буферам
(defun k/select-window-fix-tabbar ()
  "Hide `tabbar' for buffers displayed in windows located
not in the top of the frame."
  (when tabbar-mode
    (-map
     (lambda (window)
       (let ((buffer (window-buffer window)))
         (with-current-buffer buffer
           (condition-case nil
               ;; Keep `tabbar' if
               (if (or
                    ;; buffer is displayed in window located
                    ;; in the top of the frame
                    (not (> (cadr (window-edges window)) 0))
                    (and
                     ;; or this buffer displayed in other window too
                     (> (length (get-buffer-window-list buffer)) 1)
                     ;; but not only in the bottom windows.
                     (not (-all?
                           (lambda (w) (> (cadr (window-edges w)) 0))
                           (get-buffer-window-list buffer)))))
                   (tabbar-local-mode -1)
                 ;; Hide `tabbar' otherwise.
                 (tabbar-local-mode 1))
             (error nil)))))
     (window-list))
    (global-set-key (kbd "C-<next>") 'tabbar-forward-tab)
    (global-set-key (kbd "C-<prior>") 'tabbar-backward-tab)))

; Используется, например, так:
(when (require 'ejc-sql nil 'noerror)
  (add-hook 'ejc-sql-complete-query-hook 'k/select-window-fix-tabbar))
Kostafey
()
Последнее исправление: Kostafey (всего исправлений: 3)
Ответ на: комментарий от Bad_ptr

Ну ты хотя бы сделай чтобы такие биндинги ставились отдельной функцией и только тем, кому это надо..

А то выглядит так что ты пришёл в мечеть размахивая радужным флагом… Это плохо для популярности.

Выглядит так, что люди программируют под свои хотелки изначально задуманный как программируемый под хотелки текстовый редактор, а старый дед им говорит: «Не надо слишком сильно программировать, мое чувство прекрасного страдает!»

Деда, не страдай так! :)

Virtuos86 ★★★★★
()
Ответ на: комментарий от lovesan

Проблема еще в отсутствии консистентности примерно со всеми остальными редакторами и программами. Мышечная память рубится от постоянных переключений.

Эт да. Я в свое время, познакомившись с линупсом после «хрюши», хотел пользоваться переключалкой раскладки на Ctrl+Shift. Казалось, это более разумно – клавиши рядом располагаются, и контрол в углу клавиатуры находится => на ощупь легче ориентироваться. Но потом сказалось чередование работы/эникейства то на венде, то на линупсе на разных компах, и вернулся к Alt+Shift, на чем благополучно и остановился. Может, и безобразно, зато единообразно и без досадных ступоров.

Virtuos86 ★★★★★
()
Ответ на: комментарий от no-such-file

Чтобы что? Чтобы тупорылые макаки, которые не могут запомнить несколько новых кнопок пытались в ЛИСП? Может не надо?

Как чистокровно по-арийски замечено :D.

Virtuos86 ★★★★★
()
Последнее исправление: Virtuos86 (всего исправлений: 1)
Ответ на: комментарий от ugoday

вместо projectile или вместе с ним?

Вместе. Вкладки, чтобы сменить проект, projectile для перемещения внутри проекта. Можно и без вкладок обойтись, конечно, но мне нравится одним взглядом видеть всё, над чем работаю.

Nervous ★★★★★
()
Ответ на: комментарий от no-such-file

Это шляпа. Лучше педали для пианино. Там можно сразу блок на 3 взять и они гораздо удобнее.

Ага, а педаль expression вообще 14-битное значение передаёт по midi. Можно приспособить для переключения режимов в evil.

Gentooshnik ★★★★★
()
Ответ на: комментарий от no-such-file

Мне так кажется что VS не принято держать постоянно запущенной и открывать там по 500 файлов одновременно.

Зачем их открывать одновременно? Вот допустим у тебя есть 10 проектов. Ты создаешь 1 workspace, и включаешь в него 10 папок, дальше уже если что то надо отредактировать, то ты открываешь файл в этих папках на сайдбаре, или через поиск, и редактируешь.

В чем преимущество того, что они находятся в списке открытых файлов, перед тем что бы просто их открывать через поиск файлов?

MOPKOBKA ★★★★★
()
Последнее исправление: MOPKOBKA (всего исправлений: 1)
Ответ на: комментарий от MOPKOBKA

В чем преимущество того, что они находятся в списке открытых файлов

Дело не в том, что есть преимущество, а в том, что в emacs открытые файлы нигде не маячат постоянно. А табы видно всегда, поэтому приходится их закрывать, чтобы не мешались. При этом переключаться по табам с клавиатуры не то чтобы удобно.

Ну в качестве преимущества, впрочем спорного, можно назвать то, что постепенно набор файлов с которыми ты работаешь в проекте оказывается открытым и поиск становится чуть более быстрым и удобным (ты изначально не видишь нерелевантные файлы).

no-such-file ★★★★★
()
Ответ на: комментарий от no-such-file

Ты удивишься, но на современных клавиатурах есть специальные кнопки для этого: delete, insert. И они даже работают. Везде. И даже в emacs, внезапно.

Такое может написать только человек, который так и не научился набирать и редактировать текст.

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

anonymous
()
Ответ на: комментарий от no-such-file

Дело не в том, что есть преимущество, а в том, что в emacs открытые файлы нигде не маячат постоянно. А табы видно всегда, поэтому приходится их закрывать, чтобы не мешались. При этом переключаться по табам с клавиатуры не то чтобы удобно.

Скрыть табы можно и в VSCode, переключаться по файлам через поиск файлов.

Ну в качестве преимущества, впрочем спорного, можно назвать то, что постепенно набор файлов с которыми ты работаешь в проекте оказывается открытым и поиск становится чуть более быстрым и удобным

Это поиск по Recent Files

MOPKOBKA ★★★★★
()
Ответ на: комментарий от MOPKOBKA

Скрыть табы можно и в VSCode, переключаться по файлам через поиск файлов.

И получится как в emacs, вид сбоку. Мой вопрос был в обратную сторону, зачем и как прикручивать табы в emacs.

поиск по Recent Files

Поэтому я и говорю, что спорно. Просто так получается из-за реализации. Другой бонус, например это поиск по открытым буферам проекта. И т.п., вообще, любая пакетная операция/обработка. Да это можно прикрутить и в условный vscode, но это отдельная фича. А тут автоматически получается, потому что такая архитектура.

Для понимания, буферы ты можешь открыть/закрыть как тебе надо. А recent files это именно последние файлы, этот список неизменяемый.

no-such-file ★★★★★
()
Последнее исправление: no-such-file (всего исправлений: 1)
Ответ на: комментарий от no-such-file

И получится как в emacs, вид сбоку. Мой вопрос был в обратную сторону, зачем и как прикручивать табы в emacs.

Состояние вкладок в JetBrains IDE сохраняется, поэтому можно переключаться по задачам, и у тебя есть нужные вкладки, их тыкать мне как то быстрее, чем где то выбирать или искать файл.

Лучше бы lovesan сделал CL плагин к IDEA Community.

MOPKOBKA ★★★★★
()
Последнее исправление: MOPKOBKA (всего исправлений: 1)
Ответ на: комментарий от MOPKOBKA

их тыкать мне как то быстрее, чем где то выбирать или искать файл

Чтобы тыкать тоже нужно выбирать и искать, только уже самому и глазами. Мне удобнее через автоматический поиск.

no-such-file ★★★★★
()