blob: 67fc9eff7e528fd66dba1e724f2e42909dd76668 [file] [log] [blame]
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001// Copyright 2008 the V8 project authors. All rights reserved.
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28
ager@chromium.org8bb60582008-12-11 12:02:20 +000029#include <cstdio> // NOLINT
ager@chromium.org5c838252010-02-19 08:53:10 +000030#include <readline/readline.h> // NOLINT
31#include <readline/history.h> // NOLINT
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000032
33
34#include "d8.h"
35
36
ager@chromium.org8bb60582008-12-11 12:02:20 +000037// There are incompatibilities between different versions and different
ager@chromium.org32912102009-01-16 10:38:43 +000038// implementations of readline. This smooths out one known incompatibility.
ager@chromium.org8bb60582008-12-11 12:02:20 +000039#if RL_READLINE_VERSION >= 0x0500
40#define completion_matches rl_completion_matches
41#endif
42
43
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000044namespace v8 {
45
46
47class ReadLineEditor: public LineEditor {
48 public:
49 ReadLineEditor() : LineEditor(LineEditor::READLINE, "readline") { }
50 virtual i::SmartPointer<char> Prompt(const char* prompt);
51 virtual bool Open();
52 virtual bool Close();
53 virtual void AddHistory(const char* str);
54 private:
55 static char** AttemptedCompletion(const char* text, int start, int end);
56 static char* CompletionGenerator(const char* text, int state);
57 static char kWordBreakCharacters[];
58};
59
60
61static ReadLineEditor read_line_editor;
62char ReadLineEditor::kWordBreakCharacters[] = {' ', '\t', '\n', '"',
63 '\\', '\'', '`', '@', '.', '>', '<', '=', ';', '|', '&', '{', '(',
64 '\0'};
65
66
67bool ReadLineEditor::Open() {
68 rl_initialize();
69 rl_attempted_completion_function = AttemptedCompletion;
70 rl_completer_word_break_characters = kWordBreakCharacters;
71 rl_bind_key('\t', rl_complete);
72 using_history();
73 return read_history(Shell::kHistoryFileName) == 0;
74}
75
76
77bool ReadLineEditor::Close() {
78 return write_history(Shell::kHistoryFileName) == 0;
79}
80
81
82i::SmartPointer<char> ReadLineEditor::Prompt(const char* prompt) {
83 char* result = readline(prompt);
84 return i::SmartPointer<char>(result);
85}
86
87
88void ReadLineEditor::AddHistory(const char* str) {
89 add_history(str);
90}
91
92
93char** ReadLineEditor::AttemptedCompletion(const char* text,
94 int start,
95 int end) {
ager@chromium.org8bb60582008-12-11 12:02:20 +000096 char** result = completion_matches(text, CompletionGenerator);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000097 rl_attempted_completion_over = true;
98 return result;
99}
100
101
102char* ReadLineEditor::CompletionGenerator(const char* text, int state) {
103 static unsigned current_index;
104 static Persistent<Array> current_completions;
105 if (state == 0) {
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000106 i::SmartPointer<char> full_text(i::StrNDup(rl_line_buffer, rl_point));
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000107 HandleScope scope;
108 Handle<Array> completions =
109 Shell::GetCompletions(String::New(text), String::New(*full_text));
110 current_completions = Persistent<Array>::New(completions);
111 current_index = 0;
112 }
113 if (current_index < current_completions->Length()) {
114 HandleScope scope;
115 Handle<Integer> index = Integer::New(current_index);
116 Handle<Value> str_obj = current_completions->Get(index);
117 current_index++;
118 String::Utf8Value str(str_obj);
119 return strdup(*str);
120 } else {
121 current_completions.Dispose();
122 current_completions.Clear();
123 return NULL;
124 }
125}
126
127
128} // namespace v8