mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-18 15:26:31 +00:00
Estimated hours taken: 30 Modified files -------------- samples/diff/README: Info about this new version. Put the existing READMEs in reverse order, so that they'll be in the most sensible order for someone reading top-down. samples/diff/Mmakefile: Supply more detail about which bit of this program GCC 2.7.2 under Digital Unix 3.2 doesn't compile properly. samples/diff/diff.m: Slight reorganisation. Accept options, remove some high coupling betweem diff__do_diff and lcss.m. samples/diff/file.m: Add support for attaching a filename to a file. samples/diff/lcss.m: Add more documentation, one slight performance improvement. lcss__to_diff now works on the reversed LCSS, to avoid going to the trouble of reversing it. New files --------- samples/diff/TODO: Meaning should be obvious. samples/diff/diff_out.m: Replacement for diffs.m (which was never a very good name). Now contains code to display a diff in lots more output styles than previously supported. samples/diff/difftype.m: Replacement for lcsstype.m. Contains the type of a diff (but not of an lcss, which is now local to lcss.m, hence the renaming). samples/diff/filter.m: Contains code to filter a diff before being displayed. This is only required if the user specified that they didn't want to see part of the diff (e.g. with --ignore-blank-lines). samples/diff/globals.m: samples/diff/options.m: Support for option handling. Removed files ------------- samples/diff/diffs.m: Functionality moved to diff_out.m. samples/diff/lcsstype.m: Functionality moved to difftype.m.
148 lines
4.8 KiB
Mathematica
148 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 author: bromage
|
|
% Simplified by 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, lcss, diff_out, globals, filter.
|
|
:- 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 } ->
|
|
% There are no differences between identical files.
|
|
[]
|
|
;
|
|
% 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 three passes:
|
|
%
|
|
% - diff_by_lcss takes the two files and produces
|
|
% a diff using the LCSS algorithm.
|
|
% - 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.
|
|
%
|
|
% TO DO: Options like --ignore-case are probably best handled
|
|
% by a pass taking place _before_ the diff algorithm is
|
|
% run. This pass would have the benefit of determining
|
|
% whether or not there are any differences or not, in
|
|
% the case where the output style chosen doesn't require
|
|
% output if there is no diff. It would also speed up
|
|
% the --brief output style.
|
|
:- 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) -->
|
|
{ diff_by_lcss(File1, File2, Diff0) },
|
|
filter_diff(Diff0, File1, File2, Diff),
|
|
display_diff(File1, File2, Diff).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
%-----------------------------------------------------------------------------%
|