diff options
-rw-r--r-- | lib/session.tes | 3 | ||||
-rw-r--r-- | src/ioview.cpp | 2 | ||||
-rw-r--r-- | src/main.cpp | 3 | ||||
-rw-r--r-- | src/parser.cpp | 1 | ||||
-rw-r--r-- | src/qregisters.cpp | 75 | ||||
-rw-r--r-- | src/qregisters.h | 27 | ||||
-rw-r--r-- | src/ring.cpp | 12 |
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 ®) +{ + BEGIN_EXEC(&States::saveqreg); + register_argument = ® + 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 ®); +}; + +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); |