Attached is a patch that implements LFUN_BUFFER_FORALL, which applies a passed LFUN command to all buffers. My motivation was that I sometimes need to do the same thing in all of the buffers that I have open. Another advantage of implementing this LFUN is that it allows buffer-specific settings to be made global. For example, if a user wants to be able to toggle track changes for all documents, he can do that (similarly for read only).
Here are some sample uses: Close all Notes in all documents: \n buffer-forall inset-forall Note inset-toggle close \n Toggle change tracking on all documents: \n buffer-forall changes-track \n Toggle read-only for all documents: \n buffer-forall buffer-toggle-read-only \n Show statistics for each document: \n buffer-forall statistics \n Activate the branch named "Solutions" in all documents: \n buffer-forall branch-activate Solutions \n I tested several potential special uses, such as nested calls, repeated calls, uses with other special commands like command-sequence, and uses with LFUNs that create and close buffers. The following all work fine: buffer-forall buffer-forall self-insert testing repeat 3 buffer-forall repeat 3 self-insert 1 buffer-forall buffer-close buffer-forall buffer-new buffer-forall inset-forall Note inset-toggle close When a buffer-forall command is issued and the command passed to it is disabled on one of the buffers, currently buffer-forall continues on to the other buffers and tries to execute the passed command. I think this is the correct behavior. Alternatively, buffer-forall could stop whenever it finds a buffer where the command is disabled. buffer-forall allows for an optional flag, includehidden. If includehidden is not specified, hidden buffers are ignored. If includehidden is specified, the action is applied to the hidden buffers and then they are hidden again. I might extend this option to allow for onlyhidden, which would not apply the command to non-hidden buffers. This would allow, e.g., to close all hidden buffers. Any comments? Thanks, Scott
diff --git a/src/FuncCode.h b/src/FuncCode.h index 9a7b06e..a066234 100644 --- a/src/FuncCode.h +++ b/src/FuncCode.h @@ -452,6 +452,7 @@ enum FuncCode // 350 LFUN_CLIPBOARD_PASTE_SIMPLE, // tommaso, 20111028 LFUN_IPA_INSERT, // spitz, 20120305 + LFUN_BUFFER_FORALL, // scottkostyshak, 20120715 LFUN_LASTACTION // end of the table }; diff --git a/src/LyXAction.cpp b/src/LyXAction.cpp index 39018ce..bed84c6 100644 --- a/src/LyXAction.cpp +++ b/src/LyXAction.cpp @@ -3127,6 +3139,27 @@ void LyXAction::init() */ { LFUN_BUFFER_WRITE_AS, "buffer-write-as", ReadOnly, Buffer }, /*! + * \var lyx::FuncCode lyx::LFUN_BUFFER_FORALL + * \li Action: Applies a command to all non-hidden buffers, optionally including hidden buffers. + * \li Syntax: buffer-forall [<INCLUDEHIDDEN>] <LFUN-COMMAND> + * \li Params: <LFUN-COMMAND>: The command that is to be applied to the buffers. + <INCLUDEHIDDEN>: 'includehidden' to iterate over hidden buffers. + Otherwise they are skipped + * \li Sample: Close all Notes in all non-hidden documents: \n + buffer-forall inset-forall Note inset-toggle close \n + Toggle change tracking on all documents: \n + buffer-forall includehidden changes-track \n + Toggle read-only for all non-hidden documents: \n + buffer-forall buffer-toggle-read-only \n + Show statistics for each document: \n + buffer-forall includehidden statistics \n + Activate the branch named "Solutions" in all non-hidden documents: \n + buffer-forall branch-activate Solutions \n + * \li Origin: scottkostyshak, 15 Jul 2012 + * \endvar + */ + { LFUN_BUFFER_FORALL, "buffer-forall", ReadOnly | Argument, Buffer }, +/*! * \var lyx::FuncCode lyx::LFUN_BUFFER_WRITE_ALL * \li Action: Save all changed documents. * \li Syntax: buffer-write-all diff --git a/src/frontends/qt4/GuiView.cpp b/src/frontends/qt4/GuiView.cpp index ca63632..bd06441 100644 --- a/src/frontends/qt4/GuiView.cpp +++ b/src/frontends/qt4/GuiView.cpp @@ -1679,6 +1683,7 @@ bool GuiView::getStatus(FuncRequest const & cmd, FuncStatus & flag) break; } + case LFUN_BUFFER_FORALL: case LFUN_BUFFER_WRITE_AS: case LFUN_BUFFER_EXPORT_AS: enable = doc_buffer; @@ -3332,6 +3337,54 @@ void GuiView::dispatch(FuncRequest const & cmd, DispatchResult & dr) gotoNextOrPreviousBuffer(PREVBUFFER); break; + case LFUN_BUFFER_FORALL: { + Buffer * const buf = ¤tBufferView()->buffer(); + if (!buf) + break; + + bool processHidden = false; + string commandToRun = argument; + if (argument.substr(0,13) == "includehidden") { + processHidden = true; + commandToRun = argument.substr(14, argument.size()); + } + + docstring const hiddenOrNot = processHidden ? _("all hidden and non-hidden") : _("all non-hidden"); + dr.setMessage(bformat(_("Applied the command \"%1$s\" to %2$s buffers"), from_utf8(commandToRun), hiddenOrNot)); + + Buffer * const last = theBufferList().last(); + Buffer * b = theBufferList().first(); + Buffer * nextBuf = 0; + // We cannot use a for loop as the buffer list cycles. + while (true) { + if (b != last) + nextBuf = theBufferList().next(b); //get next now bc LFUN might close current + + bool const hidden = !(guiApp->currentView() && guiApp->currentView()->workArea(*b)); + if (hidden) { + if (processHidden) { + setBuffer(b); + lyx::dispatch(FuncRequest(lyxaction.lookupFunc(commandToRun))); + GuiWorkArea * const wa = currentWorkArea(); + wa->view().hideWorkArea(wa); + } + } + + else { + setBuffer(b); + lyx::dispatch(FuncRequest(lyxaction.lookupFunc(commandToRun))); + } + + if (b == last) + break; + b = nextBuf; + } + + if (theBufferList().isLoaded(buf)) //the LFUN might have closed buf + setBuffer(buf); + break; + } + case LFUN_COMMAND_EXECUTE: { bool const show_it = cmd.argument() != "off"; // FIXME: this is a hack, "minibuffer" should not be