Fixing d8's broken readline history.
authoryangguo@chromium.org <yangguo@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 14 Sep 2011 14:39:56 +0000 (14:39 +0000)
committeryangguo@chromium.org <yangguo@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 14 Sep 2011 14:39:56 +0000 (14:39 +0000)
Review URL: http://codereview.chromium.org/7885026

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@9282 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/d8-readline.cc
src/d8.cc
src/d8.h

index 8422783..71be933 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright 2008 the V8 project authors. All rights reserved.
+// Copyright 2011 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
@@ -72,6 +72,7 @@ bool ReadLineEditor::Open() {
   rl_completer_word_break_characters = kWordBreakCharacters;
   rl_bind_key('\t', rl_complete);
   using_history();
+  stifle_history(Shell::kMaxHistoryEntries);
   return read_history(Shell::kHistoryFileName) == 0;
 }
 
@@ -88,6 +89,18 @@ i::SmartArrayPointer<char> ReadLineEditor::Prompt(const char* prompt) {
 
 
 void ReadLineEditor::AddHistory(const char* str) {
+  // Do not record empty input.
+  if (strlen(str) == 0) return;
+  // Remove duplicate history entry.
+  history_set_pos(history_length-1);
+  if (current_history()) {
+    do {
+      if (strcmp(current_history()->line, str) == 0) {
+        remove_history(where_history());
+        break;
+      }
+    } while (previous_history());
+  }
   add_history(str);
 }
 
index a025299..55f0d4c 100644 (file)
--- a/src/d8.cc
+++ b/src/d8.cc
@@ -70,6 +70,7 @@ namespace v8 {
 #ifndef V8_SHARED
 LineEditor *LineEditor::first_ = NULL;
 const char* Shell::kHistoryFileName = ".d8_history";
+const int Shell::kMaxHistoryEntries = 1000;
 
 
 LineEditor::LineEditor(Type type, const char* name)
@@ -117,6 +118,7 @@ CounterCollection Shell::local_counters_;
 CounterCollection* Shell::counters_ = &local_counters_;
 i::Mutex* Shell::context_mutex_(i::OS::CreateMutex());
 Persistent<Context> Shell::utility_context_;
+LineEditor* Shell::console = NULL;
 #endif  // V8_SHARED
 
 Persistent<Context> Shell::evaluation_context_;
@@ -791,6 +793,7 @@ void Shell::Exit(int exit_code) {
 
 #ifndef V8_SHARED
 void Shell::OnExit() {
+  if (console != NULL) console->Close();
   if (i::FLAG_dump_counters) {
     printf("+----------------------------------------+-------------+\n");
     printf("| Name                                   | Value       |\n");
@@ -895,20 +898,19 @@ void Shell::RunShell() {
   HandleScope outer_scope;
   Handle<String> name = String::New("(d8)");
 #ifndef V8_SHARED
-  LineEditor* editor = LineEditor::Get();
-  printf("V8 version %s [console: %s]\n", V8::GetVersion(), editor->name());
+  console = LineEditor::Get();
+  printf("V8 version %s [console: %s]\n", V8::GetVersion(), console->name());
   if (i::FLAG_debugger) {
     printf("JavaScript debugger enabled\n");
   }
-  editor->Open();
+  console->Open();
   while (true) {
-    i::SmartArrayPointer<char> input = editor->Prompt(Shell::kPrompt);
+    i::SmartArrayPointer<char> input = console->Prompt(Shell::kPrompt);
     if (input.is_empty()) break;
-    editor->AddHistory(*input);
+    console->AddHistory(*input);
     HandleScope inner_scope;
     ExecuteString(String::New(*input), name, true, true);
   }
-  editor->Close();
 #else
   printf("V8 version %s [D8 light using shared library]\n", V8::GetVersion());
   static const int kBufferSize = 256;
index e193f10..15d8d5d 100644 (file)
--- a/src/d8.h
+++ b/src/d8.h
@@ -116,6 +116,29 @@ class CounterMap {
 #endif  // V8_SHARED
 
 
+#ifndef V8_SHARED
+class LineEditor {
+ public:
+  enum Type { DUMB = 0, READLINE = 1 };
+  LineEditor(Type type, const char* name);
+  virtual ~LineEditor() { }
+
+  virtual i::SmartArrayPointer<char> Prompt(const char* prompt) = 0;
+  virtual bool Open() { return true; }
+  virtual bool Close() { return true; }
+  virtual void AddHistory(const char* str) { }
+
+  const char* name() { return name_; }
+  static LineEditor* Get();
+ private:
+  Type type_;
+  const char* name_;
+  LineEditor* next_;
+  static LineEditor* first_;
+};
+#endif  // V8_SHARED
+
+
 class SourceGroup {
  public:
   SourceGroup() :
@@ -313,6 +336,8 @@ class Shell : public i::AllStatic {
   static void AddOSMethods(Handle<ObjectTemplate> os_template);
 #ifndef V8_SHARED
   static const char* kHistoryFileName;
+  static const int kMaxHistoryEntries;
+  static LineEditor* console;
 #endif  // V8_SHARED
   static const char* kPrompt;
   static ShellOptions options;
@@ -343,29 +368,6 @@ class Shell : public i::AllStatic {
 };
 
 
-#ifndef V8_SHARED
-class LineEditor {
- public:
-  enum Type { DUMB = 0, READLINE = 1 };
-  LineEditor(Type type, const char* name);
-  virtual ~LineEditor() { }
-
-  virtual i::SmartArrayPointer<char> Prompt(const char* prompt) = 0;
-  virtual bool Open() { return true; }
-  virtual bool Close() { return true; }
-  virtual void AddHistory(const char* str) { }
-
-  const char* name() { return name_; }
-  static LineEditor* Get();
- private:
-  Type type_;
-  const char* name_;
-  LineEditor* next_;
-  static LineEditor* first_;
-};
-#endif  // V8_SHARED
-
-
 }  // namespace v8