refactor completers
[conkeror.git] / modules / minibuffer-read-file.js
blobe01cb487a7a3bde8a58cf049735b0d27fc367de9
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, suffix) {
24     completions.call(this, completer, data);
25     this.suffix = suffix;
27 file_path_completions.prototype = {
28     constructor: file_path_completions,
29     __proto__: completions.prototype,
30     toString: function () "#<file_path_completions>",
31     suffix: null,
32     get_string: function (i) this.data[i].path,
33     get_input_state: function (i) {
34         var s = this.get_string(i);
35         if (this.data[i].isDirectory() &&
36             (this.suffix == "" ||
37              ! separator_p(this.suffix[0])))
38         {
39             s += "/";
40         }
41         var sel = s.length;
42         return [s + this.suffix, sel, sel];
43     }
47 define_keywords("$test");
48 function file_path_completer () {
49     keywords(arguments, $test = constantly(true));
50     completer.call(this);
51     this.test = arguments.$test;
53 file_path_completer.prototype = {
54     constructor: file_path_completer,
55     __proto__: completer.prototype,
56     toString: function () "#<file_path_completer>",
57     test: null,
58     complete: function (input, pos) {
59         var s = input.substring(0, pos);
60         var suffix = input.substring(pos);
61         var ents = [];
62         try {
63             var f = make_file(s);
64             if (directory_p(f)) {
65                 var dir = f;
66                 var leaf = "";
67             } else {
68                 dir = f.parent;
69                 leaf = f.leafName;
70             }
71             var ll = leaf.length;
72             if (! dir.exists())
73                 return null;
74             var iter = dir.directoryEntries;
75             while (iter.hasMoreElements()) {
76                 var e = iter.getNext().QueryInterface(Ci.nsIFile);
77                 if (e.leafName.substr(0, ll) == leaf &&
78                     this.test(e))
79                 {
80                     ents.push(e);
81                 }
82             }
83         } catch (e) {
84             return null;
85         }
86         return new file_path_completions(this, ents, suffix);
87     }
91 /* keywords: $prompt, $initial_value, $history, $completer, $auto_complete */
92 minibuffer.prototype.read_file_path = function () {
93     keywords(arguments,
94              $prompt = "File:",
95              $initial_value = cwd.path,
96              $history = "file",
97              $completer = null);
98     var result = yield this.read(
99         $prompt = arguments.$prompt,
100         $initial_value = arguments.$initial_value,
101         $history = arguments.$history,
102         $completer = arguments.$completer || new file_path_completer(),
103         $auto_complete);
104     yield co_return(result);
107 minibuffer.prototype.read_file = function () {
108     var result = yield this.read_file_path(forward_keywords(arguments));
109     yield co_return(make_file(result));
112 minibuffer.prototype.read_existing_file = function () {
113     var result = yield this.read_file_path(
114         forward_keywords(arguments),
115         $require_match);
116     yield co_return(result);
119 minibuffer.prototype.read_directory_path = function () {
120     function validator (x) {
121         try {
122             return directory_p(make_file(x));
123         } catch (e) {
124             return false;
125         }
126     }
127     var result = yield this.read_file_path(
128         forward_keywords(arguments),
129         $completer = new file_path_completer($test = directory_p),
130         $validator = validator); //XXX: check if this works.  it's okay if
131                                  //the result doesn't exist, but not okay
132                                  //if it exists but is not a directory.
133     yield co_return(result);
136 minibuffer.prototype.read_existing_directory_path = function () {
137     var result = yield this.read_directory_path(
138         forward_keywords(arguments),
139         $require_match);
140     yield co_return(result);
143 minibuffer.prototype.read_file_check_overwrite = function () {
144     keywords(arguments);
145     var initial_value = arguments.$initial_value;
146     do {
147         var path = yield this.read_file_path(forward_keywords(arguments),
148                                              $initial_value = initial_value);
149         var file = make_file(path);
150         if (file.exists()) {
151             var overwrite = yield this.read_yes_or_no(
152                 $prompt = "Overwrite existing file " + path + "?");
153             if (!overwrite) {
154                 initial_value = path;
155                 continue;
156             }
157         }
158         yield co_return(file);
159     } while (true);
162 provide("minibuffer-read-file");