There are two changes in this patch:
1. Loading the history, the code used 

  while (!infile.eof()) {
      getline(infile, ...);
      ...
  }

That's simply wrong, because it will read one superfluous empty line at the 
end. You need to check if reading succeeded instead of checking if the stream 
already encountered EOF.

2. Writing back the history, the code tried to skip elements until it found 
the current one, then write the rest and then finally the current command. 
This avoids writing the beginning of the file, but firstly it doesn't work, 
and secondly it is IMHO a completely unnecessary optimization because a) it 
isn't called often enough and b) the file is <1kB here after years of use. I'm 
using the most simple implementation and just write the whole history every 
time, skipping all duplicates and finally append the current command.


There was one thing I'm not sure how the code was supposed to work and which 
wasn't documented either. The question is how editing of previously entered 
commands is reflected in the history. There are two approaches:
1. If I enter "xter" (if I pressed enter too early), going back in history and 
then appending the "m", it replaces the "xter" with "xterm" in history.
2. If I enter "xter", going back in history and appending the "m" yields two 
entries "xter" and "xterm".

I chose approach 1 in the patch. However, that means that if a user wants to 
have two entries like "xterm sh" and "xterm bash", they can't achieve that by 
just editing the history, they must enter them completely separately instead. 
If you don't like that, just skip the code leading to the second "continue" in 
the look that writes the history. ;)

Cheers!

Uli
Index: FbRun.cc
===================================================================
--- FbRun.cc	(revision 34)
+++ FbRun.cc	(revision 39)
@@ -137,43 +137,22 @@
     hide(); // hide gui
 
     // save command history to file
-    if (text().size() != 0) { // no need to save empty command
+    if (!command.empty()) { // no need to save empty command
 
-        // don't allow duplicates into the history file, first
-        // look for a duplicate
-        if (m_current_history_item < m_history.size()
-            && text() == m_history[m_current_history_item]) {
-            // m_current_history_item is the duplicate
-        } else {
-            m_current_history_item = 0;
-            for (; m_current_history_item < m_history.size();
-                 ++m_current_history_item) {
-                if (m_history[m_current_history_item] == text())
-                    break;
-            }
-        }
-
-        fstream inoutfile(m_history_file.c_str(), ios::in|ios::out);
-        if (inoutfile) {
-            // now m_current_history_item points at the duplicate, or
-            // at m_history.size() if no duplicate
-            if (m_current_history_item != m_history.size()) {
-                unsigned int i = 0;
-                // read past history items before current
-                for (; inoutfile.good() && i < m_current_history_item; i++)
-                    inoutfile.ignore(1, '\n');
-
-                // write the history items that come after current
-                for (i++; i < m_history.size(); i++)
-                    inoutfile<<m_history[i]<<endl;
-
-            } else {
-                // set put-pointer at end of file
-                inoutfile.seekp(0, ios::end);
+        ofstream outfile(m_history_file.c_str());
+        if (outfile) {
+            for (unsigned i = 0; i != m_history.size(); ++i) {
+                // don't allow duplicates into the history file
+                if (m_history[i] == command)
+                    continue;
+                // skip currently selected item, this will be appended but is
+                // not caught as duplicate when it was modified by the user
+                if (i == m_current_history_item)
+                    continue;
+                outfile<<m_history[i]<<endl;
             }
             // append current command to the file
-            inoutfile<<command<<endl;
-
+            outfile<<command<<endl;
         } else
             cerr<<"FbRun Warning: Can't write command history to file: "<<m_history_file<<endl;
     }
@@ -197,8 +176,7 @@
     m_history.clear();
     // each line is a command
     string line;
-    while (!infile.eof()) {
-        getline(infile, line);
+    while (getline(infile, line)) {
         if (line.size()) // don't add empty lines
             m_history.push_back(line);
     }

Reply via email to