kill_buffer: go to about:blank instead of erroring when killing last buffer
[conkeror.git] / modules / minibuffer-read-file.js
blobbe0821dc412f1429c9ed09397d1723b7645a5cc7
1 /**
2  * (C) Copyright 2008 Jeremy Maitin-Shepard
3  * (C) Copyright 2008 Nelson Elhage
4  * (C) Copyright 2012-2013 John J. Foerch
5  *
6  * Use, modification, and distribution are subject to the terms specified in the
7  * COPYING file.
8 **/
10 require("io.js");
11 require("completers.js");
14 function directory_p (file) {
15     return file.exists() && file.isDirectory();
18 function separator_p (s) {
19     return s == "/" || (WINDOWS && s == "\\");
23 function file_path_completions (completer, data, common_prefix, suffix) {
24     completions.call(this, completer, data);
25     this.common_prefix = common_prefix;
26     this.suffix = suffix;
28 file_path_completions.prototype = {
29     constructor: file_path_completions,
30     __proto__: completions.prototype,
31     toString: function () "#<file_path_completions>",
32     common_prefix: null,
33     suffix: null,
34     get_string: function (i) this.data[i].path,
35     get_input_state: function (i) {
36         var s = this.get_string(i);
37         if (this.data[i].isDirectory() &&
38             (this.suffix == "" ||
39              ! separator_p(this.suffix[0])))
40         {
41             s += "/";
42         }
43         var sel = s.length;
44         return [s + this.suffix, sel, sel];
45     },
46     get common_prefix_input_state () {
47         if (this.count == 1) {
48             var prefix = this.get_string(0);
49             if (this.data[0].isDirectory())
50                 prefix += "/";
51         } else {
52             prefix = this.common_prefix;
53         }
54         var i = prefix.length;
55         return [prefix, i, i];
56     }
60 define_keywords("$test");
61 function file_path_completer () {
62     keywords(arguments, $test = constantly(true));
63     completer.call(this);
64     this.test = arguments.$test;
66 file_path_completer.prototype = {
67     constructor: file_path_completer,
68     __proto__: completer.prototype,
69     toString: function () "#<file_path_completer>",
70     test: null,
71     complete: function (input, pos) {
72         var s = input.substring(0, pos);
73         var suffix = input.substring(pos);
74         var entries = [];
75         try {
76             var f = make_file(s);
77             if (separator_p(s.substr(pos - 1, 1))) {
78                 var dir = f;
79                 var leaf = "";
80             } else {
81                 dir = f.parent;
82                 leaf = f.leafName;
83             }
84             var ll = leaf.length;
85             if (! dir.exists())
86                 return null;
87             var iter = dir.directoryEntries;
88             while (iter.hasMoreElements()) {
89                 var e = iter.getNext().QueryInterface(Ci.nsIFile);
90                 if (e.leafName.substr(0, ll) == leaf &&
91                     this.test(e))
92                 {
93                     entries.push(e);
94                 }
95             }
96         } catch (e) {
97             return null;
98         }
99         entries.sort(function (a, b) {
100             a = a.path;
101             b = b.path;
102             if (a < b)
103                 return -1;
104             if (a > b)
105                 return 1;
106             return 0;
107         });
108         var first = entries[0].path;
109         var last = entries[entries.length - 1].path;
110         var cpi = common_prefix_length(first, last);
111         var common_prefix = first.substring(0, cpi);
112         return new file_path_completions(this, entries, common_prefix, suffix);
113     }
117 /* keywords: $prompt, $initial_value, $history, $completer, $auto_complete */
118 minibuffer.prototype.read_file_path = function () {
119     keywords(arguments,
120              $prompt = "File:",
121              $initial_value = cwd.path,
122              $history = "file",
123              $completer = null);
124     var result = yield this.read(
125         $completer = arguments.$completer || new file_path_completer(),
126         forward_keywords(arguments),
127         $auto_complete);
128     yield co_return(result);
131 minibuffer.prototype.read_file = function () {
132     var result = yield this.read_file_path(forward_keywords(arguments));
133     yield co_return(make_file(result));
136 minibuffer.prototype.read_existing_file = function () {
137     function validator (x) {
138         try {
139             return make_file(x).exists();
140         } catch (e) {
141             return false;
142         }
143     }
144     var result = yield this.read_file_path(
145         forward_keywords(arguments),
146         $validator = validator);
147     yield co_return(result);
150 //XXX: why '_path' instead of just 'read_directory' returning an nsIFile?
151 minibuffer.prototype.read_directory_path = function () {
152     function validator (x) {
153         try {
154             var f = make_file(x);
155             return !f.exists() || f.isDirectory();
156         } catch (e) {
157             return false;
158         }
159     }
160     var result = yield this.read_file_path(
161         forward_keywords(arguments),
162         $completer = new file_path_completer($test = directory_p),
163         $validator = validator); //XXX: overridden by read_existing_directory_path?
164     yield co_return(result);
167 //XXX: why '_path' instead of just 'read_existing_directory' returning an nsIFile?
168 minibuffer.prototype.read_existing_directory_path = function () {
169     function validator (x) {
170         try {
171             return directory_p(make_file(x));
172         } catch (e) {
173             return false;
174         }
175     }
176     var result = yield this.read_directory_path(
177         forward_keywords(arguments),
178         $validator = validator);
179     yield co_return(result);
182 minibuffer.prototype.read_file_check_overwrite = function () {
183     keywords(arguments);
184     var initial_value = arguments.$initial_value;
185     do {
186         var path = yield this.read_file_path(forward_keywords(arguments),
187                                              $initial_value = initial_value);
188         var file = make_file(path);
189         if (file.exists()) {
190             var overwrite = yield this.read_yes_or_no(
191                 $prompt = "Overwrite existing file " + path + "?");
192             if (!overwrite) {
193                 initial_value = path;
194                 continue;
195             }
196         }
197         yield co_return(file);
198     } while (true);
201 provide("minibuffer-read-file");