aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--lib/session.tes3
-rw-r--r--src/ioview.cpp2
-rw-r--r--src/main.cpp3
-rw-r--r--src/parser.cpp1
-rw-r--r--src/qregisters.cpp75
-rw-r--r--src/qregisters.h27
-rw-r--r--src/ring.cpp12
7 files changed, 96 insertions, 27 deletions
diff --git a/lib/session.tes b/lib/session.tes
index 63e4cfc..3dfb05f 100644
--- a/lib/session.tes
+++ b/lib/session.tes
@@ -16,8 +16,7 @@ EU[session.path]Q[$HOME]/.teco_session
Q.u"F :@EU.[session]{EB -EF^M} '
:@EU.[session]{\.[curbuf]EB^M}
- EBQ[session.path]
- HK G.[session] EW EF
+ E%.[session]Q[session.path]
Q.[curbuf]EB
}
diff --git a/src/ioview.cpp b/src/ioview.cpp
index c9d147c..b0a2d40 100644
--- a/src/ioview.cpp
+++ b/src/ioview.cpp
@@ -254,7 +254,7 @@ IOView::save(const gchar *filename)
file = g_fopen(filename, "w");
if (!file)
/* hopefully, errno is also always set on Windows */
- throw Error("Error opening file \"%s\": %s",
+ throw Error("Error opening file \"%s\" for writing: %s",
filename, strerror(errno));
/* write part of buffer before gap */
diff --git a/src/main.cpp b/src/main.cpp
index e7cf62b..463cdfd 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -32,6 +32,7 @@
#include "sciteco.h"
#include "cmdline.h"
#include "interface.h"
+#include "ioview.h"
#include "parser.h"
#include "goto.h"
#include "qregisters.h"
@@ -53,7 +54,7 @@ namespace SciTECO {
* GCC init_priority() attribute
*/
InterfaceCurrent interface;
-ViewCurrent QRegisters::view;
+IOView QRegisters::view;
/*
* Scintilla will be initialized after these
diff --git a/src/parser.cpp b/src/parser.cpp
index 4b8caef..8c9e209 100644
--- a/src/parser.cpp
+++ b/src/parser.cpp
@@ -1802,6 +1802,7 @@ StateASCII::custom(gchar chr)
StateECommand::StateECommand() : State()
{
transitions['\0'] = this;
+ transitions['%'] = &States::epctcommand;
transitions['B'] = &States::editfile;
transitions['C'] = &States::executecommand;
transitions['G'] = &States::egcommand;
diff --git a/src/qregisters.cpp b/src/qregisters.cpp
index d59686b..940ce23 100644
--- a/src/qregisters.cpp
+++ b/src/qregisters.cpp
@@ -45,6 +45,8 @@ namespace States {
StatePopQReg popqreg;
StateEQCommand eqcommand;
StateLoadQReg loadqreg;
+ StateEPctCommand epctcommand;
+ StateSaveQReg saveqreg;
StateCtlUCommand ctlucommand;
StateEUCommand eucommand;
StateSetQRegString setqregstring_nobuilding(false);
@@ -207,24 +209,41 @@ QRegister::execute(bool locals)
void
QRegister::load(const gchar *filename)
{
- gchar *contents;
- gsize size;
+ undo_set_string();
- GError *gerror = NULL;
-
- /* FIXME: prevent excessive allocations by reading file into buffer */
- if (!g_file_get_contents(filename, &contents, &size, &gerror))
- throw GlibError(gerror);
+ if (QRegisters::current)
+ QRegisters::current->string.update(QRegisters::view);
string.edit(QRegisters::view);
string.reset();
- QRegisters::view.ssm(SCI_BEGINUNDOACTION);
- QRegisters::view.ssm(SCI_CLEARALL);
- QRegisters::view.ssm(SCI_APPENDTEXT, size, (sptr_t)contents);
- QRegisters::view.ssm(SCI_ENDUNDOACTION);
+ /*
+ * undo_set_string() pushes undo tokens that restore
+ * the previous document in the view.
+ * So if loading fails, QRegisters::current will be
+ * made the current document again.
+ */
+ QRegisters::view.load(filename);
- g_free(contents);
+ if (QRegisters::current)
+ QRegisters::current->string.edit(QRegisters::view);
+}
+
+void
+QRegister::save(const gchar *filename)
+{
+ if (QRegisters::current)
+ QRegisters::current->string.update(QRegisters::view);
+
+ string.edit(QRegisters::view);
+
+ try {
+ QRegisters::view.save(filename);
+ } catch (...) {
+ if (QRegisters::current)
+ QRegisters::current->string.edit(QRegisters::view);
+ throw; /* forward */
+ }
if (QRegisters::current)
QRegisters::current->string.edit(QRegisters::view);
@@ -600,7 +619,6 @@ StateLoadQReg::done(const gchar *str)
if (*str) {
/* Load file into Q-Register */
- register_argument->undo_load();
register_argument->load(str);
} else {
/* Edit Q-Register */
@@ -612,6 +630,37 @@ StateLoadQReg::done(const gchar *str)
}
/*$
+ * E%q<file>$ -- Save Q-Register string to file
+ *
+ * Saves the string contents of Q-Register <q> to
+ * <file>.
+ * The <file> must always be specified, as Q-Registers
+ * have no notion of associated file names.
+ *
+ * In interactive mode, the E% command may be rubbed out,
+ * restoring the previous state of <file>.
+ * This follows the same rules as with the \fBEW\fP command.
+ *
+ * File names may also be tab-completed and string building
+ * characters are enabled by default.
+ */
+State *
+StateEPctCommand::got_register(QRegister &reg)
+{
+ BEGIN_EXEC(&States::saveqreg);
+ register_argument = &reg;
+ return &States::saveqreg;
+}
+
+State *
+StateSaveQReg::done(const gchar *str)
+{
+ BEGIN_EXEC(&States::start);
+ register_argument->save(str);
+ return &States::start;
+}
+
+/*$
* [c1,c2,...]^Uq[string]$ -- Set or append to Q-Register string without string building
* [c1,c2,...]:^Uq[string]$
*
diff --git a/src/qregisters.h b/src/qregisters.h
index 80222f8..9dd3989 100644
--- a/src/qregisters.h
+++ b/src/qregisters.h
@@ -27,6 +27,7 @@
#include "sciteco.h"
#include "interface.h"
+#include "ioview.h"
#include "undo.h"
#include "rbtree.h"
#include "parser.h"
@@ -35,8 +36,8 @@
namespace SciTECO {
namespace QRegisters {
- /* initialized after Interface.main() in main() */
- extern ViewCurrent view;
+ /* initialized after Interface::main() in main() */
+ extern IOView view;
}
/*
@@ -134,12 +135,12 @@ public:
void execute(bool locals = true);
+ /*
+ * Load and save already care about undo token
+ * creation.
+ */
void load(const gchar *filename);
- inline void
- undo_load(void)
- {
- undo_set_string();
- }
+ void save(const gchar *filename);
};
class QRegisterBufferInfo : public QRegister {
@@ -356,6 +357,16 @@ private:
State *done(const gchar *str);
};
+class StateEPctCommand : public StateExpectQReg {
+private:
+ State *got_register(QRegister &reg);
+};
+
+class StateSaveQReg : public StateExpectFile {
+private:
+ State *done(const gchar *str);
+};
+
class StateCtlUCommand : public StateExpectQReg {
public:
StateCtlUCommand() : StateExpectQReg(true) {}
@@ -433,6 +444,8 @@ namespace States {
extern StatePopQReg popqreg;
extern StateEQCommand eqcommand;
extern StateLoadQReg loadqreg;
+ extern StateEPctCommand epctcommand;
+ extern StateSaveQReg saveqreg;
extern StateCtlUCommand ctlucommand;
extern StateEUCommand eucommand;
extern StateSetQRegString setqregstring_nobuilding;
diff --git a/src/ring.cpp b/src/ring.cpp
index e7f7d75..df80246 100644
--- a/src/ring.cpp
+++ b/src/ring.cpp
@@ -372,7 +372,7 @@ StateEditFile::done(const gchar *str)
}
/*$
- * EW$ -- Save or rename current buffer
+ * EW$ -- Save current buffer or Q-Register
* EWfile$
*
* Saves the current buffer to disk.
@@ -381,6 +381,13 @@ StateEditFile::done(const gchar *str)
* the buffer is saved with the specified file name
* and is renamed in the ring.
*
+ * The EW command also works if the current document
+ * is a Q-Register, i.e. a Q-Register is edited.
+ * In this case, the string contents of the current
+ * Q-Register are saved to <file>.
+ * Q-Registers have no notion of associated file names,
+ * so <file> must be always specified.
+ *
* In interactive mode, EW is executed immediately and
* may be rubbed out.
* In order to support that, \*(ST creates so called
@@ -411,8 +418,7 @@ StateSaveFile::done(const gchar *str)
BEGIN_EXEC(&States::start);
if (QRegisters::current)
- throw Error("Cannot save Q-Register");
-// QRegisters::current->save(str);
+ QRegisters::current->save(str);
else
ring.current->save(*str ? str : NULL);