mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-16 14:25:56 +00:00
Estimated hours taken: 30 Modified files -------------- samples/diff/Mmakefile: Minor documentation update. samples/diff/README: samples/diff/TODO: Update stuff that's now done, do a couple of minor wording changes. samples/diff/diff.m: Fix case of identical filenames (which implicitly assumed no_diff_implies_no_output). Add new match pass, call the new diff algorithm. samples/diff/diff_out.m: Add --cvs-merge-conflict output style. Slight reorganisation of top-level predicate. Lots of small fixes to use better syntax (e.g. functional style for integer maths operations). samples/diff/difftype.m: Added first_mentioned_positions/3, last_mentioned_positions/3, add_edit/4. samples/diff/file.m: Use io__read_line_as_string. samples/diff/filter.m: Minor syntax/wording changes. samples/diff/options.m: Update all the newly handled options. New files --------- samples/diff/myers.m: New diff algorithm. samples/diff/match.m: New pass to match common lines in the files to be diffed. Removed file ------------ samples/diff/lcss.m: Functionality replaced by myers.m.
151 lines
4.8 KiB
Mathematica
151 lines
4.8 KiB
Mathematica
%-----------------------------------------------------------------------------%
|
|
% Copyright (C) 1995-1998 The University of Melbourne.
|
|
% This file may only be copied under the terms of the GNU General
|
|
% Public License - see the file COPYING in the Mercury distribution.
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
% Main authors: bromage, Marnix Klooster <marnix@worldonline.nl>
|
|
|
|
% Something very similar to the standard diff utility. Sort of. :-)
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- module diff.
|
|
|
|
:- interface.
|
|
:- import_module io.
|
|
|
|
:- pred main(io__state :: di, io__state :: uo) is det.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- implementation.
|
|
:- import_module options, myers, diff_out, globals, filter, match.
|
|
:- import_module string, list, file, std_util, require, getopt.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
% main: top-level predicate.
|
|
main -->
|
|
io__command_line_arguments(Args0),
|
|
{ options__get_option_ops(OptionOps) },
|
|
{ getopt__process_options(OptionOps, Args0, Args, Result0) },
|
|
postprocess_options(Result0, Result),
|
|
( { Result = yes(Msg) },
|
|
usage_error(Msg)
|
|
; { Result = no },
|
|
globals__io_get_output_style(OutputStyle),
|
|
( { OutputStyle = help_only } ->
|
|
usage
|
|
; { OutputStyle = version_only } ->
|
|
version
|
|
;
|
|
main_2(Args)
|
|
)
|
|
).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- pred usage_error(string :: in, io__state :: di, io__state :: uo) is det.
|
|
usage_error(Msg) -->
|
|
io__progname_base("diff", ProgName),
|
|
io__stderr_stream(StdErr),
|
|
io__write_strings(StdErr, [ProgName, ": ", Msg, "\n"]),
|
|
io__set_exit_status(1),
|
|
usage.
|
|
|
|
:- pred usage_io_error(io__error, io__state, io__state).
|
|
:- mode usage_io_error(in, di, uo) is det.
|
|
usage_io_error(Error) -->
|
|
{ io__error_message(Error, Msg) },
|
|
usage_error(Msg).
|
|
|
|
:- pred usage(io__state :: di, io__state :: uo) is det.
|
|
usage -->
|
|
io__write_string("Usage: diff [options] from-file to-file\n\n"),
|
|
options_help.
|
|
|
|
:- pred version(io__state :: di, io__state :: uo) is det.
|
|
version -->
|
|
io__write_string("diff - Mercury diff version 0.4\n").
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
% main_2 analyses the command-line arguments which are not
|
|
% options and calls diff__do_diff.
|
|
:- pred main_2(list(string), io__state, io__state).
|
|
:- mode main_2(in, di, uo) is det.
|
|
main_2([]) -->
|
|
usage_error("missing operand").
|
|
main_2([Fname1 | Rest]) -->
|
|
( { Rest = [Fname2 | _] },
|
|
( { Fname1 = Fname2 } ->
|
|
% Not sure why anyone would want to diff two
|
|
% files with the same name, but just in case...
|
|
( { Fname1 = "-" } ->
|
|
file__read_input(Fname1, Contents1),
|
|
{ Contents1 = Contents2 }
|
|
;
|
|
file__read_file(Fname1, Contents1),
|
|
{ Contents1 = Contents2 }
|
|
)
|
|
;
|
|
% If either file is "-", simply use standard input.
|
|
% (Note: Both can't be "-" since that was dealt with
|
|
% in the previous case.)
|
|
( { Fname1 = "-" } ->
|
|
file__read_input(Fname1, Contents1),
|
|
file__read_file(Fname2, Contents2)
|
|
; { Fname2 = "-" } ->
|
|
file__read_file(Fname1, Contents1),
|
|
file__read_input(Fname2, Contents2)
|
|
;
|
|
% Otherwise read the files normally.
|
|
file__read_file(Fname1, Contents1),
|
|
file__read_file(Fname2, Contents2)
|
|
)
|
|
),
|
|
% Now do the diff.
|
|
( { Contents1 = ok(File1), Contents2 = ok(File2) } ->
|
|
diff__do_diff(File1, File2)
|
|
; { Contents1 = error(Msg) } ->
|
|
usage_io_error(Msg)
|
|
; { Contents2 = error(Msg) } ->
|
|
usage_io_error(Msg)
|
|
;
|
|
{ error("main2") }
|
|
)
|
|
; { Rest = [] },
|
|
usage_error("missing operand")
|
|
).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
% diff__do_diff takes the files plus all the command
|
|
% line options and determines what to do with them.
|
|
%
|
|
% At the moment, we're organised into four passes:
|
|
%
|
|
% - build_matches determines which lines from the
|
|
% input files match (using the appropriate command-
|
|
% line options).
|
|
% - diff_by_myers takes the matches produced and
|
|
% computes a diff between them.
|
|
% - filter_diff analyses the diff, filtering out
|
|
% any edits which the user said that they didn't
|
|
% want to see (using the appropriate command-line
|
|
% options).
|
|
% - display_diff outputs the diff in whatever output
|
|
% format the user chose.
|
|
%
|
|
:- pred diff__do_diff(file, file, io__state, io__state).
|
|
:- mode diff__do_diff(in, in, di, uo) is det.
|
|
diff__do_diff(File1, File2) -->
|
|
build_matches(File1, File2, FileX, FileY),
|
|
diff_by_myers(FileX, FileY, Diff0),
|
|
filter_diff(Diff0, File1, File2, Diff),
|
|
display_diff(File1, File2, Diff).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
%-----------------------------------------------------------------------------%
|