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