LINUX.ORG.RU

[Emacs] смена текущей директории при переходе на ошибку

 


0

0

При переходе на ошибку в еще не открытый файл, emacs меняет для него значение текущей директории. Как запретить emacs менять текущую директорию? Или может можно как-нибудь поведения перехода по ошибкам изменить?

Решил в лоб, добавив в .emacs измененую функцию find-file-noselect-1:

(defun find-file-noselect-1 (buf filename nowarn rawfile truename number)
  (let (error)
    (with-current-buffer buf
      (kill-local-variable 'find-file-literally)
      ;; Needed in case we are re-visiting the file with a different
      ;; text representation.
      (kill-local-variable 'buffer-file-coding-system)
      (kill-local-variable 'cursor-type)
      (let ((inhibit-read-only t))
	(erase-buffer))
      (and (default-value 'enable-multibyte-characters)
	   (not rawfile)
	   (set-buffer-multibyte t))
      (if rawfile
	  (condition-case ()
	      (let ((inhibit-read-only t))
		(insert-file-contents-literally filename t))
	    (file-error
	     (when (and (file-exists-p filename)
			(not (file-readable-p filename)))
	       (kill-buffer buf)
	       (signal 'file-error (list "File is not readable"
					 filename)))
	     ;; Unconditionally set error
	     (setq error t)))
	(condition-case ()
	    (let ((inhibit-read-only t))
	      (insert-file-contents filename t))
	  (file-error
	   (when (and (file-exists-p filename)
		      (not (file-readable-p filename)))
	     (kill-buffer buf)
	     (signal 'file-error (list "File is not readable"
				       filename)))
	   ;; Run find-file-not-found-functions until one returns non-nil.
	   (or (run-hook-with-args-until-success 'find-file-not-found-functions)
	       ;; If they fail too, set error.
	       (setq error t)))))
      ;; Record the file's truename, and maybe use that as visited name.
      (if (equal filename buffer-file-name)
	  (setq buffer-file-truename truename)
	(setq buffer-file-truename
	      (abbreviate-file-name (file-truename buffer-file-name))))
      (setq buffer-file-number number)
      (if find-file-visit-truename
	  (setq buffer-file-name (expand-file-name buffer-file-truename)))
      ;; Set buffer's default directory to that of the file.
      ;; (setq default-directory (file-name-directory buffer-file-name))
      ;; Turn off backup files for certain file names.  Since
      ;; this is a permanent local, the major mode won't eliminate it.
      (and backup-enable-predicate
	   (not (funcall backup-enable-predicate buffer-file-name))
	   (progn
	     (make-local-variable 'backup-inhibited)
	     (setq backup-inhibited t)))
      (if rawfile
	  (progn
	    (set-buffer-multibyte nil)
	    (setq buffer-file-coding-system 'no-conversion)
	    (set-buffer-major-mode buf)
	    (make-local-variable 'find-file-literally)
	    (setq find-file-literally t))
	(after-find-file error (not nowarn)))
      (current-buffer))))

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

Есть другой способ изменить поведение find-file?

К тому же в виме подобная операция не прокатит, а emacs подобную лаботамию прекрасно переносит. Я кстати только строку `(setq default-directory (file-name-directory buffer-file-name))` закомментировал, все остальное копипаст из `files.el`.

plambir
() автор топика

Что-то сразу не понял. Подробнее объясни, что он там меняет и какое поведение требуется. С default-directory игрался?

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

Меняет он как раз default-directory. Требуется что бы default-directory менялась только по команде cd. Если меняется default-directory то вызов compile соответственно будет искать скрипт сборки не в той папке в которой это скрипт находиться, то есть куда ранее была перенесена эта default-directory командой cd, а в той где находиться файл с ошибкой.

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

Насколько я понимаю, задача состоит в следующем. Ты находишься в каком-то файле проекта, делаешь M-x compile. При этом тебе надо, чтобы вызвался Makefile, который находится директорией выше. Так, может быть, разумнее решать задачу поиска Makefile, нежели затевать игру с default-directory?

http://www.emacswiki.org/emacs/CompileCommand#toc5

http://www.emacswiki.org/emacs/UsingMakefileFromParentDirectory

И т. д.

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

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

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

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

Ну так есть там по ссылке функции, которые ищут Makefile, который лежит в одном каталоге с configure.ac (Similar, but using nearest Makefile in directory with "configure.ac") независимо от того, есть ли уже в текущем каталоге Makefile или нет. Есть там функция, которая реализует компиляцию в другой директории (Compile in another directory). Может, что из этого подойдет?

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

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

Emacs в базовом варианте не реализует управление проектом (их же разных великое множество). А вот эта чехорда с Makefile -- это уже элементы управления. Однако это управление реализуется пакетами. Например, CEDET. Есть и другие, специфичные для каких-то языков, систем.

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

>Если все это не подойдет, то можно написать функцию, которая поднимается по директориям вверх, пока не дойдет до директории, где Makefile нет. Тогда принимается решение, что в предыдущем каталоге был Makefile верхнего уровня.

Хотя это решение частного случая, так как в общем случае в иерархии Makefile, наверное, могут быть дырки, то есть подкаталоги, которые не содержат Makefile, а уже их подкаталоги содержат.

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

Поиск Makefile'ов не удобен еще и тем, что в случае параллельного использования scons, для других проектов, поиск Makefile'а нужно будет заменять на SConstruct. Поэтому, мне кажется, удобнее просто сменить директорию и не особо задумываться чем сейчас собирать проект, точнее что будет искатся для сборки. Можно конечно в зависимости от команды определять какой файл с инструкцией сборки искать, но это как-то через чур, по моему. Если оставлять авто смену директории, то можно явно указывать где лежит инструкция по сборке, тогда вне зависимости от текущей default-directory, будет использоваться именно тот скрипт что нам нужен.

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

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

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

И проектики подобные мимо меня проскакивали, но я их не пробовал никогда, честно скажу. Например, proel.el (http://www.stifflog.com/2008/12/14/proel-project-support-for-emacs/). Там тоже заявлен поиск Makefile и распознавание проекта. Ну и на emacswiki есть всякие разные. Такой, например: http://www.emacswiki.org/emacs-zh/ProjmanMode (тоже не испытывал).

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

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

а я могу запустить команду компиляции проекта в любое время,
т.к. у меня записан в информации о проекте полный путь
к файлу сборки.
По количеству строк код, который за все отвечает, равен
количеству кода функции find-file-noselect-1
И у меня нет никакой черной магии с автопределением файла сборки.
Пример: ресурсы для проекта я собираю с помощью Common Lisp.
Из REPL'а я запустил сборку ресурсов и тут же жму F5 для сборки моего
проекта с новыми ресурсами. И мне не важно знать какой был
полный путь у емакса, когда я запускал slime

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

>а я могу запустить команду компиляции проекта в любое время, т.к. у меня записан в информации о проекте полный путь к файлу сборки.

>И у меня нет никакой черной магии с автопределением файла сборки.

Так, насколько я понимаю, это только тогда, когда ты открывал именно проект, а не просто файл. Или не так? То есть, ты загрузил Emacs, потом C-x C-f blahblah.c и тут же compile. Он соберет проект, к которому принадлежит этот blahblah.c или надо сначала явно указать название проекта? Вот в этом случае нужно автоопределение. Либо по эвристике какой типа configure.ac, либо используя твою базу проектов, где указаны пути к ним. Я, например, для тех проектов, которыми занимаюсь, не использую никакую метаинформацию. По счастливой случайности все они сделаны через autotools, поэтому меня вполне устроил способ поиска Makefile с configure.ac.

Пакетик по второй ссылке, которую я привел, делает именно то, что у тебя. Там тоже указываются пакеты с путями и способами компиляции, реализуется переключение между пакетами и т. п., запоминание открытых буферов проекта и что-то там еще.

Zubok ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.