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 = &currentBufferView()->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

Reply via email to