[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