[m-rev.] split-screen source linking

Mark Brown dougl at cs.mu.OZ.AU
Fri Nov 2 17:36:33 AEDT 2001


This is for review by Ralph.

Cheers,
Mark.

Estimated hours taken: 3
Branches: main

Implement a split-screen version of source linking for mdb.  The upper
window shows what would normally be shown in the full window.  This
includes displaying the parent context at interface events.  The lower
window shows the current context (the callee) at interface events.

Split screen mode is enabled with the '-2' or '--split-screen' options
to 'view'.

trace/mercury_trace_source.h:
	Add a 'split' field to the struct which holds server info.

trace/mercury_trace_source.c:
	Handle split screen mode when opening a server and when
	synchronising.

	Factor out some common code into MR_trace_source_jump().

	Close the server with ":qall" instead of ":q".

	Repair an earlier oversight: pass the verbose flag in a call
	to MR_trace_source_check_server().

trace/mercury_trace_internal.c:
	Parse the new option and pass its value around where required.

	Set the split field in the server info before starting a
	new server.

	When synchronising, pass both parent and current contexts
	(if available).

doc/user_guide.texi:
	Document the new option.

Index: doc/user_guide.texi
===================================================================
RCS file: /home/mercury1/repository/mercury/doc/user_guide.texi,v
retrieving revision 1.275
diff -u -r1.275 user_guide.texi
--- doc/user_guide.texi	31 Oct 2001 17:53:26 -0000	1.275
+++ doc/user_guide.texi	1 Nov 2001 21:27:25 -0000
@@ -2385,7 +2385,7 @@
 In the case that the format itself is being set,
 these options are ignored.
 @sp 1
- at item view [-v] [-f] [-w @var{window-cmd}] [-s @var{server-cmd}] [-n @var{server-name}] [-t @var{timeout}]
+ at item view [-vf2] [-w @var{window-cmd}] [-s @var{server-cmd}] [-n @var{server-name}] [-t @var{timeout}]
 @itemx view -c [-v] [-s @var{server-cmd}] [-n @var{server-name}]
 @kindex view (mdb command)
 Opens a new window displaying the source code,
@@ -2413,6 +2413,11 @@
 The option @samp{-f} (or @samp{--force})
 stops the command from aborting if there is already a window open.
 Instead it attempts to close that window first.
+ at sp 1
+The option @samp{-2} (or @samp{--split-screen})
+starts the vim server with two windows.
+This allows both the callee as well as the caller
+to be displayed at interface events.
 @sp 1
 The option @samp{-w} (or @samp{--window-command}) specifies
 the command to open a new window.
Index: trace/mercury_trace_internal.c
===================================================================
RCS file: /home/mercury1/repository/mercury/trace/mercury_trace_internal.c,v
retrieving revision 1.107
diff -u -r1.107 mercury_trace_internal.c
--- trace/mercury_trace_internal.c	31 Oct 2001 17:53:51 -0000	1.107
+++ trace/mercury_trace_internal.c	1 Nov 2001 21:27:25 -0000
@@ -186,7 +186,7 @@
 static	bool	MR_parse_source_locn(char *word, const char **file, int *line);
 static	const char *MR_trace_new_source_window(const char *window_cmd,
 			const char *server_cmd, const char *server_name,
-			int timeout, bool force, bool verbose);
+			int timeout, bool force, bool verbose, bool split);
 static	void	MR_trace_maybe_sync_source_window(MR_Event_Info *event_info,
 			bool verbose);
 static	void	MR_trace_maybe_close_source_window(bool verbose);
@@ -220,9 +220,9 @@
 			const char *item);
 static	bool	MR_trace_options_view(const char **window_cmd,
 			const char **server_cmd, const char **server_name,
-			int *timeout, bool *force, bool *verbose, bool *close,
-			char ***words, int *word_count, const char *cat,
-			const char*item);
+			int *timeout, bool *force, bool *verbose, bool *split,
+			bool *close, char ***words, int *word_count,
+			const char *cat, const char*item);
 static	void	MR_trace_usage(const char *cat, const char *item);
 static	void	MR_trace_do_noop(void);
 
@@ -1160,13 +1160,14 @@
 		int			timeout = 8;	/* seconds */
 		bool			force = FALSE;
 		bool			verbose = FALSE;
+		bool			split = FALSE;
 		bool			close = FALSE;
 		const char		*msg;
 
 		if (! MR_trace_options_view(&window_cmd, &server_cmd,
 				&server_name, &timeout, &force, &verbose,
-				&close, &words, &word_count, "browsing",
-				"view"))
+				&split, &close, &words, &word_count,
+				"browsing", "view"))
 		{
 			; /* the usage message has already been printed */
 		} else if (word_count != 1) {
@@ -1176,7 +1177,7 @@
 		} else {
 			msg = MR_trace_new_source_window(window_cmd,
 					server_cmd, server_name, timeout,
-					force, verbose);
+					force, verbose, split);
 			if (msg != NULL) {
 				fflush(MR_mdb_out);
 				fprintf(MR_mdb_err, "mdb: %s.\n", msg);
@@ -2387,7 +2388,8 @@
 */
 static const char *
 MR_trace_new_source_window(const char *window_cmd, const char *server_cmd,
-		const char *server_name, int timeout, bool force, bool verbose)
+		const char *server_name, int timeout, bool force, bool verbose,
+		bool split)
 {
 	const char	*msg;
 
@@ -2402,6 +2404,7 @@
 		}
 	}
 
+	MR_trace_source_server.split = split;
 	if (server_cmd != NULL) {
 		MR_trace_source_server.server_cmd = MR_copy_string(server_cmd);
 	} else {
@@ -2444,6 +2447,8 @@
 	const MR_Label_Layout	*parent;
 	const char		*filename;
 	int			lineno;
+	const char		*parent_filename;
+	int			parent_lineno;
 	const char		*problem; /* not used */
 	MR_Word			*base_sp, *base_curfr;
 	const char		*msg;
@@ -2451,10 +2456,13 @@
 	if (MR_trace_source_server.server_name != NULL) {
 		lineno = 0;
 		filename = "";
+		parent_lineno = 0;
+		parent_filename = "";
 
 		/*
-		** At interface ports we use the parent context if we can.
-		** Otherwise, we use the current context.
+		** At interface ports we send both the parent context and
+		** the current context.  Otherwise, we just send the current
+		** context.
 		*/
 		if (MR_port_is_interface(event_info->MR_trace_port)) {
 			base_sp = MR_saved_sp(event_info->MR_saved_regs);
@@ -2462,8 +2470,8 @@
 			parent = MR_find_nth_ancestor(event_info->MR_event_sll,
 				1, &base_sp, &base_curfr, &problem);
 			if (parent != NULL) {
-				(void) MR_find_context(parent, &filename,
-					&lineno);
+				(void) MR_find_context(parent,
+					&parent_filename, &parent_lineno);
 			}
 		}
 
@@ -2473,7 +2481,8 @@
 		}
 
 		msg = MR_trace_source_sync(&MR_trace_source_server, filename,
-				lineno, verbose);
+				lineno, parent_filename, parent_lineno,
+				verbose);
 		if (msg != NULL) {
 			fflush(MR_mdb_out);
 			fprintf(MR_mdb_err, "mdb: %s.\n", msg);
@@ -2964,25 +2973,26 @@
 	{ "timeout",		MR_required_argument,	NULL,	't' },
 	{ "force",		MR_no_argument,		NULL,	'f' },
 	{ "verbose",		MR_no_argument,		NULL,	'v' },
+	{ "split-screen",	MR_no_argument,		NULL,	'2' },
 	{ NULL,			MR_no_argument,		NULL,	0 }
 };
 
 static bool
 MR_trace_options_view(const char **window_cmd, const char **server_cmd,
 		const char **server_name, int *timeout, bool *force,
-		bool *verbose, bool *close, char ***words, int *word_count,
-		const char *cat, const char *item)
+		bool *verbose, bool *split, bool *close, char ***words,
+		int *word_count, const char *cat, const char *item)
 {
 	int	c;
 	bool	no_close = FALSE;
 
 	MR_optind = 0;
-	while ((c = MR_getopt_long(*word_count, *words, "cw:s:n:t:fv",
+	while ((c = MR_getopt_long(*word_count, *words, "cw:s:n:t:fv2",
 			MR_trace_view_opts, NULL)) != EOF)
 	{
 		/*
 		** Option '-c' is mutually incompatible with '-f', '-t',
-		** '-s', '-n' and '-w'.
+		** '-s', '-n', '-w' and '-2'.
 		*/
 		switch (c) {
 
@@ -3042,6 +3052,15 @@
 
 			case 'v':
 				*verbose = TRUE;
+				break;
+
+			case '2':
+				if (*close) {
+					MR_trace_usage(cat, item);
+					return FALSE;
+				}
+				*split = TRUE;
+				no_close = TRUE;
 				break;
 
 			default:
Index: trace/mercury_trace_source.c
===================================================================
RCS file: /home/mercury1/repository/mercury/trace/mercury_trace_source.c,v
retrieving revision 1.3
diff -u -r1.3 mercury_trace_source.c
--- trace/mercury_trace_source.c	1 Nov 2001 20:31:26 -0000	1.3
+++ trace/mercury_trace_source.c	2 Nov 2001 06:32:45 -0000
@@ -80,6 +80,15 @@
 		const char *server_name, bool verbose);
 
 /*
+** Tell the server to jump to the given file and line.  If the server has
+** multiple windows open, use the current window.  If successful, returns
+** NULL, otherwise returns an error message.
+*/
+static const char *MR_trace_source_jump(const char *server_cmd,
+		const char *server_name, const char *filename, int lineno,
+		bool verbose);
+
+/*
 ** Send the given key sequence to the vim server.  Returns the status
 ** code of the shell command.
 */
@@ -172,6 +181,7 @@
 	** 2) check that server is valid;
 	** 3) start a server with a unique name;
 	** 4) wait until the server is found;
+	** 5) (if required) split the window.
 	*/
 
 	msg = MR_trace_source_check_display();
@@ -264,9 +274,21 @@
 		*/
 		MR_free(server->server_name);
 		server->server_name = NULL;
+		return msg;
 	}
 
-	return msg;
+	if (server->split) {
+		/* Split the window with "^Ws". */
+		status = MR_trace_source_send(real_server_cmd,
+				server->server_name,
+				MR_SOURCE_SERVER_RESET_STRING "\027s", FALSE);
+		if (status != 0) {
+			server->split = FALSE;
+			return "warning: unable to split source window";
+		}
+	}
+
+	return NULL;
 }
 
 const char *
@@ -307,12 +329,22 @@
 
 const char *
 MR_trace_source_sync(MR_Trace_Source_Server *server, const char *filename,
-		int lineno, bool verbose)
+		int lineno, const char *parent_filename, int parent_lineno,
+		bool verbose)
 {
 	const char	*real_server_cmd;
 	const char	*msg;
-	char		system_call[MR_SYSCALL_BUFFER_SIZE];
 	int		status;
+	bool		have_parent;
+	bool		have_current;
+
+	have_parent = strdiff(parent_filename, "") && parent_lineno != 0;
+	have_current = strdiff(filename, "") && lineno != 0;
+
+	if (!have_parent && !have_current) {
+		/* No point continuing. */
+		return NULL;
+	}
 
 	if (server->server_cmd != NULL) {
 		real_server_cmd = server->server_cmd;
@@ -321,17 +353,102 @@
 	}
 
 	msg = MR_trace_source_check_server(real_server_cmd,
-			server->server_name, FALSE);
+			server->server_name, verbose);
 	if (msg != NULL) {
 		return msg;
 	}
 
+	if (server->split) {
+		/*
+		** When in split mode, we use the bottom two windows on
+		** the vim server.  The window second from bottom (which
+		** will usually be the top window) displays what would be
+		** shown in non-split mode.
+		**
+		** If there is no parent context (e.g. at internal events)
+		** we leave the bottom window alone.
+		**
+		** If we have a parent context it will be displayed in the
+		** window second from bottom.  So in this case we show the
+		** current context in the bottom window.
+		*/
+
+		if (have_parent && have_current) {
+			/* Move to the bottom window with "^Wb". */
+			status = MR_trace_source_send(real_server_cmd,
+					server->server_name,
+					MR_SOURCE_SERVER_RESET_STRING "\027b",
+					FALSE);
+			if (status != 0) {
+				return "warning: source synchronisation failed";
+			}
+
+			msg = MR_trace_source_jump(real_server_cmd,
+					server->server_name, filename, lineno,
+					verbose);
+			if (msg != NULL) {
+				return msg;
+			}
+
+			/* Move up one window with "^Wk". */
+			status = MR_trace_source_send(real_server_cmd,
+					server->server_name,
+					MR_SOURCE_SERVER_RESET_STRING "\027k",
+					FALSE);
+			if (status != 0) {
+				return "warning: source synchronisation failed";
+			}
+		} else {
+			/*
+			** Move to the second from bottom window with
+			** "^Wb^Wk".
+			*/
+			status = MR_trace_source_send(real_server_cmd,
+					server->server_name,
+					MR_SOURCE_SERVER_RESET_STRING
+					"\027b\027k", FALSE);
+			if (status != 0) {
+				return "warning: source synchronisation failed";
+			}
+		}
+	}
+
+	/*
+	** We show the parent context if we can, since if both are present
+	** the parent context is usually more interesting.  Otherwise we
+	** show the current context.
+	*/
+	if (have_parent) {
+		msg = MR_trace_source_jump(real_server_cmd,
+				server->server_name, parent_filename,
+				parent_lineno, verbose);
+		if (msg != NULL) {
+			return msg;
+		}
+	} else {
+		msg = MR_trace_source_jump(real_server_cmd,
+				server->server_name, filename, lineno,
+				verbose);
+		if (msg != NULL) {
+			return msg;
+		}
+	}
+
+	return NULL;
+}
+
+static const char *
+MR_trace_source_jump(const char *server_cmd, const char *server_name,
+		const char *filename, int lineno, bool verbose)
+{
+	char		system_call[MR_SYSCALL_BUFFER_SIZE];
+	int		status;
+
 	/*
 	** Point the source server to the given context.
 	*/
 	sprintf(system_call, "%s --servername \"%s\" --remote '+%d' %s",
-			real_server_cmd, server->server_name, lineno,
-			filename);
+			server_cmd, server_name, lineno, filename);
 	status = MR_verbose_system_call(system_call, verbose);
 	if (status != 0) {
 		return "warning: source synchronisation failed";
@@ -345,7 +462,7 @@
 	** Avoid echoing the command even if --verbose is set, because
 	** the control characters may interfere with the terminal.
 	*/
-	status = MR_trace_source_send(real_server_cmd, server->server_name,
+	status = MR_trace_source_send(server_cmd, server_name,
 			MR_SOURCE_SERVER_RESET_STRING "z.", FALSE);
 	if (status != 0) {
 		return "warning: source synchronisation failed";
@@ -374,15 +491,15 @@
 
 	/*
 	** We first send "Ctrl-\ Ctrl-N", which guarantees we get back to
-	** "normal" mode without beeping, followed by ":q\n" which should
-	** quit.  This won't quit if the user has modified the file, which
-	** is just as well.
+	** "normal" mode without beeping, followed by ":qall\n" which should
+	** quit all windows.  This won't quit if the user has modified any
+	** file, which is just as well.
 	**
 	** Avoid echoing the command even if --verbose is set, because
 	** the control characters may interfere with the terminal.
 	*/
 	MR_trace_source_send(real_server_cmd, server->server_name,
-			MR_SOURCE_SERVER_RESET_STRING ":q\n", FALSE);
+			MR_SOURCE_SERVER_RESET_STRING ":qall\n", FALSE);
 
 #if 0
 	/*
Index: trace/mercury_trace_source.h
===================================================================
RCS file: /home/mercury1/repository/mercury/trace/mercury_trace_source.h,v
retrieving revision 1.2
diff -u -r1.2 mercury_trace_source.h
--- trace/mercury_trace_source.h	2 Nov 2001 06:25:56 -0000	1.2
+++ trace/mercury_trace_source.h	2 Nov 2001 06:31:54 -0000
@@ -28,10 +28,13 @@
 ** 			is no server.
 ** 	server_cmd	Command to run to start the server, or connect
 ** 			to it, or NULL if to use the default of "vim".
+**	split		Is the server in split screen mode?  If so, we
+**			show both the parent and current contexts.
 */
 typedef struct {
 	char		*server_name;
 	char		*server_cmd;
+	bool		split;
 } MR_Trace_Source_Server;
 
 /*
@@ -72,7 +75,8 @@
 ** problems.
 */
 const char *MR_trace_source_sync(MR_Trace_Source_Server *server,
-		const char *filename, int lineno, bool verbose);
+		const char *filename, int lineno, const char *parent_filename,
+		int parent_lineno, bool verbose);
 
 /*
 ** Close a server if possible.  If the server appears to be still
--------------------------------------------------------------------------
mercury-reviews mailing list
post:  mercury-reviews at cs.mu.oz.au
administrative address: owner-mercury-reviews at cs.mu.oz.au
unsubscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: unsubscribe
subscribe:   Address: mercury-reviews-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------



More information about the reviews mailing list