Редактор почти идеален, но было одно маленькое «но». В частности, бесило переключение раскладки. Недавно в личной беседе зашла речь о лежащих на пути использования Vim граблях, и решил я набросать эдакие «заметки на полях».
Казалось бы, ну что там такого: нажал сочетание, вводишь латиницу, нажал еще раз — кириллицу. Однако, в нормальном режиме, пребывание в котором занимает как минимум 80% времени, накладываются свои отпечатки. Ладно, про langmap, думаю, знают все.
Прописываем в ~/.vimrc следующее:
set langmap=ФИСВУАПРШОЛДЬТЩЗЙКЫЕГМЦЧНЯ;ABCDEFGHIJKLMNOPQRSTUVWXYZ,фисвуапршолдьтщзйкыегмцчня;abcdefghijklmnopqrstuvwxyz
И можем выполнять команды в нормальном режиме с кириллической раскладкой. Правда, для ввода команд через <:> по-прежнему требуется переключить раскладку, что бесило.
Тогда я вспомнил, что редактор имеет собственную переключалку.
set keymap=russian-jcukenwin
Более детально прием описывался, например, здесь.
Вроде бы, проблема решилась: раскладка переключается только в режиме вставки, а команды вводятся латиницей. Но вновь проблема: встроенная переключалка ну очень сильно конфликтует с иксовой. Да и дефолтное сочетание <C-^> не особо эргономично.
Отключать иксовую и полностью полагаться на Vim? В принципе, на это можно было пойти, но очень не хотелось. Вызывать редактор, для набора кириллических названий в терминале показалось мне некоторым перебором. Какое-то время пользовался, путался и матерился.
Так дело не пойдет, снова в гугл. Нашел интересную статью Храброва Дмитрия DeXPeriX о написанном им и Алексеем Радковым плагине vim-xkbswitch.
Вкратце, плагин делает следующее: при переходе в нормальный режим, переключает общесистемную раскладку (через xkb-switch, который должен быть установлен в системе) на латиницу, запомнив текущую раскладку, а при переходе в режим вставки, переключает на запомненную. Сказать, что я был рад — не сказать ничего. Огромная благодарность авторам за то, чего так не хватало все эти годы.
Однако, в процессе эксплуатации, столкнулся-таки с некоторыми трудностями. Зашел как-то на свой компьютер по ssh:
$vim file.txt
Vim: Caught deadly signal SEGV
Vim: Finished.
zsh: segmentation fault vim file.txt
Сразу на плагин не подумал, были мысли о посыпавшемся жестком диске, сбойнувшей файловой системе и тому подобных «приятных» вещах… В общем, xkb-switch при неустановленной переменной DISPLAY выпадает в segfault, а следом за ним и плагин, унося за собой и vim.
В качестве решения, можно проверить задана ли переменная и, только в случае успеха, активировать плагин. Выглядит это примерно так:
if $DISPLAY == ""
let g:XkbSwitchEnabled = 0
else
let g:XkbSwitchEnabled = 1
let g:XkbSwitchLib = '~/.local/lib/libxkbswitch.so'
let g:XkbSwitchIMappings = ['ru']
endif
После этого вылеты прекратились. Если хочется иметь функционал плагина при редактировании по ssh, то нужно подключаться с поддержкой X-forwarding'a, с ключами -X или -Y.
Надеюсь, статья поможет сохранить немного нервных клеток.
UPD: Сделал pull request разработчику.
Комментарии (31)
MooNDeaR
15.02.2017 18:00-14Серьезно, когда уже наконец хоть ЧТО-НИБУДЬ начнет работать в линуксах без эпичного ё#линга.
P.S.
Сам линуксовод уже даже со стажем, но уже задолбался. Чувствую вернусь скоро на винду или разорюсь и куплю мак.acmnu
15.02.2017 18:52+2Под маком и виндой на виме будет ровно эта же проблема. Только решать её надо будет как-то по-другому.
mtex
15.02.2017 19:57+3Ну, увы, большой кнопки с надписью «сделать пи^Wхорошо всем и сразу» нет. В линуксе очень многое работает сразу и хорошо. А когда есть возможность подпилить что-то под личные предпочтения или по-быстрому пофиксить — это очень хорошо. Линукс я люблю, в том числе, за это.
rPman
16.02.2017 02:28+2Потелепатствую — вы про опенсорс.
Вы не поняли, в случае с проприетарной идеологией, у вас даже в мыслях не появятся желание (и тем более возможности) отойти от заранее проторенной дорожки, а значит и 'эпичного ё#линга' у вас будет поменьше, но он будет, чтобы это хотя бы просто заработало, особенно когда устареет!
с opensource же у вас появляется возможность сделать что то интересное, и возможно, иногда, даже не тратить на это море сил!
pmcode
15.02.2017 19:31А какое у вас DE? xkb-switch с какого-то момента перестал работать в Unity, а когда я перешел на Gnome 3, то оказалось что и в нем тоже. Некоторое время жил с такой штукой.
function SetUSLayoutGnome()
silent !qdbus org.gnome.SettingsDaemon.Keyboard /org/gnome/SettingsDaemon/Keyboard org.gnome.SettingsDaemon.Keyboard.SetInputSource 0
endfunction
Но сейчас по большей части ушел на Атом, потому что vim, если его использовать как IDE, обрастает каким-то жутким количеством костылей и теряет ту простоту, из-за которой им и приятно пользоваться.mtex
15.02.2017 19:59DE у меня нет, в качестве wm использую i3. Atom пробовал пользоваться, но концепция редактора, сляпанного из браузера меня как-то ужаснула. Как и то, что этот самый голый atom запускается гораздо медленнее моего обвешенного по самое «не могу» vim'a.
immaculate
15.02.2017 20:33+1Да, я так понял, что сейчас используется уже не xkb, а другие решения (какой-то im метод, детали уже не помню). Не знаю, с чем связано такое решение, оно гораздо хуже xkb: переключение случается не всегда (у меня CapsLock переключает раскладку, и иногда вместо переключения включается CapsLock), переключаются раскладки с задержкой, при переключении теряется фокус ввода (это самая раздражающая особенность).
bravosierrasierra
15.02.2017 19:57+1Именно по этой причине я ушёл на Emacs + evil-mode, которое и есть самый лучший vim на настоящий момент. Я привык во всех ОС переключаться по alt-space и мне важно было сохранять работоспособность на любой раскладке. Под windows при помощи punto-switcher было настроено игнорирование Emacs и переключение по alt-space. В самом emacs сделаны настройки:
(global-unset-key (kbd «M-SPC»))
(global-set-key (kbd «M-SPC») 'toggle-input-method)
(define-key helm-map (kbd «M-SPC») 'toggle-input-method)
(define-key isearch-mode-map (kbd «M-SPC») 'toggle-input-method)
(setq mac-command-modifier 'meta)
(setq mac-option-modifier 'super)
(setq mac-pass-command-to-system nil)
(setq mac-pass-control-to-system nil)
В результате под windows и mac всё ок и во всех приложениях язык переключается Alt/Cmd+Space. Под Linux Mint после недолгих плясок с штатными настройками DE заработало само.
mtex
15.02.2017 20:01Evil-mode я пробовал, в свое время. Сильно не порадовало, что нужно держать в голове (или, скорей, намоторивать рефлексы) на два типа хоткеев: для vim и, собственно, родные emacs'овские. Потому, что evil-mode распространяется, увы, не на все: в том же dired, например, не работает.
bravosierrasierra
15.02.2017 20:22+1да, пришлось evil-ифицировать всё нижеприведёнными маппингами и emacs заиграл очень яркими красками.
Возни было много, но результат меня радует, уж больно сильно комбайн emacs превосходит текстовый редактор vim. Один только org-mode для меня, как менеджера, уже окупил emacs. Ещё очень радует связка tramp+eshell+dired+compile, когда я отлаживаю код на удалённых серверах как на локальной машине и при этом по M-x eshell попадаю в шелл на том сервере, файл которого у меня в буфере.
Начинающим, чтобы не заморачиваться, стоит использовать spacemacs, там как раз всё приведено к единой vim-системе.
Мои наборы для примера:
(define-key dired-mode-map (kbd "<M-return>") 'shell-instead-dired)
(define-key dired-mode-map (kbd «K») 'dired-do-kill-lines)
(define-key dired-mode-map (kbd «k») 'dired-previous-line)
(define-key dired-mode-map (kbd «J») 'dired-goto-file)
(define-key dired-mode-map (kbd «j») 'dired-next-line)
(define-key dired-mode-map (kbd «M-p») 'ace-window)
(define-key dired-mode-map (kbd «M-q») 'ace-window)
(define-key dired-mode-map (kbd "/") 'helm-occur)
;; в любом режиме Alt+hjkl ведут себя как обычный vim
(global-set-key (kbd «M-h») 'backward-char)
(global-set-key (kbd «M-j») 'evil-next-line)
(global-set-key (kbd «M-k») 'evil-previous-line)
(global-set-key (kbd «M-l») 'forward-char)
(define-key evil-insert-state-map (kbd «M-h») 'backward-char)
(define-key evil-insert-state-map (kbd «M-j») 'evil-next-line)
(define-key evil-insert-state-map (kbd «M-k») 'evil-previous-line)
(define-key evil-insert-state-map (kbd «M-l») 'forward-char)
(loop for (mode. state) in '((inferior-emacs-lisp-mode. emacs)
(nrepl-mode. insert)
(pylookup-mode. emacs)
(chronos-mode. emacs)
(comint-mode. normal)
(shell-mode. insert)
(eshell-mode. emacs)
(git-commit-mode. insert)
(git-rebase-mode. emacs)
(term-mode. emacs)
(help-mode. motion)
(helm-grep-mode. emacs)
(grep-mode. emacs)
(bc-menu-mode. emacs)
(elfeed-show-mode. emacs)
(elfeed-search-mode. emacs)
(rdictcc-buffer-mode. emacs)
(dired-mode. emacs)
(image-dired-thumbnail-mode. emacs)
(ztree-mode. emacs)
(diff-mode. emacs)
(vc-svn-log-view-mode. emacs)
(wdired-mode. normal))
do (evil-set-initial-state mode state))
(push '("\\*CAPTURE-\\*". insert) evil-buffer-regexps)
(push '("\\*help\\*". motion) evil-buffer-regexps)
(push '("\\*chronos\\*". emacs) evil-buffer-regexps)
(push '("\\*eshell\\*". emacs) evil-buffer-regexps)
(push '("\\*backtrace\\*". emacs) evil-buffer-regexps)
(push '("\\*vc-\\*". insert) evil-buffer-regexps)
(evil-define-key 'normal magit-mode-map
«j» 'magit-goto-next-section
«k» 'magit-goto-previous-section)
(evil-define-key 'normal magit-log-mode-map
«j» 'magit-goto-next-section
«k» 'magit-goto-previous-section)
(evil-define-key 'normal magit-diff-mode-map
«j» 'magit-goto-next-section
«k» 'magit-goto-previous-section)
;; Make HJKL keys work in special buffers
(evil-add-hjkl-bindings magit-branch-manager-mode-map 'emacs
«K» 'magit-discard
«L» 'magit-key-mode-popup-logging)
(evil-add-hjkl-bindings magit-status-mode-map 'emacs
(kbd «DEL») 'magit-discard
«K» 'magit-discard
;; «l» 'magit-key-mode-popup-logging
«l» 'magit-log-popup
«h» 'magit-toggle-diff-refine-hunk)
(evil-add-hjkl-bindings ztree-mode-map 'emacs)
(evil-add-hjkl-bindings magit-log-mode-map 'emacs)
(evil-add-hjkl-bindings magit-commit-mode-map 'emacs)
(evil-add-hjkl-bindings occur-mode 'emacs)
(evil-define-key 'motion compilation-mode-map
«h» 'evil-backward-char
)
(define-key compilation-mode-map
(kbd «C-u») 'evil-scroll-up
)
;;;; Evil-leader
(require 'evil-leader) ;; https://github.com/cofi/evil-leader
(evil-leader/set-leader «SPC»)
(global-evil-leader-mode)
(evil-leader/set-key
«0» 'select-window-0
«1» 'select-window-1
«2» 'select-window-2
«3» 'select-window-3
«4» 'select-window-4
«5» 'select-window-5
«6» 'select-window-6
«7» 'select-window-7
«8» 'select-window-8
«9» 'select-window-9
"" 'evil-buffer
«b» 'ido-switch-buffer
;; «t» 'helm-chronos-add-timer
«t» 'chronos-add-timers-from-string
«T» '(lambda() (interactive)(switch-to-buffer "*chronos*"))
«c» 'org-ctrl-c-ctrl-c
«e» 'eshell
«f» 'helm-find-files
«w» 'avy-goto-word-or-subword-1
«W» 'evil-ace-jump-char-mode
«l» 'evil-ace-jump-line-mode
;; «l» 'avy-goto-line
«SPC» 'evil-ace-jump-word-mode
«d» 'kill-this-buffer
«D» 'other-window-kill-buffer
«o» 'helm-occur
;; «i» 'helm-imenu
«i» 'helm-semantic-or-imenu
«p» 'projectile-find-file
«g» 'magit-status
;; «j» 'ranger
«j» 'dired-jump
«k» 'kill-buffer
«u» 'undo-tree-visualize
«y» 'helm-show-kill-ring
«s» 'save-buffer
"|" '(lambda () (interactive) (split-window-horizontally) (other-window 1))
«m» 'folding-toggle-show-hide
«nh» 'org-habit-toggle-habits
«nb» 'bss/org-toggle-budgets-and-habits
«nn» 'bss/org-todo
«nd» 'org-deadline
«na» 'org-archive-subtree-default
«nr» 'bss/org-refile
«nm» 'bss/org-refile
«nf» 'org-narrow-to-subtree ;; focus
«ns» 'bss/org-schedule
«nw» 'widen ;;unfocus
«ny» 'org-cut-special
«nc» 'org-capture
«nt» 'org-ctrl-c-ctrl-c
«v» 'org-capture
«x» 'nlinum-mode
"-" (lambda () (interactive) (split-window-vertically) (other-window 1))
"/" 'helm-occur
;; «gg» '(lambda () (interactive) (w3m-search «g» (thing-at-point 'symbol)))
)mtex
15.02.2017 20:34Спасибо, сохранил набор биндингов на всякий случай. Хотя, к Vim'у я прирос слишком сильно и вряд ли сменяю его на Emacs.
olegkrasnov
15.02.2017 21:18+1Такой лонгрид под спойлер бы =)
bravosierrasierra
15.02.2017 21:30Простите, не знал про спойлеры в комментариях. Править собственный комментарий не могу, нету контролов для правки. У меня конфиг 7841 строчка и 313килобайт, вот это лонгрид, да. :) Чего я только туда за полтора года битвы за перфекционизм не запихал: и punto switcher и 100500 тюнингов всего подряд. И хочется ещё пилить и пилить :) Сейчас пробую программировать в intellij idea на питоне over ssh и понимаю что в общем-то на уровне моих задач вся эта магия у меня уже есть в emacs спустя полтора года настроек :)
immaculate
15.02.2017 21:43+1Справедливости ради, допилить Emacs до того уровня, чтобы он понимал Python как PyCharm — невозможно. Когда работаешь с большими проектами, возможности PyCharm понимания кода и рефакторинга — неоценимы.
Например, когда открываешь простыню спагетти-кода, с функциями по 300-400 строк и переменными с названиями в один символ. PyCharm сразу подсветит, где в этих 300-400 строчных монстрах неиспользуемые переменные и ветки, потом потихоньку можно в нем безопасно дать переменным человеческие имена, а потом уже становится понятно, как работает этот код, и его можно переписать или разбить на более короткие и осмысленные функции/методы.
Да и с проектами меньшего размера тоже помогает. PyCharm как наркотик, слезть с него невозможно. :)
Использую в нем с первого дня плагин IdeaVIM, работает идеально.
bravosierrasierra
15.02.2017 22:10+1Если говорить о рафинированной эффективности программиста, то да, Intellij Idea/Pycharm это стандартный и чрезвычайно эффективный инструмент программиста. Но нужно понимать, что «достаточно хорошего» инструмента зачастую достаточно.
Для меня emacs это универсальный тамагочи, в котором можно эффективно и без вреда для других провести большую часть рабочего дня со всеми GTD/толканиями проектов/pomodoro/скриптописаниями/magit/tramp/dired. Причём особый шарм в том, что один и тот же конфиг ездит в онлайн-режиме вместе с одними и теми же заметками при помощи dropbox по куче машин с разными ОС, причём ездит в виде git-репозитория. Я отдаю себе отчёт, что Idea/Pycharm «just works», но тамагочи они не являются и фана мне не дают. И да, я их изучаю и мне ничего не мешает по мере необходимости запустить их и сделать что-то, что мне лень или сложно делать в emacs+unix. Я отдаю себе отчёт что если говорить о рациональности, то сейчас emacs и vim среднему айтишнику нужны на стартовом уровне, если вообще нужны. Но фана они могут подарить море. Мне дарят.am-amotion-city
16.02.2017 11:35-1при помощи dropbox [...], причём [...] в виде git-репозитория
Вот это я понимаю, это система будущего. Я бы еще туда куда-нибудь вовнутрь почту бы прикрутил, чтобы оно рассылалось аттачами на те машины, где нет клиента дропбокса.
С такой архитектурой можно главный приз на каком-нибудь конкурсе великих интеграционных решений взять, отвечаю.
olegkrasnov
16.02.2017 03:51Что vim, что emacs редакторы не дружелюбные и поглощают много времени на обучение.
Crandel
16.02.2017 11:11У меня в емакс есть flycheck-mode, который так само подсвечивает все pep8 ошибки и варнинги и зачастую приходится еще и исправлять после программистов с пайчармом, потому что они забивают на ворнинги. Для рефакторинга переменных и класов есть rope-mode так что разница не слишком большая.
immaculate
16.02.2017 14:09Сомневаюсь, что дело в PyCharm. PyCharm тоже подсвечивает все ошибки и ворнинги, даже эффективнее, чем любая сторонняя утилита, так как он знает о структуре проекта и умеет выводить типы. Если обладатель PyCharm их не фиксит — то это уже его личный выбор.
Когда в последний раз прикручивал rope-mode к emacs, это были неудобные и ненадежные костыли. Рад, если это изменилось — я в последний раз пользовался Emacs около 8-9 лет назад, уверен, что с тех пор произошли большие сдвиги.
Еще одна причина, по которой ушел с Emacs — туннельный синдром запястья. Поэтому сначала ушел на vim, затем на PyCharm с IdeaVim. Симптомы туннельного синдрома ушли.
olegkrasnov
16.02.2017 18:51Если вдруг туннельный синдром вернётся, попробуйте заняться штангой (это не шутка).
mpetrunin
15.02.2017 20:16А есть какая-то крутая статья про Emacs + evil-mode для vim-оводов? А то много упоминаний слышу, но чтобы кто-то зажёг и убедил меня, что так гораздо круче, ещё не видел.
Было бы здорово, если бы бы был текст (видео?) со всеми преимуществами.
bravosierrasierra
15.02.2017 20:34+1Вот о причинах, почему стоит попробовать evil-mode: https://www.youtube.com/watch?v=JWD1Fpdd4Pc
Вот quickstart-режим для начинающих с использованием spacemacs: https://www.youtube.com/watch?v=ZFV5EqpZ6_s&list=PLrJ2YN5y27KLhd3yNs2dR8_inqtEiEweE
Вот вводный курс по emacs от Бушенко, который мне помог втянуться: https://www.youtube.com/playlist?list=PLECBtie1W1tGlrbDDBvcxnttRR4IA5qZn
Вот краткое введение в elisp для начинающих: http://steve-yegge.blogspot.ru/2008/01/emergency-elisp.html
Вот «золотая» схема работы с org-mode для менеджеров: http://doc.norang.ca/org-mode.html
Кстати, как по мне, для использования emacs caps-lock обязательно должен быть замаплен как ctrl, иначе пальцы отвалятся, т.к. он был спроектирован под клавиатуру, у которой ctrl рядом с пробелом.
mpetrunin
15.02.2017 20:18Кстати, разумно было бы кинуть баг в список задач проекта: чтобы плагин сам определял, установлен ли $DISPLAY и матерился бы, что не установлен, и надо
ssh -Y
mtex
15.02.2017 20:22+1Кстати да проект вроде есть на git, попробую пулл-реквест сделать. Там, в принципе, эту проверку в начало плагина добавить, и дело в шляпе.
mpetrunin
15.02.2017 20:26Только я бы посоветовал, что всё-таки плагин пыхтел что-нибудь типа
забыли "-Y" в ssh!!!
или там что-то в таком стиле (не всегда же отсутствие $DISPLAY означает ssh-сессию, иногда это просто безиксовый терминал). :)mtex
15.02.2017 20:36Ну, xkb-switch валится не только при логине через ssh, то же самое поведение и в текстовой консоли. Вообще, по-хорошему, тут надо не плагин лечить, а именно xkb-switch, так как проблема в нем.
Wilk
16.02.2017 22:24Здравствуйте.
Сходная проблема есть и в Emacs: при переключении системной раскладки на русский язык какие-либо команды выполнить нельзя. Для себя я это и на Windows, и на Kubuntu решил очень просто: в настройках переключения раскладки включил использование отдельной раскладки для каждого отдельного приложения (могу ошибаться, но быть может даже окна на Kubuntu) и Emacs использовал только встроенную систему интернационализации и переключения раскладок. В результате волки сыты (всё равботает, я доволен), и овцы целы (не пришлось что-либо делать).
olegkrasnov
17.02.2017 00:09На маке xkbswitch не хочет работать за пределами /usr/local/
Променял его на ISS:
let g:XkbSwitchLib = $HOME.'/.vim/bin/libInputSourceSwitcher.dylib'
acmnu
Спасибо. Действительно полезная вещь.