123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175(*********************************************************************************)(* OCaml-Stk *)(* *)(* Copyright (C) 2023-2024 INRIA All rights reserved. *)(* Author: Maxence Guesdon, INRIA Saclay *)(* *)(* This program is free software; you can redistribute it and/or modify *)(* it under the terms of the GNU General Public License as *)(* published by the Free Software Foundation, version 3 of the License. *)(* *)(* This program is distributed in the hope that it will be useful, *)(* but WITHOUT ANY WARRANTY; without even the implied warranty of *)(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *)(* GNU General Public License for more details. *)(* *)(* You should have received a copy of the GNU General Public *)(* License along with this program; if not, write to the Free Software *)(* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA *)(* 02111-1307 USA *)(* *)(* As a special exception, you have permission to link this program *)(* with the OCaml compiler and distribute executables, as long as you *)(* follow the requirements of the GNU GPL in regard to all of the *)(* software in the executable aside from the OCaml compiler. *)(* *)(* Contact: Maxence.Guesdon@inria.fr *)(* *)(*********************************************************************************)(** A widget to display {!Logs} message.*)[@@@landmark"auto"](** Property ["log_max_size"] so that log will not keep more
characters than specified. Default is [30_000]. *)letmax_size=Props.int_prop~default:30000"log_max_size"letcss_max_size=Theme.int_propmax_size(** The [textlog] widgets to display log messages.
This widget inherits from {!Textview.class-textview} and
provides methods to display log messages.
*)classtextlog?(classes=[])?name?props?wdata()=letclasses="log"::classesinobject(self)inheritTextview.textview~classes?name?props?wdata()assupervalmutablelog_cursor=None(** {2 Properties} *)methodmax_size=self#get_pmax_sizemethodset_max_size=self#set_pmax_size(** Property {!val-max_size}. *)(** {2 Log-printing functions}
Function for each log level inserts the given message with a
{{!Texttag.T.t}tag} associated to header characters:
{!Texttag.tag_debug}, {!Texttag.tag_info}, {!Texttag.tag_warning},
{!Texttag.tag_error} or {!Texttag.tag_app}.
The {{!Texttag.Theme.prop}theme} property of the widget will
use this tag to display the message header with the required text properties.
*)methoddebug?srcstr=self#insert_msg?src~tags:[Texttag.tag_debug]strmethodinfo?srcstr=self#insert_msg?src~tags:[Texttag.tag_info]strmethodwarn?srcstr=self#insert_msg?src~tags:[Texttag.tag_warning]strmethoderror?srcstr=self#insert_msg?src~tags:[Texttag.tag_error]strmethodapp?srcstr=self#insert_msg?src~tags:[Texttag.tag_app]str(** [insert_msg ?src ~tags str] inserts the given message [str].
Optional argument [src] indicates the {{!Logs.Src.t}log source}.
If it is provided, then the message is
preceded by the string ["[source]"] associated to given text tags.
[source] is the log source name.*)methodinsert_msg?src~tagsstr=(matchsrcwith|None->super#insert~tags?c:log_cursorstr;|Somesrc->super#insert~tags?c:log_cursor(Printf.sprintf"[%s]"(Logs.Src.namesrc));super#insertstr?c:log_cursor);letsize=Textbuffer.sizebufferinletmsize=self#max_sizeinifsize>msizethenlet_=self#delete~start:0~size:(size-msize)()in()else()(** [v#raw str] prints message [str] with no tags and no source.*)methodrawstr=self#insert~tags:[]strmethodprint?srclevel=matchlevelwith|Logs.Debug->self#debug?src|Logs.Info->self#info?src|Logs.Warning->self#warn?src|Logs.Error->self#error?src|Logs.App->self#app?srcinitializerList.iterself#add_handled_tagTexttag.log_tags;letc=self#add_cursor()inlog_cursor<-Somecend(** Convenient function to create a {!class-textlog}.
[max_size] can specified a value for {!val-max_size} property.
[theme] can specify a theme name to use.
See {!Widget.section-widget_arguments} for other arguments. *)lettextlog?classes?name?props?wdata?theme?maxsize?pack()=letw=newtextlog?classes?name?props?wdata()inOption.iter(w#set_pmax_size)maxsize;w#set_pTextview.show_cursorsfalse;w#set_pProps.editablefalse;w#set_pTextview.wrap_modeTextview.Wrap_char;Option.iterw#set_tagthemetheme;Widget.may_pack?packw#coerce;w(** [reporter textlog] creates a {!Logs.reporter} which will
dispatch log messages according to the presence of
{!Log.tag} in message tags: if present, the message is a Stk
log message and will be displayed on stderr, else if will
be displayed in the [textlog] widget. *)letreporter(logbox:textlog)=letbuf_fmt()=letb=Buffer.create512inFormat.formatter_of_bufferb,fun()->letm=Buffer.contentsbinBuffer.resetb;minletppf,b_flush=buf_fmt()in(*let reporter = Logs.format_reporter ~app:ppf ~dst:ppf () in*)letwrite_stklevel()=letstr=b_flush()inletstr=Printf.sprintf"[%s]%s"(Logs.level_to_string(Somelevel))strinLwt_io.writeLwt_io.stderrstrinletwrite_othersrclevel()=letstr=b_flush()in(trylogbox#print~srclevelstrwithe->prerr_endline(Printexc.to_stringe));(*Lwt.return_unit*)inletk_writelevel~overk_=letunblock()=over();Lwt.return_unitinLwt.finalize(writelevel)unblock|>Lwt.ignore_result;k()inletprint_stksrclevel~overkfmt=letk=k_write_stklevel~overkinFormat.kfprintfkppf("[%s] @["^^fmt^^"@]@.")(Logs.Src.namesrc)inletprint_othersrclevel~overkfmt=(*let k = k_ (write_other src) level ~over k in*)letk_=write_othersrclevel();over();k()inFormat.kfprintfkppf(fmt^^"@.")inletreportsrclevel~overkmsgf=msgf@@fun?header?tagsfmt->ignore(header);matchtagswith|SomesetwhenLogs.Tag.memLog.tagset->print_stksrclevel~overkfmt|_->print_othersrclevel~overkfmtin{Logs.report=report}