From debbugs-submit-bounces@debbugs.gnu.org Wed Jun 21 11:50:58 2023 Received: (at submit) by debbugs.gnu.org; 21 Jun 2023 15:50:58 +0000 Received: from localhost ([127.0.0.1]:34099 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1qC06j-0002Q9-D8 for submit@debbugs.gnu.org; Wed, 21 Jun 2023 11:50:58 -0400 Received: from lists.gnu.org ([209.51.188.17]:43280) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1qC06g-0002Q0-NF for submit@debbugs.gnu.org; Wed, 21 Jun 2023 11:50:55 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qC06d-0006wO-Nm for bug-gnu-emacs@gnu.org; Wed, 21 Jun 2023 11:50:52 -0400 Received: from mxout5.mail.janestreet.com ([64.215.233.18]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qC06b-0004H5-Qx for bug-gnu-emacs@gnu.org; Wed, 21 Jun 2023 11:50:51 -0400 From: Aaron Zeng To: bug-gnu-emacs@gnu.org Subject: Allow ff-other-file-alist to specify which file to create Date: Wed, 21 Jun 2023 11:50:46 -0400 Message-ID: MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Received-SPF: pass client-ip=64.215.233.18; envelope-from=azeng@janestreet.com; helo=mxout5.mail.janestreet.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-Spam-Score: -1.4 (-) X-Debbugs-Envelope-To: submit Cc: app-emacs-dev@janestreet.com X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -2.4 (--) --=-=-= Content-Type: text/plain Tags: patch Tags: patch This patch adds an optional third element to the lists that make ff-other-file-alist. If this third element is present, it is used as the extension for a new file, when none of the other options were found. Previously, this was forced to be the first extension in the list, which unnecessarily coupled search order and file-to-create. The specific use case I have in mind is for the following scenario in OCaml source files: it is common to have the following three files for a module "Foo": foo.ml, foo.mli, and foo_intf.ml. I would like to make ff-find-other-file cycle between these files if all of them exist, or to create a new file if they do not. However, it is also normal for only foo.ml and foo.mli to exist, and foo_intf.ml should not be created if it is not necessary. At the moment, if the user is looking at foo.mli, there is no way to program ff-other-file-alist to say, "go to foo_intf.ml if it exists, otherwise foo.ml, but if neither exist, create foo.ml". This patch makes it possible to specify what file to create, if it is not the first file searched for. The manual has not yet been updated for this change, since I wanted to get some feedback on the patch itself first. Happy to make the changes in the appropriate places if the patch looks reasonable. In GNU Emacs 28.2 (build 1, x86_64-pc-linux-gnu, X toolkit, cairo version 1.15.12, Xaw scroll bars) of 2023-02-09 built on igm-qws-u12685a Repository revision: 739b5d0e52d83ec567bd61a5a49ac0e93e0eb469 Repository branch: HEAD Windowing system distributor 'The X.Org Foundation', version 11.0.12011000 System Description: CentOS Linux 7 (Core) Configured using: 'configure --with-x-toolkit=lucid --without-gpm --without-gconf --without-selinux --without-imagemagick --with-modules --with-gif=no --with-cairo --with-rsvg --prefix=/j/office/app/emacs/builds/28.2-20230209-135825' --=-=-= Content-Type: text/patch Content-Disposition: attachment; filename=0001-Allow-ff-other-file-alist-functions-to-be-lambdas.patch >From 6aba92d369183035cd86cc56bea5104dfc1816d4 Mon Sep 17 00:00:00 2001 From: "Aaron L. Zeng" Date: Mon, 12 Jun 2023 18:43:38 -0400 Subject: [PATCH 1/2] Allow ff-other-file-alist functions to be lambdas * lisp/find-file.el (ff-other-file-alist, ff-find-the-other-file): allow functions in the alist to be lambdas, by just checking `functionp'. Also make a minor docstring correction to `ff-other-file-alist'. --- lisp/find-file.el | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lisp/find-file.el b/lisp/find-file.el index 05459c3643d..e4c86ecdfee 100644 --- a/lisp/find-file.el +++ b/lisp/find-file.el @@ -215,10 +215,10 @@ matching extension or name (e.g., `.cc' yields `.hh'). This alist should be set by the major mode. -Note: if an element of the alist names a FUNCTION as its cdr, that -function must return a non-nil list of file-names. It cannot -return nil, nor can it signal in any way a failure to find a suitable -list of file names." +Note: if an element of the alist names a FUNCTION as its cadr, +that function must return a non-nil list of file-names. It +cannot return nil, nor can it signal in any way a failure to find +a suitable list of file names." :type '(choice (repeat (list regexp (choice (repeat string) function))) symbol)) @@ -469,7 +469,7 @@ If optional IN-OTHER-WINDOW is non-nil, find the file in another window." ;; if we have a function to generate new names, ;; invoke it with the name of the current file - (if (and (atom action) (fboundp action)) + (if (functionp action) (setq suffixes (funcall action (ff-buffer-file-name)) match (cons (car match) (list suffixes)) stub nil -- 2.39.3 --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0002-Allow-ff-other-file-alist-to-specify-the-extension-f.patch >From 13d1881e03ea838c5448da6b57678c7ba4c48704 Mon Sep 17 00:00:00 2001 From: "Aaron L. Zeng" Date: Tue, 13 Jun 2023 17:07:40 -0400 Subject: [PATCH 2/2] Allow ff-other-file-alist to specify the extension for a new file * lisp/find-file.el (ff-other-file-alist, ff-find-the-other-file): Add an optional third element to the lists that make ff-other-file-alist. If this third element is present, it is used as the extension for a new file, when none of the other options were found. Previously, this was forced to be the first extension in the list, which unnecessarily coupled search order and file-to-create. --- lisp/find-file.el | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/lisp/find-file.el b/lisp/find-file.el index e4c86ecdfee..807f46e637c 100644 --- a/lisp/find-file.el +++ b/lisp/find-file.el @@ -192,7 +192,7 @@ filename that EXTRACT returned." The value could be an alist or a symbol whose value is an alist. Each element of the alist has the form - (REGEXP (EXTENSION...)) + (REGEXP (EXTENSION...) [CREATE-EXTENSION]) where REGEXP is the regular expression matching a file's extension, and EXTENSIONs is the list of literal file-name extensions to search @@ -202,7 +202,7 @@ through each directory specified in `ff-search-directories'. Alist elements can also be of the form - (REGEXP FUNCTION) + (REGEXP FUNCTION [CREATE-EXTENSION]) where FUNCTION is a function of one argument, the current file's name, that returns the list of possible names of the corresponding files, with @@ -210,8 +210,11 @@ or without leading directories. Note the difference: FUNCTION returns the list of file names, not their extensions. This is for the case when REGEXP is not enough to determine the file name of the other file. -If a file is not found, a new one is created with the first -matching extension or name (e.g., `.cc' yields `.hh'). +If a file is not found, a new one is created with the first matching +extension or name (e.g., `.cc' yields `.hh'). If [CREATE-EXTENSION] +is present, it is used instead of the first extension. If +[CREATE-EXTENSION] is a function, it is called with a single argument, +the current file's name, and the name it returns is used instead. This alist should be set by the major mode. @@ -219,7 +222,13 @@ Note: if an element of the alist names a FUNCTION as its cadr, that function must return a non-nil list of file-names. It cannot return nil, nor can it signal in any way a failure to find a suitable list of file names." - :type '(choice (repeat (list regexp (choice (repeat string) function))) + :type '(choice (repeat (list regexp + (choice :tag "Extensions to try" + (repeat string) + function) + (choice :tag "Extension to create" + (list :inline t :tag "string" string) + (list :inline t :tag "function" function)))) symbol)) (defcustom ff-search-directories 'cc-search-directories @@ -465,7 +474,11 @@ If optional IN-OTHER-WINDOW is non-nil, find the file in another window." ;; otherwise, suffixes contains what we need (setq suffixes (car (cdr match)) action (car (cdr match)) - found nil) + found nil + default-name (caddr match)) + + (when (functionp default-name) + (setq default-name (funcall default-name (ff-buffer-file-name)))) ;; if we have a function to generate new names, ;; invoke it with the name of the current file @@ -473,7 +486,7 @@ If optional IN-OTHER-WINDOW is non-nil, find the file in another window." (setq suffixes (funcall action (ff-buffer-file-name)) match (cons (car match) (list suffixes)) stub nil - default-name (car suffixes)) + default-name (or default-name (car suffixes))) ;; otherwise build our filename stub (cond @@ -493,7 +506,7 @@ If optional IN-OTHER-WINDOW is non-nil, find the file in another window." ;; if we find nothing, we should try to get a file like this one (setq default-name - (concat stub (car (car (cdr match)))))) + (concat stub (or default-name (car (car (cdr match))))))) ;; do the real work - find the file (setq found -- 2.39.3 --=-=-=-- From debbugs-submit-bounces@debbugs.gnu.org Sun Sep 03 07:49:33 2023 Received: (at control) by debbugs.gnu.org; 3 Sep 2023 11:49:33 +0000 Received: from localhost ([127.0.0.1]:39865 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1qclbh-0004lO-Hp for submit@debbugs.gnu.org; Sun, 03 Sep 2023 07:49:33 -0400 Received: from mail-lj1-x22a.google.com ([2a00:1450:4864:20::22a]:62946) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1qclbf-0004l8-Et for control@debbugs.gnu.org; Sun, 03 Sep 2023 07:49:31 -0400 Received: by mail-lj1-x22a.google.com with SMTP id 38308e7fff4ca-2bcda0aaf47so16816981fa.1 for ; Sun, 03 Sep 2023 04:49:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1693741755; x=1694346555; darn=debbugs.gnu.org; h=to:subject:message-id:date:mime-version:from:from:to:cc:subject :date:message-id:reply-to; bh=VRoDw49VbXblfOKoTElPtLKXC9aFF0luXrvGFAGU+fQ=; b=iD9PDGgnbdFmD4+bjkErLAyi90gJKPQAf/h9MyG0t0HCEqhJ3LZpxUy91SRRMTCKF2 376/ZwpolvDWoryusJUnQBE/U70uMtHGoIpsDfGDxrS2t3OvfWFtB1gWNSs/ru2FIrTS 4FAbofgcK1Je1LQRD9ivD55ImI7cuDpwy5hwWTN0NIJ6PWkqjQCzgJbpaNao42fJ9ESO kCw278Kpq0LmqJIFVBmFeA7I90Uvh0OTgwd5QlxpLpkC8Uwr2fARu4T7w7jJwTbVNUii bwxkd5GdrcPnL5QAdgqErjtOxoJ6hKS3O3wD0/MjEnmqwI656VeJMvFh9/9xbgf1u2Ey ZelA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1693741755; x=1694346555; h=to:subject:message-id:date:mime-version:from:x-gm-message-state :from:to:cc:subject:date:message-id:reply-to; bh=VRoDw49VbXblfOKoTElPtLKXC9aFF0luXrvGFAGU+fQ=; b=g/X2i+GAl0JM47p9jzZmCbkQCetSk3mV3aB/KIWf24oIRUB40ynyeQbJn0CLizMsxv s+JnHgSXQA0AClZKZw+aBVtudnC5fTQReP8xrpE/Smk+OQn/hE8F6sMxP4eM+DkGRQcK SmQYH/3QAoIZ/PRmJG6TpzfdDs117eYSXPAekeGtBJ0cfjD7WHzcMf8L9iiDJuMwL/T4 yZ6oWwUWAS2TXkbq64qKXnby+HP2ofyO6iJ8Rl/J41nSxqSmfHTPxzK2fjst2f+QLNrW 23OtK+Hoc70PNOsP9lh8pJ0wHml88ljRKHkj/OuBLjWjMxI/Zbh1ikZnvKMyWXlP916k OyWg== X-Gm-Message-State: AOJu0YwY3r9t2v2HstkGseWWmkZO9ubPucNwkEFPDNTlJQX07AhvAwL/ jBosHV/JgAz8FqirEZJ2cYslBbPfR1kE4InTaUFTaSczvwg= X-Google-Smtp-Source: AGHT+IH1G1Ty6+ZULRTQ3q71fn0dsrOIODhlbAolOhCZev+iA1nYdba01Kuq/udSoMRcqlXvx4Ya1OVzpqCqeOYTJU4= X-Received: by 2002:a05:6512:31c6:b0:4f9:dac6:2f3d with SMTP id j6-20020a05651231c600b004f9dac62f3dmr2742465lfe.13.1693741754960; Sun, 03 Sep 2023 04:49:14 -0700 (PDT) Received: from 753933720722 named unknown by gmailapi.google.com with HTTPREST; Sun, 3 Sep 2023 04:49:14 -0700 From: Stefan Kangas MIME-Version: 1.0 Date: Sun, 3 Sep 2023 04:49:14 -0700 Message-ID: Subject: control message for bug #64210 To: control@debbugs.gnu.org Content-Type: text/plain; charset="UTF-8" X-Spam-Score: 0.0 (/) X-Debbugs-Envelope-To: control X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) severity 64210 wishlist quit From debbugs-submit-bounces@debbugs.gnu.org Wed Sep 06 06:53:42 2023 Received: (at 64210) by debbugs.gnu.org; 6 Sep 2023 10:53:42 +0000 Received: from localhost ([127.0.0.1]:33068 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1qdqAH-0003MA-UP for submit@debbugs.gnu.org; Wed, 06 Sep 2023 06:53:42 -0400 Received: from mail-lj1-x232.google.com ([2a00:1450:4864:20::232]:50631) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1qdqAD-0003Lp-Gl for 64210@debbugs.gnu.org; Wed, 06 Sep 2023 06:53:40 -0400 Received: by mail-lj1-x232.google.com with SMTP id 38308e7fff4ca-2bcbfb3705dso55255601fa.1 for <64210@debbugs.gnu.org>; Wed, 06 Sep 2023 03:53:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1693997610; x=1694602410; darn=debbugs.gnu.org; h=cc:to:subject:message-id:date:mime-version:references:in-reply-to :from:from:to:cc:subject:date:message-id:reply-to; bh=jXttWCdhP90z0NxBJKupLGi3/MVd9lbounWmad8Q5IU=; b=SBIsy0xHzTKiD+Y6xrxpOetlkAT+JtzfpYfPBKO+YUTdbq88K3SmckXSDHEi4tT0mX 1+nTBr5OSjn3qjR7x53U5HyfgZ65GF+6fVgSY9Vfmb5dBYRQzAqUY0YcHtvCOwsLy/TI LbqdDn/PQrieVBJEA//+3w29TDoWj6lqZKFbamQv7k0wYlztBwX45IcgeHSrt44F38Xs jrB5EwatTpTq9TTN6g6yPiqcoMZWesGgyiw9cF0Gr9/Cceq1jo55EO9ZKq0OHz8tia+V 15LZCg8oh/cJ4Nf8o3pPvchOM2IkDqJVj150jN34Es4TMxSYK+txkaC5EbqMWOyxMMNk 6+xQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1693997610; x=1694602410; h=cc:to:subject:message-id:date:mime-version:references:in-reply-to :from:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=jXttWCdhP90z0NxBJKupLGi3/MVd9lbounWmad8Q5IU=; b=jfNcbn0kTGu7/xYLhjekTAAQ/Kct1m17/GlTkvCeFwRRfXLjWeHyFIH3spX+usiIQ9 K39yb2G9dSWsk7eYq4ND/5wdxqtOb7MO1DA8oT+o8rngtI/9/3eHwHhbeSIy9dUPS3TV yAshisJLGm2Mt0mPKJXnIXzKLFLaNcGegA841rFPEgIUPN8lPAA07pSxPtXLc9TmaTZn u3gxkzdIVeLp46LV6WBZE73cYdTL5WVWEavgd3Wve2ftni4cI8POZJniCmbWVjf9qy2v QYe0yiYbFJ4KMV6Z56Te1aK2kM8Ofm+IvTNiMWy3LokC/vPDkrr/pqpRZi0tk4tZ0QCn W1fw== X-Gm-Message-State: AOJu0Yz5Sua3Y82rjgKIpu21c6dei0c99Qoz3PyTVKG84+G2nGlOHdJ6 MSIiyjWCTpoL7k2Ha4vu3MtF1N0BbW+lo4pgToU= X-Google-Smtp-Source: AGHT+IFtClOZ4pnMSYlx1XJqVjJYy+Z26a2CcNnh++e4eaAyasQOHMNX0fNt6WtwP1SPsgEhW06nXokF/wODmUVZVds= X-Received: by 2002:a19:8c4c:0:b0:500:771f:4887 with SMTP id i12-20020a198c4c000000b00500771f4887mr1740463lfj.55.1693997609682; Wed, 06 Sep 2023 03:53:29 -0700 (PDT) Received: from 753933720722 named unknown by gmailapi.google.com with HTTPREST; Wed, 6 Sep 2023 03:53:29 -0700 From: Stefan Kangas In-Reply-To: (Aaron Zeng's message of "Wed, 21 Jun 2023 11:50:46 -0400") References: MIME-Version: 1.0 Date: Wed, 6 Sep 2023 03:53:29 -0700 Message-ID: Subject: Re: bug#64210: Allow ff-other-file-alist to specify which file to create To: Aaron Zeng Content-Type: text/plain; charset="UTF-8" X-Spam-Score: 0.0 (/) X-Debbugs-Envelope-To: 64210 Cc: app-emacs-dev@janestreet.com, 64210@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) Aaron Zeng writes: > This patch adds an optional third element to the lists that make > ff-other-file-alist. If this third element is present, it is used as > the extension for a new file, when none of the other options were > found. Previously, this was forced to be the first extension in the > list, which unnecessarily coupled search order and file-to-create. > > The specific use case I have in mind is for the following scenario in > OCaml source files: it is common to have the following three files for > a module "Foo": foo.ml, foo.mli, and foo_intf.ml. I would like to > make ff-find-other-file cycle between these files if all of them > exist, or to create a new file if they do not. However, it is also > normal for only foo.ml and foo.mli to exist, and foo_intf.ml should > not be created if it is not necessary. > > At the moment, if the user is looking at foo.mli, there is no way to > program ff-other-file-alist to say, "go to foo_intf.ml if it exists, > otherwise foo.ml, but if neither exist, create foo.ml". This patch > makes it possible to specify what file to create, if it is not the > first file searched for. Makes sense to me. Please find my review below, which is basically only about minor, stylistic things. > The manual has not yet been updated for this change, since I wanted to > get some feedback on the patch itself first. Happy to make the > changes in the appropriate places if the patch looks reasonable. Yes, the manual needs updating, and this should be called out in NEWS, too. >>>From 6aba92d369183035cd86cc56bea5104dfc1816d4 Mon Sep 17 00:00:00 2001 > From: "Aaron L. Zeng" > Date: Mon, 12 Jun 2023 18:43:38 -0400 > Subject: [PATCH 1/2] Allow ff-other-file-alist functions to be lambdas > > * lisp/find-file.el (ff-other-file-alist, ff-find-the-other-file): > allow functions in the alist to be lambdas, by just checking > `functionp'. Also make a minor docstring correction to > `ff-other-file-alist'. Please include the bug number here. (Bug#NNNNN) > --- > lisp/find-file.el | 10 +++++----- > 1 file changed, 5 insertions(+), 5 deletions(-) > > diff --git a/lisp/find-file.el b/lisp/find-file.el > index 05459c3643d..e4c86ecdfee 100644 > --- a/lisp/find-file.el > +++ b/lisp/find-file.el > @@ -215,10 +215,10 @@ matching extension or name (e.g., `.cc' yields `.hh'). > > This alist should be set by the major mode. > > -Note: if an element of the alist names a FUNCTION as its cdr, that > -function must return a non-nil list of file-names. It cannot > -return nil, nor can it signal in any way a failure to find a suitable > -list of file names." > +Note: if an element of the alist names a FUNCTION as its cadr, > +that function must return a non-nil list of file-names. It > +cannot return nil, nor can it signal in any way a failure to find > +a suitable list of file names." > :type '(choice (repeat (list regexp (choice (repeat string) function))) > symbol)) > > @@ -469,7 +469,7 @@ If optional IN-OTHER-WINDOW is non-nil, find the file in another window." > > ;; if we have a function to generate new names, > ;; invoke it with the name of the current file > - (if (and (atom action) (fboundp action)) > + (if (functionp action) > (setq suffixes (funcall action (ff-buffer-file-name)) > match (cons (car match) (list suffixes)) > stub nil > -- > 2.39.3 > > >>>From 13d1881e03ea838c5448da6b57678c7ba4c48704 Mon Sep 17 00:00:00 2001 > From: "Aaron L. Zeng" > Date: Tue, 13 Jun 2023 17:07:40 -0400 > Subject: [PATCH 2/2] Allow ff-other-file-alist to specify the extension for a > new file > > * lisp/find-file.el (ff-other-file-alist, ff-find-the-other-file): Add > an optional third element to the lists that make ff-other-file-alist. > If this third element is present, it is used as the extension for a > new file, when none of the other options were found. Previously, this > was forced to be the first extension in the list, which unnecessarily > coupled search order and file-to-create. Please include the bug number here. > --- > lisp/find-file.el | 29 +++++++++++++++++++++-------- > 1 file changed, 21 insertions(+), 8 deletions(-) > > diff --git a/lisp/find-file.el b/lisp/find-file.el > index e4c86ecdfee..807f46e637c 100644 > --- a/lisp/find-file.el > +++ b/lisp/find-file.el > @@ -192,7 +192,7 @@ filename that EXTRACT returned." > The value could be an alist or a symbol whose value is an alist. > Each element of the alist has the form > > - (REGEXP (EXTENSION...)) > + (REGEXP (EXTENSION...) [CREATE-EXTENSION]) > > where REGEXP is the regular expression matching a file's extension, > and EXTENSIONs is the list of literal file-name extensions to search > @@ -202,7 +202,7 @@ through each directory specified in `ff-search-directories'. > > Alist elements can also be of the form > > - (REGEXP FUNCTION) > + (REGEXP FUNCTION [CREATE-EXTENSION]) > > where FUNCTION is a function of one argument, the current file's name, > that returns the list of possible names of the corresponding files, with > @@ -210,8 +210,11 @@ or without leading directories. Note the difference: FUNCTION returns > the list of file names, not their extensions. This is for the case when > REGEXP is not enough to determine the file name of the other file. > > -If a file is not found, a new one is created with the first > -matching extension or name (e.g., `.cc' yields `.hh'). > +If a file is not found, a new one is created with the first matching > +extension or name (e.g., `.cc' yields `.hh'). If [CREATE-EXTENSION] > +is present, it is used instead of the first extension. If This should read: If CREATE-EXTENSION is non-nil, ... > +[CREATE-EXTENSION] is a function, it is called with a single argument, > +the current file's name, and the name it returns is used instead. CREATE-EXTENSION should not have brackets here. See for example `font-lock-defaults' for how we do this. > This alist should be set by the major mode. > > @@ -219,7 +222,13 @@ Note: if an element of the alist names a FUNCTION as its cadr, > that function must return a non-nil list of file-names. It > cannot return nil, nor can it signal in any way a failure to find > a suitable list of file names." > - :type '(choice (repeat (list regexp (choice (repeat string) function))) > + :type '(choice (repeat (list regexp > + (choice :tag "Extensions to try" > + (repeat string) > + function) > + (choice :tag "Extension to create" > + (list :inline t :tag "string" string) > + (list :inline t :tag "function" function)))) > symbol)) > > (defcustom ff-search-directories 'cc-search-directories > @@ -465,7 +474,11 @@ If optional IN-OTHER-WINDOW is non-nil, find the file in another window." > ;; otherwise, suffixes contains what we need > (setq suffixes (car (cdr match)) > action (car (cdr match)) > - found nil) > + found nil > + default-name (caddr match)) > + > + (when (functionp default-name) > + (setq default-name (funcall default-name (ff-buffer-file-name)))) > > ;; if we have a function to generate new names, > ;; invoke it with the name of the current file > @@ -473,7 +486,7 @@ If optional IN-OTHER-WINDOW is non-nil, find the file in another window." > (setq suffixes (funcall action (ff-buffer-file-name)) > match (cons (car match) (list suffixes)) > stub nil > - default-name (car suffixes)) > + default-name (or default-name (car suffixes))) > > ;; otherwise build our filename stub > (cond > @@ -493,7 +506,7 @@ If optional IN-OTHER-WINDOW is non-nil, find the file in another window." > > ;; if we find nothing, we should try to get a file like this one > (setq default-name > - (concat stub (car (car (cdr match)))))) > + (concat stub (or default-name (car (car (cdr match))))))) > > ;; do the real work - find the file > (setq found Not sure how hard it would be to add tests for this, so I'll leave that up to you.