From f8be1becf28e29b728bd7cf481d3c717b0831751 Mon Sep 17 00:00:00 2001
From: Jacob Gonzalez <jacobgonzalez5252@gmail.com>
Date: Mon, 27 Jan 2020 14:41:17 +1100
Subject: [PATCH] Updated rustyline to 6.0.0. Added completion_mode config
 (#1289)

* Updated rustyline to 6.0.0. Added completion_mode config

* Formatted completion_mode config
---
 Cargo.lock              |  4 ++--
 Cargo.toml              |  2 +-
 README.md               | 15 ++++++++-------
 docs/commands/config.md | 15 ++++++++-------
 src/cli.rs              | 15 +++++++++++++--
 src/shell/helper.rs     |  4 ++++
 6 files changed, 36 insertions(+), 19 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index fe82ffccdb..4b83f7d3a8 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3372,9 +3372,9 @@ dependencies = [
 
 [[package]]
 name = "rustyline"
-version = "5.0.6"
+version = "6.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a23cb19702a8d6afb6edb3c842386e680d4883760e0df74e6848e23c2a87a635"
+checksum = "de64be8eecbe428b6924f1d8430369a01719fbb182c26fa431ddbb0a95f5315d"
 dependencies = [
  "cfg-if",
  "dirs 2.0.2",
diff --git a/Cargo.toml b/Cargo.toml
index 688e2dee1f..05bf08f6a0 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -61,7 +61,7 @@ nu-macros = { version = "0.8.0", path = "./crates/nu-macros" }
 
 query_interface = "0.3.5"
 typetag = "0.1.4"
-rustyline = "5.0.6"
+rustyline = "6.0.0"
 chrono = { version = "0.4.10", features = ["serde"] }
 derive-new = "0.5.8"
 prettytable-rs = "0.8.0"
diff --git a/README.md b/README.md
index 2034a5ed1b..9f0b7fa011 100644
--- a/README.md
+++ b/README.md
@@ -192,13 +192,14 @@ Here we use the variable `$it` to refer to the value being piped to the external
 
 Nu has early support for configuring the shell. It currently supports the following settings:
 
-| Variable        | Type           | Description  |
-| ------------- | ------------- | ----- |
-| path | table of strings | PATH to use to find binaries |
-| env | row | the environment variables to pass to external commands |
-| ctrlc_exit | boolean | whether or not to exit Nu after multiple ctrl-c presses |
-| table_mode | "light" or other | enable lightweight or normal tables |
-| edit_mode | "vi" or "emacs" | changes line editing to "vi" or "emacs" mode |
+| Variable        | Type                 | Description                                                    |
+| --------------- | -------------------- | -------------------------------------------------------------- |
+| path            | table of strings     | PATH to use to find binaries                                   |
+| env             | row                  | the environment variables to pass to external commands         |
+| ctrlc_exit      | boolean              | whether or not to exit Nu after multiple ctrl-c presses        |
+| table_mode      | "light" or other     | enable lightweight or normal tables                            |
+| edit_mode       | "vi" or "emacs"      | changes line editing to "vi" or "emacs" mode                   |
+| completion_mode | "circular" or "list" | changes completion type to "circular" (default) or "list" mode |
 
 To set one of these variables, you can use `config --set`. For example:
 
diff --git a/docs/commands/config.md b/docs/commands/config.md
index d034690a9d..1cc3781297 100644
--- a/docs/commands/config.md
+++ b/docs/commands/config.md
@@ -29,13 +29,14 @@ Syntax: `config {flags}`
 
 ### Variables
 
-| Variable   | Type             | Description                                             |
-| ---------- | ---------------- | ------------------------------------------------------- |
-| path       | table of strings | PATH to use to find binaries                            |
-| env        | row              | the environment variables to pass to external commands  |
-| ctrlc_exit | boolean          | whether or not to exit Nu after multiple ctrl-c presses |
-| table_mode | "light" or other | enable lightweight or normal tables                     |
-| edit_mode  | "vi" or "emacs"  | changes line editing to "vi" or "emacs" mode            |
+| Variable        | Type                 | Description                                                    |
+| --------------- | -------------------- | -------------------------------------------------------------- |
+| path            | table of strings     | PATH to use to find binaries                                   |
+| env             | row                  | the environment variables to pass to external commands         |
+| ctrlc_exit      | boolean              | whether or not to exit Nu after multiple ctrl-c presses        |
+| table_mode      | "light" or other     | enable lightweight or normal tables                            |
+| edit_mode       | "vi" or "emacs"      | changes line editing to "vi" or "emacs" mode                   |
+| completion_mode | "circular" or "list" | changes completion type to "circular" (default) or "list" mode |
 
 ## Examples
 
diff --git a/src/cli.rs b/src/cli.rs
index 85c1265082..67123ba14b 100644
--- a/src/cli.rs
+++ b/src/cli.rs
@@ -18,8 +18,8 @@ use nu_protocol::{Signature, UntaggedValue, Value};
 use log::{debug, log_enabled, trace};
 use rustyline::error::ReadlineError;
 use rustyline::{
-    self, config::Configurer, config::EditMode, At, Cmd, ColorMode, Config, Editor, KeyPress,
-    Movement, Word,
+    self, config::Configurer, config::EditMode, At, Cmd, ColorMode, CompletionType, Config, Editor,
+    KeyPress, Movement, Word,
 };
 use std::error::Error;
 use std::io::{BufRead, BufReader, Write};
@@ -419,6 +419,17 @@ pub async fn cli() -> Result<(), Box<dyn Error>> {
 
         rl.set_edit_mode(edit_mode);
 
+        let completion_mode = config::config(Tag::unknown())?
+            .get("completion_mode")
+            .map(|s| match s.value.expect_string() {
+                "list" => CompletionType::List,
+                "circular" => CompletionType::Circular,
+                _ => CompletionType::Circular,
+            })
+            .unwrap_or(CompletionType::Circular);
+
+        rl.set_completion_type(completion_mode);
+
         let colored_prompt = {
             #[cfg(feature = "starship-prompt")]
             {
diff --git a/src/shell/helper.rs b/src/shell/helper.rs
index 070a10bb8c..4e2cb80aca 100644
--- a/src/shell/helper.rs
+++ b/src/shell/helper.rs
@@ -204,3 +204,7 @@ impl Painter {
 }
 
 impl rustyline::Helper for Helper {}
+
+// Use default validator for normal single line behaviour
+// In the future we can implement this for custom multi-line support
+impl rustyline::validate::Validator for Helper {}