5

I started to use Dired. The movie files will be opened by another external application (VLC) with the help of the package openwith.

So I would like to supress the confirmation File foobar.avi is too large, really open? (y or n) for movie files.

When exploring this feature, I found the variable large-file-warning-thresold, the docstring is:

The variable is large-file-warning-threshold. Documentation:

large-file-warning-threshold is a variable defined in `files.el'.
Its value is 10000000

Documentation:
Maximum size of file above which a confirmation is requested.
When nil, never request confirmation.

You can customize this variable.

This variable was introduced, or its default value was changed, in
version 22.1 of Emacs.

So I would like to disable this thresold for only specific extensions like .mp4 or .mkv, but don't change it for another extensions.

By reading the source, look at the function to open files: C-h k C-x C-f (or C-h f find-file RET). Click on files.el to browse the source file (you must have the Lisp sources installed). Don't read the code — it's pretty big — but search for parts of the message in that file. You'll find

(defun abort-if-file-too-large (size op-type filename)
  "If file SIZE larger than `large-file-warning-threshold', allow user to abort.
OP-TYPE specifies the file operation being performed (for message to user)."
  (when (and large-file-warning-threshold size
             (> size large-file-warning-threshold)
             (not (y-or-n-p
                   (format "File %s is large (%dMB), really %s? "
                           (file-name-nondirectory filename)
                           (/ size 1048576) op-type))))
    (error "Aborted")))

The message is only displayed when some conditions are met. The first condition is large-file-warning-threshold (interpreted as a boolean), i.e. large-file-warning-threshold must be non-nil. So you can disable the message by setting that variable to nil. (You can confirm that it's a global variable by looking at its definition in the same file — it's a customizable item, and the documentation explains how it's used if you aren't familiar enough with Lisp and only figured out that the variable mattered in some way.)

So I would add the condition for .mp4 and .mkv4 files.

Any idea how I could achieve that, without fiddling with the source code for Dired? I could use defadvice, but it's currently unclear to me how I could apply extra conditional for confirmation messages.

Arch Stanton
  • 1,525
  • 9
  • 22
ReneFroger
  • 3,855
  • 22
  • 63

3 Answers3

7

You're on the right track. This should do the trick:

(defvar my-ok-large-file-types
  (rx "." (or "mp4" "mkv") string-end)
  "Regexp matching filenames which are definitely ok to visit,
even when the file is larger than `large-file-warning-threshold'.")

(defadvice abort-if-file-too-large (around my-check-ok-large-file-types)
  "If FILENAME matches `my-ok-large-file-types', do not abort."
  (unless (string-match-p my-ok-large-file-types (ad-get-arg 2))
    ad-do-it))
(ad-activate 'abort-if-file-too-large)
phils
  • 48,657
  • 3
  • 76
  • 115
  • it works like a charm, thanks for that! However, I had some difficulty to understand how you figured it out. Maybe you could explain in which ways your snippet works? Thanks in advance. – ReneFroger Oct 03 '15 at 13:15
  • 1
    Sure. `abort-if-file-too-large` raises an error if its conditions are met, and does nothing at all otherwise. As such, all we need to do here is to wrap our own condition around the function, such that the original definition *isn't executed at all* if we're happy with the filename. In `around` advice, `ad-do-it` is a token which calls the original function; so here that only happens if the filename (which is argument 2 of the original function) isn't a match for our regexp. – phils Oct 03 '15 at 14:06
  • Thanks for your clear explaination, I struggled about the ad-thingy. I'm impressed with your solution after all... how long do you work with Emacs/Elisp, by the way? – ReneFroger Oct 03 '15 at 14:35
  • That would be "Longer than I like to think about" / "A sadly small proportion of the first number". I started answering S.O. questions about 5.5 years ago, and that was probably within a year of taking a proper interest in elisp. – phils Oct 03 '15 at 14:59
  • 1
    If you can find an Emacs version prior to Emacs 24.4, then you can consult the doc about `defadvice`, starting with node **Defining Advice** of the Elisp manual. Unfortunately, this doc was (unwisely, IMHO) removed with 24.4 and later. (Maybe you can find an older manual on line.) – Drew Oct 03 '15 at 16:11
  • @Drew thanks for the advice. Any chance to know why that doc was removed with 24.4? – ReneFroger Oct 03 '15 at 16:12
  • 1
    You can find some of the old doc in the Commentary of library `advice.el`. Thank goodness for that. As for who removed it from the Elisp manual, and why, see [bug 16491](http://debbugs.gnu.org/cgi/bugreport.cgi?bug=16491). The new advice system has some features that the old does not, and vice versa. But the old was simply tossed, and its doc along with it. – Drew Oct 03 '15 at 16:22
  • Please see this post which helped me with this: https://emacs.stackexchange.com/questions/54796/instruct-emacs-never-to-open-files-of-a-certain-type-or-size/54807#54807 – Edman Jan 19 '21 at 16:34
1

This is an elaboration of phils' answer that sets my-ok-large-file-types automatically using the value of openwith-associations:

(define-advice abort-if-file-too-large
    (:around (orig-fn size op-type filename &optional offer-raw) unless-openwith-handles-it)
  "Do not abort if FILENAME is handled by Openwith."
  (let ((my-ok-large-file-types (mapconcat 'car openwith-associations "\\|")))
    (unless (string-match-p my-ok-large-file-types filename)
      (funcall orig-fn size op-type filename offer-raw))))

The setting of my-ok-large-file-types works like this: my-ok-large-file-types is a list of lists with a structure like ((<regexp> <application> <file>) (<regexp> <application> <file>) …). You can make a big regexp that matches any file handled by Openwith by combining all the <regexp> elements using or operators. In code, that's (mapconcat 'car openwith-associations "\\|"): car returns the first element of a list, mapconcat applies car to all elements of openwith-associations and concatenates the results separating them with \\|, the or operator (see (elisp)Mapping Functions).

Another difference is that this advice is written using nadvice.el, which is the newer advice library. I don't know much about its technical advantages, for those I refer you to Practical benefits of new advice system in Emacs 24.4. Here, notice that all the arguments of abort-if-file-too-large are declared in the lambda list. That's what allows calling the original function's argument filename by name in (string-match-p my-ok-large-file-types filename), instead of having to use ad-get-arg as with the old advice.el library. Advices with the :around combinator additionally take the advised function's name as an argument. When you call the original function in your advice, you do it by invoking funcall or apply with that argument, in place of ad-do-it.

Arch Stanton
  • 1,525
  • 9
  • 22
0

To suppress the question altogether, I followed your thought pattern above with this line:

(setq large-file-warning-threshold nil)