MI: Add new command -complete

Message ID 20190103222930.4365-1-jan.vrany@fit.cvut.cz
State New
Headers show
Series
  • MI: Add new command -complete
Related show

Commit Message

Jan Vrany Jan. 3, 2019, 10:29 p.m.
There is a CLI command 'complete' intended to use with emacs. Such a command
would also be useful for MI frontends, when separate CLI and MI channels cannot
be used. For example, on Windows (because of lack of PTYs) or when GDB is used
through SSH session.

This commit adds a new '-complete' MI command which is implemented using
CLI's 'complete'.

gdb/Changelog:
2019-01-03  Jan Vrany  <jan.vrany@fit.cvut.cz>

	* cli/cli-cmds.h: Export complete_command.
	* cli/cli-cmds.c (complete_command): Update to print completions
	on MI channel if requested.
	* mi/mi-cmds.c: Define new -complete command implemented using
	it CLI command 'complete'.
	* NEWS: Mention new -complete command.

gdb/doc/ChangeLog:
2019-01-03  Jan Vrany  <jan.vrany@fit.cvut.cz>

	* gdb.texinfo (Miscellaneous GDB/MI Commands): Document new
	MI command -complete.

gdb/testsuite/ChangeLog:
2019-01-03  Jan Vrany  <jan.vrany@fit.cvut.cz>

	* gdb.mi/mi-complete.exp: New file.
---
 gdb/ChangeLog                        |  9 +++
 gdb/NEWS                             |  7 ++
 gdb/cli/cli-cmds.c                   | 95 +++++++++++++++++++---------
 gdb/cli/cli-cmds.h                   |  4 ++
 gdb/doc/ChangeLog                    |  5 ++
 gdb/doc/gdb.texinfo                  | 32 ++++++++++
 gdb/mi/mi-cmds.c                     |  3 +
 gdb/testsuite/ChangeLog              |  4 ++
 gdb/testsuite/gdb.mi/mi-complete.exp | 71 +++++++++++++++++++++
 9 files changed, 199 insertions(+), 31 deletions(-)
 create mode 100644 gdb/testsuite/gdb.mi/mi-complete.exp

-- 
2.20.1

Comments

Jan Vrany Jan. 16, 2019, 9:21 a.m. | #1
Polite ping. 

Jan

On Thu, 2019-01-03 at 22:29 +0000, Jan Vrany wrote:
> There is a CLI command 'complete' intended to use with emacs. Such a command

> would also be useful for MI frontends, when separate CLI and MI channels cannot

> be used. For example, on Windows (because of lack of PTYs) or when GDB is used

> through SSH session.

> 

> This commit adds a new '-complete' MI command which is implemented using

> CLI's 'complete'.

> 

> gdb/Changelog:

> 2019-01-03  Jan Vrany  <jan.vrany@fit.cvut.cz>

> 

> 	* cli/cli-cmds.h: Export complete_command.

> 	* cli/cli-cmds.c (complete_command): Update to print completions

> 	on MI channel if requested.

> 	* mi/mi-cmds.c: Define new -complete command implemented using

> 	it CLI command 'complete'.

> 	* NEWS: Mention new -complete command.

> 

> gdb/doc/ChangeLog:

> 2019-01-03  Jan Vrany  <jan.vrany@fit.cvut.cz>

> 

> 	* gdb.texinfo (Miscellaneous GDB/MI Commands): Document new

> 	MI command -complete.

> 

> gdb/testsuite/ChangeLog:

> 2019-01-03  Jan Vrany  <jan.vrany@fit.cvut.cz>

> 

> 	* gdb.mi/mi-complete.exp: New file.

> ---

>  gdb/ChangeLog                        |  9 +++

>  gdb/NEWS                             |  7 ++

>  gdb/cli/cli-cmds.c                   | 95 +++++++++++++++++++---------

>  gdb/cli/cli-cmds.h                   |  4 ++

>  gdb/doc/ChangeLog                    |  5 ++

>  gdb/doc/gdb.texinfo                  | 32 ++++++++++

>  gdb/mi/mi-cmds.c                     |  3 +

>  gdb/testsuite/ChangeLog              |  4 ++

>  gdb/testsuite/gdb.mi/mi-complete.exp | 71 +++++++++++++++++++++

>  9 files changed, 199 insertions(+), 31 deletions(-)

>  create mode 100644 gdb/testsuite/gdb.mi/mi-complete.exp

> 

> diff --git a/gdb/ChangeLog b/gdb/ChangeLog

> index 08c7c6c1f4..322b539417 100644

> --- a/gdb/ChangeLog

> +++ b/gdb/ChangeLog

> @@ -1,3 +1,12 @@

> +2019-01-03  Jan Vrany  <jan.vrany@fit.cvut.cz>

> +

> +	* cli/cli-cmds.h: Export complete_command.

> +	* cli/cli-cmds.c (complete_command): Update to print completions

> +	on MI channel if requested.

> +	* mi/mi-cmds.c: Define new -complete command implemented using

> +	it CLI command 'complete'.

> +	* NEWS: Mention new -complete command.

> +

>  2018-12-17  Andrew Burgess  <andrew.burgess@embecosm.com>

>  

>  	* dwarf2read.c (struct dwarf2_cu): Convert the fields 'mark',

> diff --git a/gdb/NEWS b/gdb/NEWS

> index 913f3ae3b6..6b561af71f 100644

> --- a/gdb/NEWS

> +++ b/gdb/NEWS

> @@ -96,6 +96,13 @@ maint show dwarf unwinders

>  info proc files

>    Display a list of open files for a process.

>  

> +* New MI commands

> +

> +-complete

> +  This lists all the possible completions for the rest of the line, if it

> +  were to be given as a command itself.  This is intended for use by MI frontends

> +  in cases when separate CLI and MI channels cannot be used.

> +

>  * Changed commands

>  

>  target remote FILENAME

> diff --git a/gdb/cli/cli-cmds.c b/gdb/cli/cli-cmds.c

> index 135f550b80..468f66dac6 100644

> --- a/gdb/cli/cli-cmds.c

> +++ b/gdb/cli/cli-cmds.c

> @@ -223,16 +223,22 @@ help_command (const char *command, int from_tty)

>  /* Note: The "complete" command is used by Emacs to implement completion.

>     [Is that why this function writes output with *_unfiltered?]  */

>  

> -static void

> +void

>  complete_command (const char *arg, int from_tty)

>  {

> +  struct ui_out *uiout = current_uiout;

> +  bool is_mi_like = uiout->is_mi_like_p ();

> +

>    dont_repeat ();

>  

>    if (max_completions == 0)

>      {

> -      /* Only print this for non-mi frontends.  An MI frontend may not

> -	 be able to handle this.  */

> -      if (!current_uiout->is_mi_like_p ())

> +      if (is_mi_like)

> +        {

> +          error (_("max-completions is zero,"

> +		   " completion is disabled.\n"));

> +        }

> +      else

>  	{

>  	  printf_unfiltered (_("max-completions is zero,"

>  			       " completion is disabled.\n"));

> @@ -278,34 +284,61 @@ complete_command (const char *arg, int from_tty)

>    completion_result result

>      = tracker->build_completion_result (word, word - arg, strlen (arg));

>  

> -  if (result.number_matches != 0)

> -    {

> -      if (result.number_matches == 1)

> -	printf_unfiltered ("%s%s\n", arg_prefix.c_str (), result.match_list[0]);

> -      else

> -	{

> -	  result.sort_match_list ();

> -

> -	  for (size_t i = 0; i < result.number_matches; i++)

> -	    {

> -	      printf_unfiltered ("%s%s",

> -				 arg_prefix.c_str (),

> -				 result.match_list[i + 1]);

> -	      if (quote_char)

> -		printf_unfiltered ("%c", quote_char);

> -	      printf_unfiltered ("\n");

> -	    }

> -	}

> -

> -      if (result.number_matches == max_completions)

> -	{

> -	  /* ARG_PREFIX and WORD are included in the output so that emacs

> -	     will include the message in the output.  */

> -	  printf_unfiltered (_("%s%s %s\n"),

> -			     arg_prefix.c_str (), word,

> -			     get_max_completions_reached_message ());

> -	}

> +  {

> +    ui_out_emit_list completions_emitter (uiout, "completions");

> +    if (result.number_matches != 0)

> +      {

> +        if (result.number_matches == 1)

> +          {

> +	    if (is_mi_like)

> +	      uiout->field_fmt(NULL, "%s%s", arg_prefix.c_str (),

> +                                             result.match_list[0]);

> +	    else

> +	      printf_unfiltered ("%s%s\n", arg_prefix.c_str (),

> +                                           result.match_list[0]);

> +          }

> +        else

> +	  {

> +	    result.sort_match_list ();

> +

> +	    for (size_t i = 0; i < result.number_matches; i++)

> +	      {

> +                if (is_mi_like)

> +	          {

> +	            uiout->field_fmt(NULL, "%s%s", arg_prefix.c_str (),

> +                                                   result.match_list[i + 1]);

> +	          }

> +	        else

> +	          {

> +		    printf_unfiltered ("%s%s", arg_prefix.c_str (),

> +                                               result.match_list[i + 1]);

> +		    if (quote_char)

> +		      printf_unfiltered ("%c", quote_char);

> +		    printf_unfiltered ("\n");

> +	          }

> +	      }

> +	  }

> +      }

>      }

> +

> +    if (result.number_matches == max_completions)

> +      {

> +	if (is_mi_like)

> +	  uiout->field_string("max_completions_reached", "1");

> +	else

> +	  {

> +	    /* ARG_PREFIX and WORD are included in the output so that emacs

> +	       will include the message in the output.  */

> +	    printf_unfiltered (_("%s%s %s\n"),

> +				 arg_prefix.c_str (), word,

> +				 get_max_completions_reached_message ());

> +	  }

> +      }

> +    else

> +      {

> +	if (is_mi_like)

> +	  uiout->field_string("max_completions_reached", "0");

> +      }

>  }

>  

>  int

> diff --git a/gdb/cli/cli-cmds.h b/gdb/cli/cli-cmds.h

> index 3fa188dba6..bcd12c0c0b 100644

> --- a/gdb/cli/cli-cmds.h

> +++ b/gdb/cli/cli-cmds.h

> @@ -106,6 +106,10 @@ void init_cmd_lists (void);

>  

>  void init_cli_cmds (void);

>  

> +/* Exported to gdb/mi/mi-cmds.c */

> +

> +void complete_command (const char *, int);

> +

>  int is_complete_command (struct cmd_list_element *cmd);

>  

>  /* Exported to gdb/main.c */

> diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog

> index 68d3068c72..da81f6a6c1 100644

> --- a/gdb/doc/ChangeLog

> +++ b/gdb/doc/ChangeLog

> @@ -1,3 +1,8 @@

> +2019-01-03  Jan Vrany  <jan.vrany@fit.cvut.cz>

> +

> +	* gdb.texinfo (Miscellaneous GDB/MI Commands): Document new

> +	MI command -complete.

> +

>  2018-12-13  John Baldwin  <jhb@FreeBSD.org>

>  

>  	* gdb.texinfo (Set Catchpoints): Add an anchor for 'catch syscall'.

> diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo

> index d766e44e63..7f88273145 100644

> --- a/gdb/doc/gdb.texinfo

> +++ b/gdb/doc/gdb.texinfo

> @@ -34236,6 +34236,38 @@ fullname="/home/nickrob/myprog.c",line="73",arch="i386:x86_64"@}

>  (gdb)

>  @end smallexample

>  

> +@subheading The @code{-complete} Command

> +@findex -complete

> +

> +@subheading Synopsis

> +

> +@smallexample

> +-complete @var{command}

> +@end smallexample

> +

> +Show a list of completions for partially typed CLI @var{command}. The

> +@var{command} should be given in verbatim without any quoting / escaping.

> +

> +This command is intended for @sc{gdb/mi} frontends that cannot use two separate

> +CLI and MI channels - for example: because of lack of PTYs like on Windows or

> +because @sc{gdb} is used remotely via a SSH connection.

> +

> +@subheading @value{GDBN} Command

> +

> +The corresponding @value{GDBN} command is @samp{complete}.

> +

> +@subheading Example

> +

> +@smallexample

> +(gdb)

> +-complete br

> +^done,completions=["break","break-range"],max_completions_reached="0"

> +(gdb)

> +-complete b madv

> +^done,completions=["b madvise"],max_completions_reached="0"

> +(gdb)

> +@end smallexample

> +

>  @node Annotations

>  @chapter @value{GDBN} Annotations

>  

> diff --git a/gdb/mi/mi-cmds.c b/gdb/mi/mi-cmds.c

> index 51014eded2..7b510f71d4 100644

> --- a/gdb/mi/mi-cmds.c

> +++ b/gdb/mi/mi-cmds.c

> @@ -20,9 +20,11 @@

>  

>  #include "defs.h"

>  #include "top.h"

> +#include "cli/cli-cmds.h"

>  #include "mi-cmds.h"

>  #include "mi-main.h"

>  

> +

>  struct mi_cmd;

>  static struct mi_cmd **lookup_table (const char *command);

>  static void build_table (struct mi_cmd *commands);

> @@ -75,6 +77,7 @@ static struct mi_cmd mi_cmds[] =

>                     &mi_suppress_notification.breakpoint),

>    DEF_MI_CMD_MI_1 ("catch-unload", mi_cmd_catch_unload,

>                     &mi_suppress_notification.breakpoint),

> +  DEF_MI_CMD_CLI ("complete", "complete", 1),

>    DEF_MI_CMD_MI ("data-disassemble", mi_cmd_disassemble),

>    DEF_MI_CMD_MI ("data-evaluate-expression", mi_cmd_data_evaluate_expression),

>    DEF_MI_CMD_MI ("data-list-changed-registers",

> diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog

> index ab3a74fffd..40da71b2c5 100644

> --- a/gdb/testsuite/ChangeLog

> +++ b/gdb/testsuite/ChangeLog

> @@ -1,3 +1,7 @@

> +2019-01-03  Jan Vrany  <jan.vrany@fit.cvut.cz>

> +

> +	* gdb.mi/mi-complete.exp: New file.

> +

>  2018-12-12  Andrew Burgess  <andrew.burgess@embecosm.com>

>  

>  	* gdb.base/annota1.exp: Update a test regexp.

> diff --git a/gdb/testsuite/gdb.mi/mi-complete.exp b/gdb/testsuite/gdb.mi/mi-complete.exp

> new file mode 100644

> index 0000000000..14c763a966

> --- /dev/null

> +++ b/gdb/testsuite/gdb.mi/mi-complete.exp

> @@ -0,0 +1,71 @@

> +# Copyright 2018 Free Software Foundation, Inc.

> +

> +# This program is free software; you can redistribute it and/or modify

> +# it under the terms of the GNU General Public License as published by

> +# the Free Software Foundation; either version 3 of the License, or

> +# (at your option) any later version.

> +#

> +# This program is distributed in the hope that it will be useful,

> +# but WITHOUT ANY WARRANTY; without even the implied warranty of

> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the

> +# GNU General Public License for more details.

> +#

> +# You should have received a copy of the GNU General Public License

> +# along with this program.  If not, see <http://www.gnu.org/licenses/>;.

> +

> +# Verify -data-evaluate-expression. There are really minimal tests.

> +

> +# The goal is not to test gdb functionality, which is done by other tests,

> +# but to verify the correct output response to MI operations.

> +#

> +

> +load_lib mi-support.exp

> +set MIFLAGS "-i=mi"

> +

> +gdb_exit

> +if [mi_gdb_start] {

> +    continue

> +}

> +

> +standard_testfile basics.c

> +

> +if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {

> +     untested "failed to compile"

> +     return -1

> +}

> +

> +mi_run_to_main

> +

> +mi_gdb_test "1-complete br" \

> +            "1\\^done,completions=\\\[.*\"break\",.*\"break-range\".*\\\],max_completions_reached=\"0\"" \

> +            "-complete br"

> +

> +# Check empty completion list

> +mi_gdb_test "5-complete bogus" \

> +            "5\\^done,completions=\\\[\\\],max_completions_reached=\"0\"" \

> +            "-complete bogus"

> +

> +

> +# Check completions for commands with space

> +mi_gdb_test "4-complete b mai" \

> +            "4\\^done,completions=\\\[.*\"b main\".*\\\],max_completions_reached=\"0\"" \

> +            "-complete b mai"

> +

> +mi_gdb_test "-info-gdb-mi-command complete" \

> +            "\\^done,command=\{exists=\"true\"\}" \

> +            "-info-gdb-mi-command complete"

> +

> +# Limit max completions and check that max_completions_reached=\"0\" is set

> +# to 1.

> +send_gdb "set max-completions 1\n"

> +

> +mi_gdb_test "2-complete br" \

> +            ".*2\\^done,completions=\\\[\"br\[A-Za-z0-9-\]+\"\\\],max_completions_reached=\"1\"" \

> +            "-complete br (max-completions 1)"

> +

> +# Disable completions and check an error is returned

> +send_gdb "set max-completions 0\n"

> +

> +mi_gdb_test "3-complete br" \

> +            ".*3\\^error,msg=\".*" \

> +            "-complete br (max-completions 1)"
Tom Tromey Jan. 17, 2019, 8:29 p.m. | #2
>>>>> "Jan" == Jan Vrany <jan.vrany@fit.cvut.cz> writes:


Jan> This commit adds a new '-complete' MI command which is implemented using
Jan> CLI's 'complete'.

I suspect it would be better to just write a new MI function and then
mildly refactor complete_command so that the two commands can share most
of their implementation.

First, this would make it so we could add options to the MI command as
needed.  (Perhaps the current argument to the command ought to have a
flag to avoid future parsing problems?  I am not sure.)

Second, it would mean that we could make changes to the CLI command
without worrying about breaking MI compatibility.

What do you think of this?

I looked and I see that some other MI commands are implemented directly
by CLI commands.  I am not sure but I suspect this might be a deprecated
approach.

Jan> +  bool is_mi_like = uiout->is_mi_like_p ();

This could be removed by having a more explicit API.

Jan> +    ui_out_emit_list completions_emitter (uiout, "completions");
Jan> +    if (result.number_matches != 0)
Jan> +      {
Jan> +        if (result.number_matches == 1)
Jan> +          {
Jan> +	    if (is_mi_like)
Jan> +	      uiout->field_fmt(NULL, "%s%s", arg_prefix.c_str (),
Jan> +                                             result.match_list[0]);
Jan> +	    else
Jan> +	      printf_unfiltered ("%s%s\n", arg_prefix.c_str (),
Jan> +                                           result.match_list[0]);

Space before "(" in the field_fmt call.  Unifying the cases would be
preferable.  Or another argument for separation.

thanks,
Tom
Jan Vrany Jan. 17, 2019, 9:01 p.m. | #3
On Thu, 2019-01-17 at 13:29 -0700, Tom Tromey wrote:
> > > > > > "Jan" == Jan Vrany <jan.vrany@fit.cvut.cz> writes:

> 

> Jan> This commit adds a new '-complete' MI command which is implemented using

> Jan> CLI's 'complete'.

> 

> I suspect it would be better to just write a new MI function and then

> mildly refactor complete_command so that the two commands can share most

> of their implementation.

> 

> First, this would make it so we could add options to the MI command as

> needed.  (Perhaps the current argument to the command ought to have a

> flag to avoid future parsing problems?  


What do you mean by this? Can you give an example? 

> I am not sure.)

> 

> Second, it would mean that we could make changes to the CLI command

> without worrying about breaking MI compatibility.


As for changes to CLI command, I've got the impression from the code that
the format is rather strict (from use of printf_unfiltered(), for instance),
deliberately so to not break clients (Emacs is mentioned). Indeed, not really
an argument against splitting. 

> 

> What do you think of this?


I thought of that actually. Also, it'd make the MI interface more regular
w.r.t quoting of spaces and other special characters. But in the end I could 
not find a way without duplicating enough code from the original function, 
so hacked it that way. 

Let me try harder :-) 

> 

> I looked and I see that some other MI commands are implemented directly

> by CLI commands.  I am not sure but I suspect this might be a deprecated

> approach.


Yeah, there's quite a lot of them. If it is a deprecated approach, 
I did not know. 

> 

> Jan> +  bool is_mi_like = uiout->is_mi_like_p ();

> 

> This could be removed by having a more explicit API.


I'm sorry, I'm not sure what do you mean here. 

> 

> Jan> +    ui_out_emit_list completions_emitter (uiout, "completions");

> Jan> +    if (result.number_matches != 0)

> Jan> +      {

> Jan> +        if (result.number_matches == 1)

> Jan> +          {

> Jan> +	    if (is_mi_like)

> Jan> +	      uiout->field_fmt(NULL, "%s%s", arg_prefix.c_str (),

> Jan> +                                             result.match_list[0]);

> Jan> +	    else

> Jan> +	      printf_unfiltered ("%s%s\n", arg_prefix.c_str (),

> Jan> +                                           result.match_list[0]);

> 

> Space before "(" in the field_fmt call.  Unifying the cases would be

> preferable.  Or another argument for separation.

> 


Thanks! 
Jan

Patch

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 08c7c6c1f4..322b539417 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,12 @@ 
+2019-01-03  Jan Vrany  <jan.vrany@fit.cvut.cz>
+
+	* cli/cli-cmds.h: Export complete_command.
+	* cli/cli-cmds.c (complete_command): Update to print completions
+	on MI channel if requested.
+	* mi/mi-cmds.c: Define new -complete command implemented using
+	it CLI command 'complete'.
+	* NEWS: Mention new -complete command.
+
 2018-12-17  Andrew Burgess  <andrew.burgess@embecosm.com>
 
 	* dwarf2read.c (struct dwarf2_cu): Convert the fields 'mark',
diff --git a/gdb/NEWS b/gdb/NEWS
index 913f3ae3b6..6b561af71f 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -96,6 +96,13 @@  maint show dwarf unwinders
 info proc files
   Display a list of open files for a process.
 
+* New MI commands
+
+-complete
+  This lists all the possible completions for the rest of the line, if it
+  were to be given as a command itself.  This is intended for use by MI frontends
+  in cases when separate CLI and MI channels cannot be used.
+
 * Changed commands
 
 target remote FILENAME
diff --git a/gdb/cli/cli-cmds.c b/gdb/cli/cli-cmds.c
index 135f550b80..468f66dac6 100644
--- a/gdb/cli/cli-cmds.c
+++ b/gdb/cli/cli-cmds.c
@@ -223,16 +223,22 @@  help_command (const char *command, int from_tty)
 /* Note: The "complete" command is used by Emacs to implement completion.
    [Is that why this function writes output with *_unfiltered?]  */
 
-static void
+void
 complete_command (const char *arg, int from_tty)
 {
+  struct ui_out *uiout = current_uiout;
+  bool is_mi_like = uiout->is_mi_like_p ();
+
   dont_repeat ();
 
   if (max_completions == 0)
     {
-      /* Only print this for non-mi frontends.  An MI frontend may not
-	 be able to handle this.  */
-      if (!current_uiout->is_mi_like_p ())
+      if (is_mi_like)
+        {
+          error (_("max-completions is zero,"
+		   " completion is disabled.\n"));
+        }
+      else
 	{
 	  printf_unfiltered (_("max-completions is zero,"
 			       " completion is disabled.\n"));
@@ -278,34 +284,61 @@  complete_command (const char *arg, int from_tty)
   completion_result result
     = tracker->build_completion_result (word, word - arg, strlen (arg));
 
-  if (result.number_matches != 0)
-    {
-      if (result.number_matches == 1)
-	printf_unfiltered ("%s%s\n", arg_prefix.c_str (), result.match_list[0]);
-      else
-	{
-	  result.sort_match_list ();
-
-	  for (size_t i = 0; i < result.number_matches; i++)
-	    {
-	      printf_unfiltered ("%s%s",
-				 arg_prefix.c_str (),
-				 result.match_list[i + 1]);
-	      if (quote_char)
-		printf_unfiltered ("%c", quote_char);
-	      printf_unfiltered ("\n");
-	    }
-	}
-
-      if (result.number_matches == max_completions)
-	{
-	  /* ARG_PREFIX and WORD are included in the output so that emacs
-	     will include the message in the output.  */
-	  printf_unfiltered (_("%s%s %s\n"),
-			     arg_prefix.c_str (), word,
-			     get_max_completions_reached_message ());
-	}
+  {
+    ui_out_emit_list completions_emitter (uiout, "completions");
+    if (result.number_matches != 0)
+      {
+        if (result.number_matches == 1)
+          {
+	    if (is_mi_like)
+	      uiout->field_fmt(NULL, "%s%s", arg_prefix.c_str (),
+                                             result.match_list[0]);
+	    else
+	      printf_unfiltered ("%s%s\n", arg_prefix.c_str (),
+                                           result.match_list[0]);
+          }
+        else
+	  {
+	    result.sort_match_list ();
+
+	    for (size_t i = 0; i < result.number_matches; i++)
+	      {
+                if (is_mi_like)
+	          {
+	            uiout->field_fmt(NULL, "%s%s", arg_prefix.c_str (),
+                                                   result.match_list[i + 1]);
+	          }
+	        else
+	          {
+		    printf_unfiltered ("%s%s", arg_prefix.c_str (),
+                                               result.match_list[i + 1]);
+		    if (quote_char)
+		      printf_unfiltered ("%c", quote_char);
+		    printf_unfiltered ("\n");
+	          }
+	      }
+	  }
+      }
     }
+
+    if (result.number_matches == max_completions)
+      {
+	if (is_mi_like)
+	  uiout->field_string("max_completions_reached", "1");
+	else
+	  {
+	    /* ARG_PREFIX and WORD are included in the output so that emacs
+	       will include the message in the output.  */
+	    printf_unfiltered (_("%s%s %s\n"),
+				 arg_prefix.c_str (), word,
+				 get_max_completions_reached_message ());
+	  }
+      }
+    else
+      {
+	if (is_mi_like)
+	  uiout->field_string("max_completions_reached", "0");
+      }
 }
 
 int
diff --git a/gdb/cli/cli-cmds.h b/gdb/cli/cli-cmds.h
index 3fa188dba6..bcd12c0c0b 100644
--- a/gdb/cli/cli-cmds.h
+++ b/gdb/cli/cli-cmds.h
@@ -106,6 +106,10 @@  void init_cmd_lists (void);
 
 void init_cli_cmds (void);
 
+/* Exported to gdb/mi/mi-cmds.c */
+
+void complete_command (const char *, int);
+
 int is_complete_command (struct cmd_list_element *cmd);
 
 /* Exported to gdb/main.c */
diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog
index 68d3068c72..da81f6a6c1 100644
--- a/gdb/doc/ChangeLog
+++ b/gdb/doc/ChangeLog
@@ -1,3 +1,8 @@ 
+2019-01-03  Jan Vrany  <jan.vrany@fit.cvut.cz>
+
+	* gdb.texinfo (Miscellaneous GDB/MI Commands): Document new
+	MI command -complete.
+
 2018-12-13  John Baldwin  <jhb@FreeBSD.org>
 
 	* gdb.texinfo (Set Catchpoints): Add an anchor for 'catch syscall'.
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index d766e44e63..7f88273145 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -34236,6 +34236,38 @@  fullname="/home/nickrob/myprog.c",line="73",arch="i386:x86_64"@}
 (gdb)
 @end smallexample
 
+@subheading The @code{-complete} Command
+@findex -complete
+
+@subheading Synopsis
+
+@smallexample
+-complete @var{command}
+@end smallexample
+
+Show a list of completions for partially typed CLI @var{command}. The
+@var{command} should be given in verbatim without any quoting / escaping.
+
+This command is intended for @sc{gdb/mi} frontends that cannot use two separate
+CLI and MI channels - for example: because of lack of PTYs like on Windows or
+because @sc{gdb} is used remotely via a SSH connection.
+
+@subheading @value{GDBN} Command
+
+The corresponding @value{GDBN} command is @samp{complete}.
+
+@subheading Example
+
+@smallexample
+(gdb)
+-complete br
+^done,completions=["break","break-range"],max_completions_reached="0"
+(gdb)
+-complete b madv
+^done,completions=["b madvise"],max_completions_reached="0"
+(gdb)
+@end smallexample
+
 @node Annotations
 @chapter @value{GDBN} Annotations
 
diff --git a/gdb/mi/mi-cmds.c b/gdb/mi/mi-cmds.c
index 51014eded2..7b510f71d4 100644
--- a/gdb/mi/mi-cmds.c
+++ b/gdb/mi/mi-cmds.c
@@ -20,9 +20,11 @@ 
 
 #include "defs.h"
 #include "top.h"
+#include "cli/cli-cmds.h"
 #include "mi-cmds.h"
 #include "mi-main.h"
 
+
 struct mi_cmd;
 static struct mi_cmd **lookup_table (const char *command);
 static void build_table (struct mi_cmd *commands);
@@ -75,6 +77,7 @@  static struct mi_cmd mi_cmds[] =
                    &mi_suppress_notification.breakpoint),
   DEF_MI_CMD_MI_1 ("catch-unload", mi_cmd_catch_unload,
                    &mi_suppress_notification.breakpoint),
+  DEF_MI_CMD_CLI ("complete", "complete", 1),
   DEF_MI_CMD_MI ("data-disassemble", mi_cmd_disassemble),
   DEF_MI_CMD_MI ("data-evaluate-expression", mi_cmd_data_evaluate_expression),
   DEF_MI_CMD_MI ("data-list-changed-registers",
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index ab3a74fffd..40da71b2c5 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,3 +1,7 @@ 
+2019-01-03  Jan Vrany  <jan.vrany@fit.cvut.cz>
+
+	* gdb.mi/mi-complete.exp: New file.
+
 2018-12-12  Andrew Burgess  <andrew.burgess@embecosm.com>
 
 	* gdb.base/annota1.exp: Update a test regexp.
diff --git a/gdb/testsuite/gdb.mi/mi-complete.exp b/gdb/testsuite/gdb.mi/mi-complete.exp
new file mode 100644
index 0000000000..14c763a966
--- /dev/null
+++ b/gdb/testsuite/gdb.mi/mi-complete.exp
@@ -0,0 +1,71 @@ 
+# Copyright 2018 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# Verify -data-evaluate-expression. There are really minimal tests.
+
+# The goal is not to test gdb functionality, which is done by other tests,
+# but to verify the correct output response to MI operations.
+#
+
+load_lib mi-support.exp
+set MIFLAGS "-i=mi"
+
+gdb_exit
+if [mi_gdb_start] {
+    continue
+}
+
+standard_testfile basics.c
+
+if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
+     untested "failed to compile"
+     return -1
+}
+
+mi_run_to_main
+
+mi_gdb_test "1-complete br" \
+            "1\\^done,completions=\\\[.*\"break\",.*\"break-range\".*\\\],max_completions_reached=\"0\"" \
+            "-complete br"
+
+# Check empty completion list
+mi_gdb_test "5-complete bogus" \
+            "5\\^done,completions=\\\[\\\],max_completions_reached=\"0\"" \
+            "-complete bogus"
+
+
+# Check completions for commands with space
+mi_gdb_test "4-complete b mai" \
+            "4\\^done,completions=\\\[.*\"b main\".*\\\],max_completions_reached=\"0\"" \
+            "-complete b mai"
+
+mi_gdb_test "-info-gdb-mi-command complete" \
+            "\\^done,command=\{exists=\"true\"\}" \
+            "-info-gdb-mi-command complete"
+
+# Limit max completions and check that max_completions_reached=\"0\" is set
+# to 1.
+send_gdb "set max-completions 1\n"
+
+mi_gdb_test "2-complete br" \
+            ".*2\\^done,completions=\\\[\"br\[A-Za-z0-9-\]+\"\\\],max_completions_reached=\"1\"" \
+            "-complete br (max-completions 1)"
+
+# Disable completions and check an error is returned
+send_gdb "set max-completions 0\n"
+
+mi_gdb_test "3-complete br" \
+            ".*3\\^error,msg=\".*" \
+            "-complete br (max-completions 1)"