Що не так з `find-file-noslect`?


11

У недавньому відповіді по lunaryorn , він заявив:

Однак я б рекомендував проти більшості інших частин Org з причин, які вже були зазначені в коментарях: Він старий і сповнений спадщини та шкідливих практик (наприклад, find-file-noselect для читання файлів неінтерактивно).

find-file-noselectХтось може пояснити, чому погана ідея читати файли в програмах Elisp? Чи є кращий спосіб? Я запитую, бо думав використовувати його в одному зі своїх проектів.


Здається, good-practicesраніше тегів не було ; чи корисно це використовувати?
mbork

Я думаю, що good-practicesце підпадало б під категорію "метатег", на яку нахмуриться SE.
nispio

1
@nispio Я думаю, що це дійсний тег, але ми, звичайно, можемо взяти це до мета.
Малабарба

1
@nsipio: Я проглянув цю статтю, і я не згоден. Але не я приймаю рішення. ;-)
mbork

Відповіді:


14

TL; DR : Якщо find-file-noselectви не маєте контролю над тим, що насправді відбувається, і ви можете закінчити довільні незначні режими, що включаються в буфер, залежно від того, що користувач включив у них init.el. Також очищення важке.

Використовуйте with-temp-bufferі insert-file-contentsзамість цього. Якщо вам потрібні конкретні основні або другорядні режими в буфері, ввімкніть їх явно . Щоб писати файли, використовуйте with-temp-fileнатомість, що, незважаючи на його ім'я, дозволяє записувати до довільних файлів.

Побічні ефекти

find-file-noselectмає безліч побічних ефектів, в тому числі

  • інтерактивно задаючи питання (що одне лише не входить в інтерактивне використання),
  • автоматично вмикаючи режим перегляду для файлів, що читаються тільки,
  • в іншому режимі,
  • і біг find-file-hook.

Сам звичайний режим

  • автоматично вибирає належний основний режим для поточного буфера,
  • запускає всі відповідні гачки головного та другорядного режиму,
  • і зчитує всі локальні змінні поточного буфера, тобто файлові змінні та змінні каталогів, які знову можуть задавати інтерактивні запитання щодо небезпечних локальних змінних.

Оскільки всі гачки запущені, ви отримуєте всі незначні режими та функції гака, увімкнені користувачем init.el, які можуть спричинити все, від незначних незручностей (якщо небажані незначні режими включені) до великих пошкоджень (якщо користувач додав функцію гака, яка розраховує на називатися з інтерактивного контексту).

Див. Https://github.com/flycheck/flycheck/isissue/366 для прикладу. Використання find-file-noselectспричиненого файлом даних було перевірено синтаксисом Flycheck, і оскільки це відбувалося під час вимкнення Emacs, не було часу знову правильно очистити, залишивши тимчасовий файл позаду.

Прибирати

З find-file-noselectвами потрібно бути особливо обережним, щоб знову вбити буфер. find-file-noselectце не робить для вас.

Вам потрібно запам’ятати буфер в якомусь місці та обережно використовувати, unwind-protectщоб переконатися, що буфер загине навіть у випадку немісцевих виходів.

Альтернативи

Щоб читати файли, використовуйте with-temp-bufferта insert-file-contents, що виконує лише найосновніші речі, наприклад, перетворення системи кодування, але не задає питань, не вмикайте гачки чи налаштовуйте локальні змінні:

(with-temp-buffer
  (insert-file-contents (locate-user-emacs-file "foo.el"))
  ;; Enter the major mode explicitly
  (emacs-lisp-mode)
  ;; …
  )

with-temp-buffer дбає про те, щоб належним чином вбити тимчасовий буфер в кінці його тіла.

Для запису файлів використовуйте with-temp-file, який створює тимчасовий буфер і записує вміст у вказане ім'я файлу в кінці його тіла:

(with-temp-file  (locate-user-emacs-file "foo.el")
  (prin1 (list 'my 'data) (current-buffer)))

10

З розділу 24.3 в посібнику Elisp:

Щоб скопіювати вміст файлу в буфер, використовуйте функцію insert-file-contents. (Не використовуйте команду insert-fileв програмі Lisp, оскільки вона встановлює позначку.)

З пошуку документації Elisp find-file-noselectочевидно, що це набагато більше, ніж просто читання файлу в буфер. Можливо, люди, які вважають, що використання цієї функції є поганою ідеєю, замислюються про, можливо, небажані побічні ефекти? Я думаю, це залежить від того, чого ти хочеш досягти. Якщо ви хочете мати максимально чистий / недоторканий вміст буфера, можливо, буде корисно використовувати стару та надійну комбінацію with-temp-buffer+ insert-file-contents. Якщо ви хочете , щоб вміст буфера , щоб бути як можна ближче до того , що find-fileвиробляти, можливо , ви дійсно хочете використовувати find-file-noselect? А може, він думав над тим find-file;)


3
Якщо щось робиться неінтерактивно, я не бачу жодного сценарію, у якому ви б хотіли, щоб "вміст буфера було близьким до того, який файл пошуку знайде" . find-file є повільним, оскільки він робить багато непотрібних речей, включаючи всілякі гачки. Єдина «особливість» пошуку-файлу, який, можливо, ви хочете, - це основний режим, але тоді вам слід просто активувати його самостійно (ви навіть не можете гарантувати, що файл пошуку знайде в будь-якому випадку потрібний вам режим).
Малабарба

Малабарба: Якщо ви плануєте, щоб буфер залишався доступним для редагування користувачем, ви, можливо, захочете імітувати find-fileпроцес.
філс
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.