1/* Part of SWI-Prolog 2 3 Author: Jan Wielemaker 4 E-mail: J.Wielemaker@vu.nl 5 WWW: http://www.swi-prolog.org 6 Copyright (c) 2011-2017, VU University Amsterdam 7 All rights reserved. 8 9 Redistribution and use in source and binary forms, with or without 10 modification, are permitted provided that the following conditions 11 are met: 12 13 1. Redistributions of source code must retain the above copyright 14 notice, this list of conditions and the following disclaimer. 15 16 2. Redistributions in binary form must reproduce the above copyright 17 notice, this list of conditions and the following disclaimer in 18 the documentation and/or other materials provided with the 19 distribution. 20 21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24 FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25 COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 27 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 31 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 POSSIBILITY OF SUCH DAMAGE. 33*/ 34 35:- module(prolog_history, 36 [ prolog_history/1 37 ]). 38:- use_module(library(base32)). 39 40:- multifile 41 prolog:history/2. 42 43/** <module> Per-directory persistent commandline history 44 45This module implements persistency of the commandline history over 46Prolog sessions on Prolog installations that are based on the GNU 47readline library (default for the development version on Unix systems). 48 49The history is stored in the directory =|~/.swipl-dir-history|=. For 50each directory for which it keeps the history, there is file whose name 51is the base32 encoding of the directory path. 52 53This file is normally loaded when Prolog is started if =user_input= is a 54terminal and the system supports history. 55*/ 56 57:- create_prolog_flag(save_history, true, [type(boolean)]). 58 59%! history_directory(-Dir) is semidet. 60% 61% Dir is the directory where the per-directory history databases 62% are stored. 63 64history_directory(Dir) :- 65 absolute_file_name(app_preferences('.swipl-dir-history'), 66 Dir, 67 [ access(write), 68 file_type(directory), 69 file_errors(fail) 70 ]), 71 !. 72history_directory(Dir) :- 73 absolute_file_name(app_preferences('.'), 74 Home, 75 [ access(write), 76 file_type(directory), 77 file_errors(fail) 78 ]), 79 atom_concat(Home, '/.swipl-dir-history', Dir), 80 ( exists_directory(Dir) 81 -> fail 82 ; make_directory(Dir) 83 ). 84 85%! dir_history_file(+Dir, -File) is det. 86%! dir_history_file(?Dir, ?File) is nondet. 87% 88% File is the history file for a Prolog session running in Dir. 89 90dir_history_file(Dir, File) :- 91 nonvar(Dir), 92 !, 93 history_directory(Base), 94 absolute_file_name(Dir, Path), 95 base32(Path, Encoded), 96 atomic_list_concat([Base, Encoded], /, File). 97dir_history_file(Dir, File) :- 98 history_directory(HDir), 99 directory_files(HDir, Files), 100 '$member'(Base32, Files), 101 base32(Dir, Base32), 102 !, 103 atomic_list_concat([Dir, Base32], /, File). 104 105write_history(File) :- 106 current_prolog_flag(save_history, true), 107 catch(prolog:history(user_input, save(File)), _, true), !. 108write_history(_). 109 110 111%! prolog_history(+Action) is det. 112% 113% Execute Action on the history. Action is one of 114% 115% * enable 116% Enable history. First loads history for the current directory. 117% Loading the history is done at most once. 118% * disable 119% Sets the Prolog flag =save_history= to =false=, such that the 120% history is not saved on halt. 121 122:- dynamic 123 history_loaded/1. 124 125load_dir_history(File) :- 126 ( exists_file(File), 127 prolog:history(user_input, load(File)) 128 -> assertz(history_loaded(File)) 129 ; true 130 ). 131 132prolog_history(enable) :- 133 history_loaded(_), 134 !. 135prolog_history(enable) :- 136 catch(dir_history_file('.', File), E, 137 (print_message(warning, E),fail)), 138 catch(load_dir_history(File), E, 139 print_message(warning, E)), 140 !, 141 at_halt(write_history(File)), 142 set_prolog_flag(save_history, true). 143prolog_history(_) :- 144 set_prolog_flag(save_history, false). 145 146 /******************************* 147 * SWIPL-WIN SUPPORT * 148 *******************************/ 149 150:- if(current_predicate('$rl_history'/1)). 151:- use_module(library(readutil)). 152 153prolog:history(_, load(File)) :- 154 access_file(File, read), 155 !, 156 setup_call_cleanup( 157 open(File, read, In, [encoding(utf8)]), 158 read_history(In), 159 close(In)). 160prologhistory(_, load(_)). 161 162read_history(In) :- 163 repeat, 164 read_line_to_codes(In, Codes), 165 ( Codes == end_of_file 166 -> ! 167 ; atom_codes(Line, Codes), 168 rl_add_history(Line), 169 fail 170 ). 171 172prolog:history(_, save(File)) :- 173 '$rl_history'(Lines), 174 ( Lines \== [] 175 -> setup_call_cleanup( 176 open(File, write, Out, [encoding(utf8)]), 177 forall(member(Line, Lines), 178 format(Out, '~w~n', [Line])), 179 close(Out)) 180 ; true 181 ). 182 183:- endif.