1 % (c) 2009-2024 Lehrstuhl fuer Softwaretechnik und Programmiersprachen,
2 % Heinrich Heine Universitaet Duesseldorf
3 % This software is licenced under EPL 1.0 (http://www.eclipse.org/org/documents/epl-v10.html)
4
5 :- module(tools_commands,
6 [ edit_file/1,edit_file/2, diff_files_with_editor/2,
7 show_errors_with_bb_results/0, show_errors_with_bb_results/1, show_source_locations_with_bb_results/1,
8 gen_dot_output/4,
9 valid_dot_output_format/1,
10 get_dot_engine_options/2,
11 get_dot_default_engine_option/1,
12 show_pdf_file/1,
13 show_dot_file/1,
14 open_file/1]).
15
16
17 :- use_module(module_information).
18 :- module_info(group,infrastructure).
19 :- module_info(description,'A few utilities to call external programs/commands.').
20 :- use_module(preferences).
21 :- use_module(debug).
22 :- use_module(tools).
23 :- use_module(error_manager).
24 :- use_module(system_call,[system_call/4]).
25
26
27 edit_file(F) :- edit_file(F,none).
28 edit_file(FILE,LINE) :-
29 get_preference(path_to_text_editor_launch,EDITOR),
30 edit_file_with_editor(EDITOR,FILE,LINE).
31
32 edit_file_with_editor('',FILE,_LINE) :- !,
33 add_error(edit_file_with_editor,'No text editor set (be sure to set the ProB EDITOR preference), cannot edit: ',FILE).
34 edit_file_with_editor(EDITOR,FILE,LINE) :- number(LINE),
35 tools:get_tail_filename(EDITOR,EdName),
36 editor_understands_plus_line(EdName),!, % bbedit/vim can handle +LINE arg
37 format('Opening file "~w" at LINE ~w using EDITOR "~w"~n',[FILE,LINE,EDITOR]),
38 tools:string_concatenate('+',LINE,LinePosArg),
39 system_call(EDITOR,[LinePosArg,FILE],ErrorTextAsCodeList,ExitCode),
40 debug_println(9,exit(ExitCode,ErrorTextAsCodeList)).
41 edit_file_with_editor(EDITOR,FILE,LINE) :- number(LINE),
42 tools:get_tail_filename(EDITOR,atom),!, % atom can handle FILE:LINE
43 format('Opening file "~w" at LINE ~w using EDITOR "~w"~n',[FILE,LINE,EDITOR]),
44 ajoin([FILE,':',LINE],FILE_LINE),
45 system_call(EDITOR,[FILE_LINE],ErrorTextAsCodeList,ExitCode),
46 debug_println(9,exit(ExitCode,ErrorTextAsCodeList)).
47 edit_file_with_editor(EDITOR,FILE,_) :-
48 format('Opening file "~w" using EDITOR "~w"~n',[FILE,EDITOR]),
49 system_call(EDITOR,[FILE],ErrorTextAsCodeList,ExitCode),
50 debug_println(9,exit(ExitCode,ErrorTextAsCodeList)).
51
52
53 editor_understands_plus_line(bbedit).
54 editor_understands_plus_line(edit). % Text Wrangler
55 editor_understands_plus_line(vim).
56
57
58
59 diff_files_with_editor(FILE1,FILE2) :-
60 DIFFER = '/usr/local/bin/bbdiff', % TO DO: provide preference
61 system_call:system_call(DIFFER,[FILE1,FILE2],ErrorTextAsCodeList,ExitCode),
62 debug_println(9,exit(ExitCode,ErrorTextAsCodeList)).
63
64
65 :- use_module(library(process)).
66 :- use_module(system_call,[system_call_keep_open/7]).
67 show_errors_with_bb_results :- show_errors_with_bb_results([]).
68 show_errors_with_bb_results(Options) :-
69 stored_error(_,_,_,Span,Options),
70 extract_file_number_and_name(Span,_,_Filename),
71 extract_line_col(Span,_,_,_,_),
72 !,
73 Command = '/usr/local/bin/bbresults', % TO DO: put in preference
74 BBArgs = ['-p', 'flake8'], Env = [],
75 catch(
76 ( system_call_keep_open(Command,BBArgs,Process,STDIn,_STDOut,_STDErr,Env),
77 write_errors_for_bbresults(STDIn,Options),
78 close(STDIn),
79 process_release(Process)),
80 error(existence_error(_,_),E),
81 add_error(show_errors_with_bb_results,'Cannot start error viewer: ',Command:E)).
82 show_errors_with_bb_results(_). % no errors to show
83
84 stored_error(Source,S,TContext,Span,Options) :-
85 (member(current,Options) -> logged_error(Source,S,TContext,Span)
86 ; backed_up_error(Source,S,_TContext,Span)).
87
88 % ---------------------
89 % write errors in bbresults style (flake8)
90 % filename:line:column: W/E1 message
91
92 write_errors_for_bbresults(Stream,Options) :-
93 stored_error(Source,S,_TContext,Span,Options),
94 extract_file_number_and_name(Span,_,Filename),
95 extract_line_col(Span,SL,SC,_EL,_EC),
96 StartCol is SC+1,
97 (Source = warning(_) -> Type='W1' ; Type='E1'),
98 format(Stream,'~w:~w:~w: ~w ~w~n',[Filename,SL,StartCol,Type,S]),
99 %format(user_output,'~w:~w:~w: ~w ~w~n',[Filename,SL,SC,Type,S]),
100 fail.
101 write_errors_for_bbresults(_,_).
102
103 :- use_module(library(lists)).
104 % show a list of source locations
105 show_source_locations_with_bb_results(List) :-
106 Command = '/usr/local/bin/bbresults', % TO DO: put in preference
107 BBArgs = ['-p', 'flake8'], Env = [],
108 catch(
109 ( system_call_keep_open(Command,BBArgs,Process,STDIn,_STDOut,_STDErr,Env),
110 maplist(write_src_loc_msg_for_bbresults(STDIn),List),
111 close(STDIn),
112 process_release(Process)),
113 error(existence_error(_,_),E),
114 add_error(show_errors_with_bb_results,'Cannot start error viewer: ',Command:E)).
115
116 write_src_loc_msg_for_bbresults(Stream,src_loc_msg(S,Filename,SL,StartCol,_EndLine,_EndCol)) :-
117 format(Stream,'~w:~w:~w: ~w ~w~n',[Filename,SL,StartCol,'W1',S]).
118
119 % ------------------------------
120
121 % show pdf/ps file using Preview/open/gsview/okular/evince/...
122 show_pdf_file(FILE) :-
123 get_preference(path_to_ps_viewer,PSVIEWER),
124 system_call:system_call(PSVIEWER,[FILE],ErrorTextAsCodeList,ExitCode),
125 (ErrorTextAsCodeList=[] -> true
126 ; format('PS/PDF Viewer (~w) Error Result: ~s~nExit code:~w.~n',[PSVIEWER,ErrorTextAsCodeList,ExitCode]),
127 fail
128 ).
129
130 % show dot file using dotty
131 show_dot_file(FILE) :-
132 get_preference(path_to_dotty,DOTTY),
133 system_call:system_call(DOTTY,[FILE],ErrorTextAsCodeList,ExitCode),
134 (ErrorTextAsCodeList=[] -> true
135 ; format('Dot Viewer(~w) Error Result: ~s~nExit code:~w.~n',[DOTTY,ErrorTextAsCodeList,ExitCode]),
136 fail
137 ).
138
139 % show file using OS specific application
140 open_file(FILE) :-
141 try_get_program_path(open,OPENCMD),
142 system_call:system_call(OPENCMD,[FILE],ErrorTextAsCodeList,ExitCode), % cf open -a
143 (ErrorTextAsCodeList=[] -> true
144 ; format('Error Result for open: ~s~nExit code:~w.~n',[ErrorTextAsCodeList,ExitCode]),
145 fail
146 ).
147
148 % ------------------------------
149
150 % call dot or sfdp to generate a PDF/PNG/SVG file:
151 :- use_module(probsrc(system_call),[system_call/5]).
152 gen_dot_output(DOTFILE,DotType,OutputType,OutputFILE) :-
153 get_preference(path_to_dot,DOTCMD),
154 valid_dot_output_parameter(OutputType,Para),!,
155 absolute_file_name(OutputFILE,AOutFile),
156 format(user_output,'Calling dot: ~w to generate ~w from ~w~n',[DOTCMD,AOutFile,DOTFILE]),
157 get_dot_engine_options(DotType,DotOptions),
158 append([Para|DotOptions],['-o', AOutFile, DOTFILE],DotArgs),
159 system_call(DOTCMD, DotArgs,_TextOut,ErrorTextAsCodeList,_JExit),
160 (ErrorTextAsCodeList=[] -> true
161 ; format('Dot Error Result: ~s~n.',[ErrorTextAsCodeList]),
162 fail
163 ).
164
165 % useful for Tcl/Tk:
166 get_dot_default_engine_option(Option) :-
167 get_dot_engine_options(default,R),
168 (R=[Opt] -> Option=Opt ; Option = '-Kdot').
169
170 get_dot_engine_options(circo,R) :- !, R=['-Kcirco'].
171 get_dot_engine_options(dot,R) :- !, R=['-Kdot'].
172 get_dot_engine_options(fdp,R) :- !, R=['-Kfdp'].
173 get_dot_engine_options(neato,R) :- !, R=['-Kneato'].
174 get_dot_engine_options(nop,R) :- !, R=['-Knop'].
175 get_dot_engine_options(nop2,R) :- !, R=['-Knop2'].
176 get_dot_engine_options(osage,R) :- !, R=['-Kosage'].
177 get_dot_engine_options(patchwork,R) :- !, R=['-Kpatchwork'].
178 get_dot_engine_options(sfdp,R) :- !, R=['-Ksfdp'].
179 get_dot_engine_options(twopi,R) :- !, R=['-Ktwopi'].
180 get_dot_engine_options(default,R) :- !, get_preference(dot_default_engine,Eng),
181 (Eng=default -> R=[] ; get_dot_engine_options(Eng,R)).
182 get_dot_engine_options(OTHER,[]) :- add_error(get_dot_engine_options,'Unknown DOT Engine:',OTHER).
183
184 valid_dot_output_format2(pdf,'-Tpdf').
185 valid_dot_output_format2(png,'-Tpng').
186 valid_dot_output_format2(svg,'-Tsvg').
187 valid_dot_output_format2(dot,'-Tdot'). % dot with layout
188 valid_dot_output_format2(canon,'-Tcanon'). % dot without layout
189 valid_dot_output_format2(xdot,'-Txdot'). % dot with layout
190 % many more a supported: eps, xdot, canon, ...
191
192 valid_dot_output_parameter(Ext,Res) :- valid_dot_output_format2(Ext,Para),!,Res=Para.
193 valid_dot_output_parameter(T,_) :- add_internal_error('Illegal dot output type: ',T),fail.
194
195 valid_dot_output_format(Ext) :- valid_dot_output_format2(Ext,_).
196