diff options
Diffstat (limited to 'macros/context')
14 files changed, 1762 insertions, 1556 deletions
diff --git a/macros/context/contrib/context-handlecsv/VERSION b/macros/context/contrib/context-handlecsv/VERSION index a81cff9619..4487f90172 100644 --- a/macros/context/contrib/context-handlecsv/VERSION +++ b/macros/context/contrib/context-handlecsv/VERSION @@ -1 +1 @@ -2023-08-31 +2023-09-01 diff --git a/macros/context/contrib/context-handlecsv/context-presvoz-master-5196bdec981cf48b83896ec7b7009fda20d9106f/doc/context/third/presvoz/gvoz.pdf b/macros/context/contrib/context-handlecsv/context-presvoz-master-5196bdec981cf48b83896ec7b7009fda20d9106f/doc/context/third/presvoz/gvoz.pdf Binary files differdeleted file mode 100644 index 06c4f78b97..0000000000 --- a/macros/context/contrib/context-handlecsv/context-presvoz-master-5196bdec981cf48b83896ec7b7009fda20d9106f/doc/context/third/presvoz/gvoz.pdf +++ /dev/null diff --git a/macros/context/contrib/context-handlecsv/context-presvoz-master-5196bdec981cf48b83896ec7b7009fda20d9106f/doc/context/third/presvoz/presvoz.pdf b/macros/context/contrib/context-handlecsv/context-presvoz-master-5196bdec981cf48b83896ec7b7009fda20d9106f/doc/context/third/presvoz/presvoz.pdf Binary files differdeleted file mode 100644 index 1e09286df2..0000000000 --- a/macros/context/contrib/context-handlecsv/context-presvoz-master-5196bdec981cf48b83896ec7b7009fda20d9106f/doc/context/third/presvoz/presvoz.pdf +++ /dev/null diff --git a/macros/context/contrib/context-handlecsv/context-presvoz-master-5196bdec981cf48b83896ec7b7009fda20d9106f/fonts/opentype/presvoz/Flechitas.otf b/macros/context/contrib/context-handlecsv/context-presvoz-master-5196bdec981cf48b83896ec7b7009fda20d9106f/fonts/opentype/presvoz/Flechitas.otf Binary files differdeleted file mode 100644 index 0107c921d2..0000000000 --- a/macros/context/contrib/context-handlecsv/context-presvoz-master-5196bdec981cf48b83896ec7b7009fda20d9106f/fonts/opentype/presvoz/Flechitas.otf +++ /dev/null diff --git a/macros/context/contrib/context-handlecsv/context-presvoz-master-5196bdec981cf48b83896ec7b7009fda20d9106f/fonts/opentype/presvoz/iRaccoonShowBold.otf b/macros/context/contrib/context-handlecsv/context-presvoz-master-5196bdec981cf48b83896ec7b7009fda20d9106f/fonts/opentype/presvoz/iRaccoonShowBold.otf Binary files differdeleted file mode 100644 index 487baf938b..0000000000 --- a/macros/context/contrib/context-handlecsv/context-presvoz-master-5196bdec981cf48b83896ec7b7009fda20d9106f/fonts/opentype/presvoz/iRaccoonShowBold.otf +++ /dev/null diff --git a/macros/context/contrib/context-handlecsv/context-presvoz-master-5196bdec981cf48b83896ec7b7009fda20d9106f/tex/context/third/presvoz/gvoz.py b/macros/context/contrib/context-handlecsv/context-presvoz-master-5196bdec981cf48b83896ec7b7009fda20d9106f/tex/context/third/presvoz/gvoz.py deleted file mode 100755 index b7efcb3d2e..0000000000 --- a/macros/context/contrib/context-handlecsv/context-presvoz-master-5196bdec981cf48b83896ec7b7009fda20d9106f/tex/context/third/presvoz/gvoz.py +++ /dev/null @@ -1,574 +0,0 @@ -#!/usr/bin/env python3 -# coding: utf-8 -# -# Copyright 2021-2022 (C) Pablo Rodríguez -# -# 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; either version 3 of the License, or -# (at your option) any later version. -# -# 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., 51 Franklin Street, Fifth Floor, Boston, -# MA 02110-1301, USA or see <http://www.gnu.org/licenses/gpl.html>. - -import os, sys, shutil -import xml.etree.ElementTree as ET -import cairo -import gi -gi.require_version("Gtk", "3.0") -gi.require_version("Gst", "1.0") -from gi.repository import Gtk, Gdk, GObject, GLib, Gst, GdkPixbuf -gi.require_version('Poppler', '0.18') -from gi.repository import Poppler - -Gst.init(sys.argv) - -class gvoz: - def __init__(self): - - self.execname = os.path.splitext(os.path.basename(sys.argv[0]))[0] - self.real_path = os.path.dirname(os.path.realpath(os.path.abspath(sys.argv[0]))) - self.program_version = "0.9.9.2" - - if(len(sys.argv) < 2): - self.on_file_selection() - print("") - print(" " + self.execname + "-" + self.program_version - + " (https://gvoz.presvoz.tk)") - print(" Written by Pablo Rodríguez") - print(" Usage: " + self.execname + " presentation.pdf") - print("") - - if len(sys.argv) > 1: - self.main_filename = sys.argv[1] - elif self.dialog_filename != "": - self.main_filename = self.dialog_filename - - self.filename = os.path.splitext(self.main_filename)[0] - - if os.path.splitext(self.main_filename)[1] != (".pdf" or ".PDF"): - self.pdffilename = os.path.splitext(self.main_filename)[0] + ".pdf" - if os.path.isfile(self.pdffilename) == False: - self.pdffilename = os.path.splitext(self.main_filename)[0] + ".PDF" - if os.path.isfile(self.pdffilename) == False: - self.on_file_selection() - elif os.path.isfile(self.pdffilename) == False: - self.on_file_selection() - else: - self.pdffilename = self.main_filename - - self.define_soundtimesnames() - - self.uri = Gst.filename_to_uri(os.path.abspath(self.pdffilename)) - - self.document = Poppler.Document.new_from_file(self.uri, None) - self.n_pages = self.document.get_n_pages() - self.page_selector = self.document.get_page(0) - self.current_page = 0 - - self.win = Gtk.Window() - self.win.set_icon_from_file(self.real_path + '/gvoz.svg') - self.doc_title = self.document.get_title() or "χαλεπὰ τὰ καλά" - self.win.set_title (self.execname + " — " + str(self.current_page + 1) + "/" + str(self.n_pages) + " — " + self.doc_title) - - self.win.set_default_size(500, 500) - self.win.set_position(Gtk.WindowPosition.CENTER_ALWAYS) - - self.box = Gtk.Box() - - self.area = Gtk.DrawingArea() - self.area.connect("draw", self.on_draw) - - self.box.pack_start(self.area, True, True, 0) - - self.win.add(self.box) - self.win.connect("destroy", Gtk.main_quit) - self.win.show_all() - - self.win.connect('key-press-event', self.key_press_event) - - self.width, self.height = self.win.get_size() - self.page_width, self.page_height= self.page_selector.get_size() - - self.surface = cairo.ImageSurface(cairo.FORMAT_RGB24, - int(self.width), - int(self.height)) - - if sys.platform.startswith('win'): - self.player = Gst.parse_launch("wasapisrc low-latency=true ! audio/x-raw,format=F32LE ! wavenc ! filesink location=\"" + self.audiofilename + "\"") - else: - self.player = Gst.parse_launch("autoaudiosrc ! audio/x-raw,format=F32LE,rate=48000,channels=1 ! wavenc ! filesink location=\"" + self.audiofilename + "\"") - - bus = self.player.get_bus() - bus.add_signal_watch() - bus.connect('message', self.on_message) - - xmp = self.document.get_metadata() - if xmp != None and xmp != "": - xmp_root = ET.fromstring(xmp) - for language in xmp_root.findall(".//{http://purl.org/dc/elements/1.1/}language"): - doc_lang = language.text - else: - print("The PDF document has no language information") - - title_separator = ". " - - self.sound_metadata = { "title" : "The Title" } - self.sound_metadata["genre"] = "Other/Presentation" - self.sound_metadata["application-name"] = "GVoz" - self.sound_metadata["encoder"] = self.sound_metadata["application-name"] - self.sound_metadata["encoder-version"] = self.program_version - self.sound_metadata["datetime"] = Gst.DateTime.new_now_local_time() - self.sound_metadata["date"] = GLib.Date.new_dmy(self.sound_metadata["datetime"].get_day(), - self.sound_metadata["datetime"].get_month(), self.sound_metadata["datetime"].get_year()) - - try: - doc_lang - except NameError: - print("\n\"" + os.path.basename(self.pdffilename) + - "\" contains no language information.") - self.doc_lang = None - else: - if doc_lang != None and doc_lang != "": - self.sound_metadata["language-code"] = doc_lang - self.sound_metadata["language-name"] = GstTag.tag_get_language_name(language_code) - if doc_lang.startswith('en'): - title_separator = ": " - else: - title_separator = ". " - - if self.document.get_subject() != None and self.document.get_subject() != "": - self.sound_metadata["comment"] = self.document.get_subject() - elif self.document.get_title() != None and self.document.get_title() != "": - self.sound_metadata["title"] = self.document.get_title() - if self.document.get_keywords() != None and self.document.get_keywords() != "": - self.sound_metadata["keywords"] = self.document.get_keywords() - if self.document.get_author() != None and self.document.get_author() != "": - self.sound_metadata["artist"] = self.document.get_author() - self.sound_metadata["copyright"] = "© " + str(self.sound_metadata["datetime"].get_year()) + " " + self.document.get_author() - else: - self.sound_metadata["copyright"] = "© " + str(self.sound_metadata["datetime"].get_year()) - - self.taglist = Gst.TagList.new_empty() - - self.mp3_converter = Gst.parse_launch("filesrc location=\"" + self.audiofilename + "\" ! decodebin ! audioconvert ! audioresample ! lamemp3enc mono=true cbr=true target=bitrate bitrate=32 ! id3v2mux ! filesink location=\"" + self.mp3_audio + "\"") - - mp3_bus = self.mp3_converter.get_bus() - mp3_bus.add_signal_watch() - mp3_bus.connect('message', self.on_mp3_message) - - self.mp3_metadata = True - - tagsetter = self.mp3_converter.get_by_interface(Gst.TagSetter) - for tag_key, tag_value in self.sound_metadata.items(): - try: - self.taglist.add_value(Gst.TagMergeMode.REPLACE, tag_key, tag_value) - except ValueError: - print("WARNING: skipping tag %s; value %s is not valid" % (tag_key, tag_value)) - if not self.taglist.is_empty() and self.mp3_metadata: - tagsetter.merge_tags(self.taglist, Gst.TagMergeMode.REPLACE_ALL) - print(type(self.mp3_metadata)) - print(self.taglist.to_string() + "\n") - else: - print("<<<< WARNING: Could not find element to set tags. >>>") - - # ~ self.opus_converter = Gst.parse_launch("filesrc location=\"" + self.audiofilename + "\" ! decodebin ! audioconvert ! audioresample ! opusenc audio-type=voice bitrate=16000 ! oggmux ! filesink location=\"" + self.opus_audio + "\"") - - # ~ opus_bus = self.opus_converter.get_bus() - # ~ opus_bus.add_signal_watch() - # ~ opus_bus.connect('message', self.on_opus_message) - - # ~ self.opus_metadata = True - - # ~ tagsetter = self.opus_converter.get_by_interface(Gst.TagSetter) - # ~ if not self.taglist.is_empty() and self.opus_metadata: - # ~ tagsetter.merge_tags(self.taglist, Gst.TagMergeMode.REPLACE_ALL) - # ~ else: - # ~ print("<<<< WARNING: Could not find element to set tags. >>>") - - self.use_presvoz = True - - def on_message(self, bus, message): - t = message.type - if t == Gst.MessageType.EOS: - self.player.set_state(Gst.State.NULL) - # ~ Gtk.main_quit() - elif t == Gst.MessageType.ERROR: - err, debug = message.parse_error() - print ("Error: %s" % err, debug) - self.player.set_state(Gst.State.NULL) - - def on_mp3_message(self, mp3_bus, message): - t = message.type - if t == Gst.MessageType.EOS: - self.mp3_converter.set_state(Gst.State.NULL) - self.generate_presentation() - Gtk.main_quit() - elif t == Gst.MessageType.ERROR: - err, debug = message.parse_error() - print ("Error: %s" % err, debug) - self.mp3_converter.set_state(Gst.State.NULL) - - # ~ def on_opus_message(self, opus_bus, message): - # ~ t = message.type - # ~ if t == Gst.MessageType.EOS: - # ~ self.opus_converter.set_state(Gst.State.NULL) - # ~ Gtk.main_quit() - # ~ elif t == Gst.MessageType.ERROR: - # ~ err, debug = message.parse_error() - # ~ print ("Error: %s" % err, debug) - # ~ self.opus_converter.set_state(Gst.State.NULL) - - def generate_presentation (self): - if shutil.which("context") != None and shutil.which("context") != "" and self.use_presvoz: - os.system("context --purgeall --extra=third-presvoz " + self.pdffilename) - if os.path.isfile(self.js_timesfilename): - os.remove(self.js_timesfilename) - - def define_soundtimesnames (self): - if sys.platform.startswith('win'): - self.audiofilename = self.filename.replace("\\", "/") + "-audio.wav" - self.mp3_audio = self.filename.replace("\\", "/") + "-audio.mp3" - self.opus_audio = self.filename.replace("\\", "/") + "-audio.opus" - else: - self.audiofilename = self.filename + "-audio.wav" - self.mp3_audio = self.filename + "-audio.mp3" - self.opus_audio = self.filename + "-audio.opus" - - self.times = [] - self.timesfilename = self.filename + '-times.txt' - self.js_timesfilename = self.filename + '-times.js' - - def on_metadata_info (self): - if self.document.get_title() != None and self.document.get_title() != "": - metadata_info = "\n<b>Title:</b> <i>" + self.document.get_title() + "</i>" - if self.document.get_author() != None and self.document.get_author() != "": - metadata_info += "\n\n<b>Author:</b> <i>" + self.document.get_author() + "</i>" - if self.document.get_subject() != None and self.document.get_subject() != "": - metadata_info += "\n\n<b>Comments:</b> <i>" + self.document.get_subject() + "</i>" - if self.document.get_keywords() != None and self.document.get_keywords() != "": - metadata_info += "\n\n<b>Keywords:</b> <i>" + self.document.get_keywords() + "</i>" - if self.doc_lang != None and self.doc_lang != "": - metadata_info += "\n\n<b>Language:</b> <i>" + self.sound_metadata['language-name'] + "</i>" - else: - metadata_info = "\nThe PDF document contains no metadata" - - - self.sound_metadata["comment"] = self.document.get_subject() - if self.document.get_author() != None and self.document.get_author() != "": - self.sound_metadata["artist"] = self.document.get_author() - self.sound_metadata["copyright"] = "© " + str(self.sound_metadata["datetime"].get_year()) + " " + self.document.get_author() - else: - self.sound_metadata["copyright"] = "© " + str(self.sound_metadata["datetime"].get_year()) - - dialog = Gtk.MessageDialog( - # ~ transient_for=self, - flags=0, - message_type=Gtk.MessageType.INFO, - buttons=Gtk.ButtonsType.OK, - text="Metadata from PDF Document", - ) - - dialog.format_secondary_text(metadata_info) - - dialog.props.secondary_use_markup = True - - dialog.run() - - dialog.destroy() - - def on_keys_info (self): - keys_info = "\n<b>space</b>\t\tGo to next slide and write its time" - keys_info += "\n\t\t\tThis starts and finishes sound recording" - keys_info += "\n\t\t\tAfter that, <i>PresVoz</i> will generate the presentation" - keys_info += "\n\n<b>a</b>\t\t\tAbout <i>GVoz</i>" - keys_info += "\n\n<b>c</b>\t\t\tDon’t generate PDF and <i>Flash</i> presentations with <i>PresVoz</i>" - keys_info += "\n\n<b>d</b>\t\t\tShow metadata imported from the PDF document" - keys_info += "\n\n<b>h</b>\t\t\tShow key information" - keys_info += "\n\n<b>m</b>\t\t\tEnable mouse–click to advance slides" - keys_info += "\n\n<b>p</b>\t\t\tPause / unpause sound and times recording" - keys_info += "\n\t\t\tWith paused recording, <i>GVoz</i> will exit full–screen" - keys_info += "\n\t\t\tWith recording started again, <i>GVoz</i> will go full–screen" - # ~ keys_info += "\n\n<b>x</b>\t\t\tRemove metadata in MP3 file\n\t\t\tTitle and author are read from the PDF document\n\t\t\tDates and times are set from the recording" - keys_info += "\n\n<b>q</b>\t\t\tQuit <i>GVoz</i> (presentation won’t be generated)" - - dialog = Gtk.MessageDialog( - # ~ transient_for=self, - flags=0, - message_type=Gtk.MessageType.INFO, - buttons=Gtk.ButtonsType.OK, - text="Keyboard Info", - ) - dialog.format_secondary_text( - keys_info - ) - - dialog.props.secondary_use_markup = True - - dialog.run() - - dialog.destroy() - - def on_presvoz_info (self): - presvoz_info = "\nPresentation won’t be generated after sound and times recording." - presvoz_info += "\n\nIf you want to generate it, just use <i>Presvoz</i> after <i>GVoz</i> finishes." - - dialog = Gtk.MessageDialog( - # ~ transient_for=self, - flags=0, - message_type=Gtk.MessageType.INFO, - buttons=Gtk.ButtonsType.OK, - text="Presentation Disabled", - ) - dialog.format_secondary_text( - presvoz_info - ) - - dialog.props.secondary_use_markup = True - - dialog.run() - - dialog.destroy() - - def on_mouse_info (self): - mouse_info = "\nMouse has been activated to advance slides." - mouse_info += "\n\nMouse–clicks have been enabled to advance slides." - mouse_info += "\n\nThere is no way to disable the mouse again." - - dialog = Gtk.MessageDialog( - # ~ transient_for=self, - flags=0, - message_type=Gtk.MessageType.INFO, - buttons=Gtk.ButtonsType.OK, - text="Mouse Enabled", - ) - dialog.format_secondary_text(mouse_info) - - dialog.props.secondary_use_markup = True - - dialog.run() - - dialog.destroy() - - def on_presvoz_presentation (self): - presvoz_presentation = "\nThe selected PDF document is already a presentation with voice." - presvoz_presentation += "\n\nPlease, select other PDF document not already generated by <i>PresVoz</i>." - - dialog = Gtk.MessageDialog( - # ~ transient_for=self, - flags=0, - message_type=Gtk.MessageType.INFO, - buttons=Gtk.ButtonsType.OK, - text="<big><b><i>PresVoz</i> Presentation Detected</b></big>", - ) - - dialog.format_secondary_text(presvoz_presentation) - - dialog.props.use_markup = True - dialog.props.secondary_use_markup = True - - response = dialog.run() - if response == Gtk.ResponseType.OK: - self.on_file_selection() - - dialog.run() - - dialog.destroy() - - def on_existing_files (self): - already_recorded_files = "\nVoice and times have already been recorded in a previous session." - already_recorded_files += "\n\nIf you proceed, <tt>" + os.path.basename(self.audiofilename) + "</tt> and <tt>" + os.path.basename(self.timesfilename) + "</tt> will be lost forever." - already_recorded_files += "\n\nIf you cancel, you will quit <i>GVoz</i>." - already_recorded_files += "\n\nIf you want to keep <tt>" + os.path.basename(self.audiofilename) + "</tt> and <tt>" + os.path.basename(self.timesfilename) + "</tt>, please quit and rename them or move them to another directory." - already_recorded_files += "\n\nDo you really want to proceed?\n" - - dialog = Gtk.MessageDialog( - # ~ transient_for=self, - flags=0, - message_type=Gtk.MessageType.WARNING, - buttons=Gtk.ButtonsType.YES_NO, - text="Existing Sound and Times", - ) - - dialog.format_secondary_text(already_recorded_files) - - dialog.set_default_response(Gtk.ResponseType.NO) - - dialog.props.secondary_use_markup = True - - response = dialog.run() - if response == Gtk.ResponseType.YES: - if os.path.isfile(self.audiofilename): - os.remove(self.audiofilename) - if os.path.isfile(self.timesfilename): - os.remove(self.timesfilename) - if os.path.isfile(self.mp3_audio): - os.remove(self.mp3_audio) - if os.path.isfile(self.opus_audio): - os.remove(self.opus_audio) - elif response == Gtk.ResponseType.NO: - Gtk.main_quit() - - dialog.destroy() - - def button_press_event(self, widget, event): - if event.button == 1: - self.record_and_advance() - - def key_press_event(self, widget, event): - if event.keyval != Gdk.keyval_from_name("a"): - if event.keyval != Gdk.keyval_from_name("h"): - if event.keyval != Gdk.keyval_from_name("q"): - if event.keyval != Gdk.keyval_from_name("x"): - if event.keyval != Gdk.keyval_from_name("c"): - if event.keyval != Gdk.keyval_from_name("m"): - if event.keyval != Gdk.keyval_from_name("d"): - if self.player.get_state(0)[1] == Gst.State.NULL and self.current_page + 1 <= self.n_pages: - if os.path.exists(self.audiofilename) or os.path.exists(self.timesfilename): - self.on_existing_files() - elif self.document.get_subject() != None: - if self.document.get_subject().endswith('🤞🐞 – https://www.presvoz.tk'): - self.on_presvoz_presentation() - if event.keyval == Gdk.keyval_from_name("h"): - self.on_keys_info() - if event.keyval == Gdk.keyval_from_name("a"): - self.about_info() - if event.keyval == Gdk.keyval_from_name("q"): - if self.player.get_state(0)[1] == Gst.State.PLAYING or self.player.get_state(0)[1] == Gst.State.PAUSED: - self.player.set_state(Gst.State.NULL) - self.file_times.close() - if os.path.isfile(self.audiofilename): - self.mp3_converter.set_state(Gst.State.PLAYING) - self.win.set_title (self.execname + " — Converting sound to MP3 format…") - Gtk.main_quit() - if event.keyval == Gdk.keyval_from_name("x"): - self.mp3_metadata = False - self.opus_metadata = False - if event.keyval == Gdk.keyval_from_name("c"): - self.use_presvoz = False - self.on_presvoz_info() - if event.keyval == Gdk.keyval_from_name("d"): - self.on_metadata_info() - if event.keyval == Gdk.keyval_from_name("m"): - self.win.connect('button-press-event', self.button_press_event) - self.on_mouse_info() - if event.keyval == Gdk.keyval_from_name("p"): - if self.player.get_state(0)[1] == Gst.State.PLAYING: - self.win.unfullscreen() - self.win.set_title (self.execname + " — " + str(self.current_page + 1) + "/" + str(self.n_pages) + " — " + self.doc_title) - self.player.set_state(Gst.State.PAUSED) - elif self.player.get_state(0)[1] == Gst.State.PAUSED: - self.win.fullscreen() - self.player.set_state(Gst.State.PLAYING) - if event.keyval == Gdk.keyval_from_name("space"): - self.record_and_advance() - - def record_and_advance(self): - if self.player.get_state(0)[1] == Gst.State.NULL and self.current_page + 1 <= self.n_pages: - self.win.fullscreen() - self.player.set_state(Gst.State.PLAYING) - self.file_times = open(self.timesfilename, 'w') - elif self.player.get_state(0)[1] == Gst.State.PLAYING: - if self.current_page + 1 < self.n_pages: - self.current_page += 1 - self.page_selector = self.document.get_page(self.current_page) - self.area.set_size_request(int(self.width),int(self.height)) - self.area.queue_draw() - self.file_times.write(str(int(self.player.get_pipeline_clock().get_time()/1000000)) + "\n") - elif self.current_page + 1 == self.n_pages: - self.win.unfullscreen() - self.win.set_title (self.execname + " — " + str(self.current_page + 1) + "/" + str(self.n_pages) + " — " + self.doc_title) - self.player.send_event(Gst.Event.new_eos()) - self.file_times.write(str(int(self.player.get_pipeline_clock().get_time()/1000000))) - self.file_times.close() - self.current_page += 1 - self.mp3_converter.set_state(Gst.State.PLAYING) - self.win.set_title (self.execname + " — Converting sound to MP3 format…") - if shutil.which("context") != None and shutil.which("context") != "" and self.use_presvoz: - self.win.set_title (self.execname + " — Generating presentation…") - # ~ self.opus_converter.set_state(Gst.State.PLAYING) - # ~ self.win.set_title (self.execname + " — Converting sound to Opus format…") - - def on_file_selection(self): - dialog = Gtk.FileChooserDialog( - title="Please choose a PDF document", action=Gtk.FileChooserAction.OPEN - ) - dialog.add_buttons( - Gtk.STOCK_CANCEL, - Gtk.ResponseType.CANCEL, - Gtk.STOCK_OPEN, - Gtk.ResponseType.OK, - ) - - self.add_filters(dialog) - - response = dialog.run() - if response == Gtk.ResponseType.OK: - self.dialog_filename = dialog.get_filename() - self.pdffilename = self.dialog_filename - self.filename = os.path.splitext(self.dialog_filename)[0] - self.define_soundtimesnames() - - dialog.destroy() - - def add_filters(self, dialog): - filter_pdf = Gtk.FileFilter() - filter_pdf.set_name("PDF documents") - filter_pdf.add_mime_type("application/pdf") - dialog.add_filter(filter_pdf) - - def on_draw(self, widget, cairo_context): - add_x = 0 - add_y = 0 - - if (self.area.get_allocated_width()/self.page_width) < (self.area.get_allocated_height()/self.page_height): - self.scale = self.area.get_allocated_width()/self.page_width - add_y = (((self.area.get_allocated_height()-(self.page_height*self.scale))/2)/self.scale) - else: - self.scale = self.area.get_allocated_height()/self.page_height - add_x = (((self.area.get_allocated_width()-(self.page_width*self.scale))/2)/self.scale) - - # ~ cr = Gdk.cairo_create(self.win.get_window()) # deprecated - # ~ cairo_context = cairo.Context(self.surface) # new, seems not required - - cairo_context.set_source_surface(self.surface) - cairo_context.set_source_rgba(1, 1, 1) - - if self.scale != 1: - cairo_context.scale(self.scale, self.scale) - - cairo_context.translate(add_x, add_y) - cairo_context.rectangle(0, 0, self.page_width, self.page_height) - cairo_context.fill() - self.page_selector.render(cairo_context) - - def about_info (self): - dialog = Gtk.AboutDialog() - dialog.set_program_name("GVoz") - dialog.set_version(self.program_version) - dialog.set_comments("Record and create presentations with voice") - dialog.set_website("https://gvoz.presvoz.tk") - dialog.set_website_label("https://gvoz.presvoz.tk") - dialog.set_authors(["Pablo Rodríguez"]) - dialog.set_copyright("© 2021-2022 Pablo Rodríguez") - dialog.set_license_type(Gtk.License.GPL_2_0) - dialog.set_wrap_license = True - dialog.set_logo(GdkPixbuf.Pixbuf.new_from_file(self.real_path + "/gvoz.svg")) - dialog.connect('response', lambda dialog, data: dialog.destroy()) - dialog.show_all() - - def gtk_main_quit(self, widget, event): - Gtk.main_quit() - - def main(self): - Gtk.main() - -gv = gvoz() -gv.main() diff --git a/macros/context/contrib/context-handlecsv/context-presvoz-master-5196bdec981cf48b83896ec7b7009fda20d9106f/tex/context/third/presvoz/mtx-context-third-presvoz.tex b/macros/context/contrib/context-handlecsv/context-presvoz-master-5196bdec981cf48b83896ec7b7009fda20d9106f/tex/context/third/presvoz/mtx-context-third-presvoz.tex deleted file mode 100644 index 2e9fc84a53..0000000000 --- a/macros/context/contrib/context-handlecsv/context-presvoz-master-5196bdec981cf48b83896ec7b7009fda20d9106f/tex/context/third/presvoz/mtx-context-third-presvoz.tex +++ /dev/null @@ -1,798 +0,0 @@ -%D \module -%D [ file=mtx-context-third-presvoz, -%D version=2022.02.02, -%D title=PresVoz, -%D subtitle=Presentations with Voice, -%D author=Pablo Rodríguez, -%D date=\currentdate, -%D copyright={Michal Vlásak \&\ Pablo Rodríguez}] -%C -%C This module is part of the \CONTEXT\ macro||package and is -%C copyrighted by its authors. - -\starttext -\startlmtxmode -\def\Presentation{\getdocumentfilename{1}} - -\startluacode -if file.extname(document.files[1]) == "" then - document.main_file = file.addsuffix(document.files[1],"pdf") -else - document.main_file = document.files[1] -end - -if file.pathpart(document.main_file) == "" then - document.main_filename = file.nameonly(document.main_file) -else - document.main_filename = file.pathpart(document.main_file):gsub(io.fileseparator, "/") .. "/" .. file.nameonly(document.main_file) -end - -document.original_times = document.main_filename .. "-times.txt" - -document.uncompressed_audio = document.main_filename .. "-audio.wav" - -document.audio_mp3 = document.main_filename .. "-audio.mp3" - -document.audio_opus = document.main_filename .. "-audio.opus" -- opus might work later - -document.compressed_audio = document.audio_mp3 - ---twolame is not an option: gives wrong sizes - -if io.exists(document.uncompressed_audio) and not(io.exists(document.audio_mp3)) and os.which('lame') then - os.execute('lame -m m -b 32 "' .. document.uncompressed_audio .. '" "' .. document.audio_mp3 .. '"') -elseif io.exists(document.uncompressed_audio) and not(io.exists(document.compressed_audio)) then - if os.which('opusenc') then os.execute('opusenc --downmix-mono --bitrate 16 "' .. document.uncompressed_audio .. '" "' .. document.audio_opus .. '"') end -end - -presvoz_name = document.main_filename .. "-presvoz.pdf" - -if not(io.exists(document.original_times)) or not(io.exists(document.compressed_audio)) then - context.enablemode({"missing-files"}) -end -\stopluacode - -\startmode[missing-files] -\setupinteractionscreen[option=max] -\setupbodyfont[pagella] -\startTEXpage[offset=2em, align=center] - \bf\color[darkred]{{\bi PresVoz} requires\\ - {\tt\cldcontext{document.original_times}} and {\tt\cldcontext{document.uncompressed_audio}}\\ - to do its magic with {\tt\cldcontext{document.main_file}}.} -\stopTEXpage -\stopmode - -\startnotmode[missing-files] -\startluacode -document.timeline_filename = document.main_filename .. "-times.js" - -document.slides_swf = document.main_filename .. ".swf" - -document.presentation_script = document.main_filename .. "-presentation.sc" - -document.presentation_swf = document.main_filename .. "-presentation.swf" - -document.presentation_filename = file.nameonly(document.main_file) .. "-presentation.swf" - -document.first_slide_swf = document.main_filename .. "-first.swf" - -document.loader_script = document.main_filename .. "-loader.sc" - -document.loader_swf = document.main_filename .. "-loader.swf" - -function document.transfer_metadata(name) - local main_doc = lpdf.epdf.load(name) - lpdf.addtocatalog("Lang", lpdf.unicode(main_doc.Catalog.Lang), lpdf.string(main_doc.Catalog.Lang)) - if main_doc.Catalog.Lang == "en" then - document.separate_subtitle = ": " - else - document.separate_subtitle = ". " - end - if main_doc.Info.Subject ~= nil and main_doc.Info.Subject ~= "" then - context.setupinteraction{ title = main_doc.Info.Title .. document.separate_subtitle .. main_doc.Info.Subject } - else - context.setupinteraction{ title = main_doc.Info.Title } - end - if main_doc.Catalog.Lang == "es" then - document.presvoz_banner = "Hecho con «PresVoz» 🤞🐞" - elseif main_doc.Catalog.Lang == "pt" then - document.presvoz_banner = "Feito con «PresVoz» 🤞🐞" - elseif main_doc.Catalog.Lang == "it" then - document.presvoz_banner = "Fatto con «PresVoz» 🤞🐞" - elseif main_doc.Catalog.Lang == "fr" then - document.presvoz_banner = "Fait avec « PresVoz » 🤞🐞" - elseif main_doc.Catalog.Lang == "de" then - document.presvoz_banner = "Erezeugt mit »PresVoz« 🤞🐞" - elseif main_doc.Catalog.Lang == "nl" then - document.presvoz_banner = "Gedaan med „PresVoz” 🤞🐞" - elseif main_doc.Catalog.Lang == "nl" then - document.presvoz_banner = "Gedaan med „PresVoz” 🤞🐞" - else - document.presvoz_banner = "Done with “PresVoz” 🤞🐞" - end - context.setupinteraction{ subtitle = document.presvoz_banner .. " – https://www.presvoz.tk" } - if main_doc.Info.Author ~= nil and main_doc.Info.Author ~= "" then - context.setupinteraction{ author = main_doc.Info.Author } - end - if main_doc.Info.ModDate ~=nil and main_doc.Info.ModDate ~= "" then - original_Doc_date = main_doc.Info.ModDate:sub(3,6) .. "-" .. - main_doc.Info.ModDate:sub(7,8) .. "-" .. - main_doc.Info.ModDate:sub(9,10) .. "T" .. - main_doc.Info.ModDate:sub(11,12) .. ":" .. - main_doc.Info.ModDate:sub(13,14) .. ":" .. - main_doc.Info.ModDate:sub(15,22):gsub("'", ":") - directives.enable('backend.date=' .. original_Doc_date .. "'") - end - lpdf.epdf.unload(name) -end - -document.transfer_metadata(document.main_file) -\stopluacode - -\startbuffer[flash-presentation] - \startluacode - local raw_times = io.open(document.original_times) - local swf_times = io.open(document.presentation_script, "w") - - swf_times:write([[# Presentation script, generated by PresVoz - # - # Copyright (C) 2003 Leonard Lin - # Copyright (C) 2007-2008 Sergio Costas - # Copyright (C) 2009-2021 Pablo Rodríguez - # - # 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; either version 3 - # of the License, or (at your option) any later version. - # - # 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, see <http://www.gnu.org/licenses>. - # - # Additional permission under GNU GPL version 3 section 7 - # - # As a special exception, if you create a document which uses this - # script, and compile this script or a modified version of it in the - # document, this script does not by itself cause the resulting document - # to be covered by the GNU General Public License. This exception does - # not however invalidate any other reasons why the document might be - # covered by the GNU General Public License. - - .flash filename="]] .. document.presentation_swf .. [[" version=8 fps=12 - - .swf slides "]] .. document.slides_swf .. [[" - .sound audio "]] .. document.audio_mp3 .. [[" - - .action: - var times=new Array(); - var maxtimes; - var position; - var mode; - var sound_position; - var sound_length; - var show_slide; - - var contextual = new ContextMenu(); - function ssurl(){ - getURL("https://www.presvoz.tk", "_blank"); - } - - switch (System.capabilities.language) { - case "en" : - ss_message = "Done with PresVoz 🤞🐞"; - break; - case "es" : - ss_message = "Hecho con PresVoz 🤞🐞"; - break; - case "gl" : - ss_message = "Feito con PresVoz 🤞🐞"; - break; - case "pt" : - ss_message = "Feito con PresVoz 🤞🐞"; - break; - case "it" : - ss_message = "Fatto con PresVoz 🤞🐞"; - break; - case "fr" : - ss_message = "Fait avec PresVoz 🤞🐞"; - break; - case "de" : - ss_message = "Erezeugt mit PresVoz 🤞🐞"; - break; - case "nl" : - ss_message = "Gedaan med PresVoz 🤞🐞"; - break; - case "el" : - ss_message = "Kατασκευασμένος με PresVoz 🤞🐞"; - break; - default: - ss_message = "Made with PresVoz 🤞🐞"; - break; - } - - contextual.hideBuiltInItems(); - ss_url = new ContextMenuItem(ss_message, ssurl); - contextual.customItems.push(ss_url); - _root.menu = contextual; - - snd = new Sound(this); - snd.attachSound("audio"); - sound_length=snd.duration; - position = 0; - - show_slide = false; - times[0] = 0;]] .. "\n") - - line_number = 0 - while true do - line = raw_times:read() - if line == nil then break end - if line:match("%D") == nil then - line_number = line_number + 1 - print ("times["..line_number.."] = " .. line .. ";") - swf_times:write(" times["..line_number.."] = " .. line .. ";") - swf_times:write("\n") - end - end - - swf_times:write("\n" .. [[ - maxtimes = times.length - 1; - - function pause_or_play() { - if (mode==0) { - snd.start(snd.position/1000.0,0); - mode=1; - } else if (mode==1) { - snd.stop(); - mode=0; - } - } - - function previous_slide() { - if (mode<2) { - if (mode==0) { mode=1; } - snd.stop(); - if (position>0) { - sound_position=times[position-1]; - } else { - sound_position=0; - } - snd.start(sound_position/1000.0,0); - } - } - - function next_slide() { - if (mode<2) { - if (mode==0) { mode=1; } - snd.stop(); - sound_position = times[position+1]; - if (sound_position>sound_length) { - sound_position=sound_length-500; - } - snd.start(sound_position/1000.0,0); - } - } - - function first_slide() { - snd.stop(); - snd.start(0,0); - slides.gotoAndStop(1); - position=0; - mode=1; - show_slide=true; - } - - function last_slide() { - snd.stop(); - sound_position = times[maxtimes-1]; - slides.gotoAndStop(maxtimes); - show_slide=false; - snd.start(sound_position/1000.0,0); - } - - function toogle_fullscreen() { - if(Stage.displayState == "normal"){ - Stage.displayState="fullScreen"; - } else { - Stage.displayState="normal"; - } - } - - Mouse.onMouseDown = function() { - if ((getTimer() - lastClick) < 400) { - pause_or_play(); - } else { - lastClick = getTimer(); - } - }; - - - key_listen=new Object(); - - key_listen.onKeyDown = function() { - switch (Key.getCode()) { - case 32: - pause_or_play(); - break; - case 37: - previous_slide(); - break; - case 38: - first_slide(); - break; - case 39: - next_slide(); - break; - case 40: - last_slide(); - break; - case 70: - toogle_fullscreen(); - break; - } - }; - - function check_time() { - if (mode==1) { - if ( sound_position + 50 > sound_length) { - snd.stop(); - mode=2; - if(Stage.displayState == "fullScreen"){ - Stage.displayState="normal"; - } - } else { - if ((snd.position>=times[position])&&(snd.position<times[position+1])) { - if (show_slide) { - slides.gotoAndStop(position+1); - show_slide=false; - } - } else { - if (position>maxtimes) { - snd.stop(); - mode=2; - } else { - if (snd.position<times[position]) { - position-=1; - } else { - position+=1; - } - show_slide=true; - } - } - } - } - } - - setInterval(check_time, 10); - - mode=1; - snd.start(0,0); - Stage["displayState"] = "fullScreen"; - Mouse.addListener(Mouse); - Key.addListener(key_listen); - - .end - - .frame 1 - .put slides - .stop slides - - .end - ]]) - - raw_times:close() - swf_times:close() - - os.execute('pdf2swf -f -T 8 -s filloverlap -s linksopennewwindow "' .. document.main_file .. '" -o "' .. document.slides_swf .. '"') - os.execute('swfc "' .. document.presentation_script .. '"') - if io.exists(document.presentation_swf) then os.remove(document.presentation_script) os.remove(document.slides_swf) end - \stopluacode -\stopbuffer - -\startbuffer[flash-loader] - \startluacode - local raw_times = io.open(document.original_times) - local loader_times = io.open(document.loader_script, "w") - - fig = figures.getinfo(document.main_file) - function dimension_bp(dimension) - return math.floor(dimension*number.dimenfactors.bp) - end - - loader_times:write([[# Preloader script, generated by PresVoz - # - # Copyright (C) 2009-2021 Pablo Rodríguez - # - # 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; either version 3 - # of the License, or (at your option) any later version. - # - # 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, see <http://www.gnu.org/licenses>. - # - # Additional permission under GNU GPL version 3 section 7 - # - # As a special exception, if you create a document which uses this - # script, and compile this script or a modified version of this script - # into the document, this script does not by itself cause the resulting - # document to be covered by the GNU General Public License. - # This exception does not however invalidate any other reasons why - # the document might be covered by the GNU General Public License. - - .flash filename="]] .. document.loader_swf .. [[" version=8 fps=12" - .font roman "]] .. resolvers.findfile("iRaccoonShowBold.otf") .. [[" glyphs=" %()KB0123456789/:,.CPDNuk[]resntiocanbld!" - .edittext newloader font=roman color=#ffff00 size=30% width=350 height=30 border=none align="center" noselect variable=load_text - .box placeholder width=]] .. dimension_bp(fig.used.width) .. [[ height=]] .. dimension_bp(fig.used.height) .. "\n" .. [[ - .box fsarea fill=#ffffff00 color=#ffffff00 width=]] .. dimension_bp(fig.used.width) .. [[ height=]] .. dimension_bp(fig.used.height) .. "\n" .. [[ - .outline fscreen_outline: M 62.78125 18.703125 L 43.367188 23.734375 L 38.390625 43.09375 L 42.109375 39.375 L 48.671875 45.9375 L 65.625 29.039062 L 59.0625 22.421875 L 62.78125 18.703125 z M 199.71875 18.703125 L 203.4375 22.421875 L 196.875 29.039062 L 213.773438 45.9375 L 220.390625 39.375 L 224.109375 43.09375 L 219.132812 23.734375 L 199.71875 18.703125 z M 83.125 45.9375 C 73.429688 45.9375 65.625 53.742188 65.625 63.4375 L 65.625 133.4375 C 65.625 143.132812 73.429688 150.9375 83.125 150.9375 L 179.375 150.9375 C 189.070312 150.9375 196.875 143.132812 196.875 133.4375 L 196.875 63.4375 C 196.875 53.742188 189.070312 45.9375 179.375 45.9375 L 83.125 45.9375 z M 48.726562 150.9375 L 42.109375 157.5 L 38.390625 153.78125 L 43.367188 173.140625 L 62.78125 178.171875 L 59.0625 174.453125 L 65.625 167.835938 L 48.726562 150.9375 z M 213.773438 150.9375 L 196.875 167.835938 L 203.4375 174.453125 L 199.71875 178.171875 L 219.132812 173.140625 L 224.109375 153.78125 L 220.390625 157.5 L 213.773438 150.9375 z .end - .outline fulls_outline: M 17.5 0 L 245 0 C 254.695312 0 262.5 7.804688 262.5 17.5 L 262.5 179.375 C 262.5 189.070312 254.695312 196.875 245 196.875 L 17.5 196.875 C 7.804688 196.875 0 189.070312 0 179.375 L 0 17.5 C 0 7.804688 7.804688 0 17.5 0 z .end - .filled fscreen outline=fscreen_outline fill=#969696ff color=#969696ff - .filled fulls outline=fulls_outline fill=#64646496 color=#64646496 - - .button fscr_button - .show fscreen as=idle - .show fscreen as=area - .show fscreen as=hover - .show fscreen as=pressed - .end - - .button fs_area - .show fsarea as=idle - .show fsarea as=area - .show fsarea as=hover - .show fsarea as=pressed - .on_release: - fullscreen_button._visible = 0; - fs_area._visible = 0; - Stage["displayState"] = "fullScreen"; - _root.load_text = "[Click to start]"; - _root.dlprogress_mvclip._visible = true; - the_presentation = "./]] .. document.presentation_filename .. [["; - this.loadMovie(the_presentation, this.placeholder); - .end - .end - - .sprite fullscreen_button - .put fscreen - .put fulls - .end - - .swf first_slide "]] .. document.first_slide_swf .. [[" - .frame 1 - .put first_slide - .stop first_slide - .put fullscreen_button - .stop fullscreen_button - .put fs_area - .stop fs_area - - .action: - slide_height=Stage.height; - slide_width=Stage.width; - - var contextual = new ContextMenu(); - function ssurl(){ getURL("https://www.presvoz.tk", "_blank"); } - - switch (System.capabilities.language) { - case "en" : - ss_message = "Done with PresVoz 🤞🐞"; - break; - case "es" : - ss_message = "Hecho con PresVoz 🤞🐞"; - break; - case "gl" : - ss_message = "Feito con PresVoz 🤞🐞"; - break; - case "pt" : - ss_message = "Feito con PresVoz 🤞🐞"; - break; - case "it" : - ss_message = "Fatto con PresVoz 🤞🐞"; - break; - case "fr" : - ss_message = "Fait avec PresVoz 🤞🐞"; - break; - case "de" : - ss_message = "Erezeugt mit PresVoz 🤞🐞"; - break; - case "nl" : - ss_message = "Gedaan med PresVoz 🤞🐞"; - break; - case "el" : - ss_message = "Kατασκευασμένος με PresVoz 🤞🐞"; - break; - default: - ss_message = "Made with PresVoz 🤞🐞"; - break; - } - - contextual.hideBuiltInItems(); - ss_url = new ContextMenuItem(ss_message, ssurl); - contextual.customItems.push(ss_url); - _root.menu = contextual; - - counter_percent=(slide_width/800)*100; - newloader._xscale=counter_percent; - newloader._yscale=counter_percent; - newloader._x = (slide_width-(newloader._width))/2; - newloader._y = (slide_height-newloader._height)/2; - - button_percent = (slide_width/600)*100; - fullscreen_button._xscale = button_percent; - fullscreen_button._yscale = button_percent; - fullscreen_button._x = (slide_width-(fullscreen_button._width))/2; - fullscreen_button._y = (slide_height-fullscreen_button._height)/2; - - _root.createEmptyMovieClip("dlprogress_mvclip", 0); - dlprogress_mvclip.createEmptyMovieClip("bar", 1); - dlprogress_mvclip.createEmptyMovieClip("stroke", 2); - - with (dlprogress_mvclip.stroke) { - lineStyle(0, 0xFF0000, 30); - moveTo(0, 0); - lineTo(300, 0); - lineTo(300, 40); - lineTo(0, 40); - lineTo(0, 0); - } - with (dlprogress_mvclip.bar) { - beginFill(0xFF0000, 30); - moveTo(0, 0); - lineTo(300, 0); - lineTo(300, 40); - lineTo(0, 40); - lineTo(0, 0); - endFill(); - _xscale = 0; - } - dlprogress_mvclip._x = (slide_width-dlprogress_mvclip._width)/2; - dlprogress_mvclip._y = (slide_height-dlprogress_mvclip._height)/2; - - dlprogress_mvclip._visible = false; - fs_listen=new Object(); - - fs_listen.onKeyDown = function() { - if (Key.isDown(13)) { - if(Stage.displayState == "normal"){ - Stage.displayState="fullScreen"; - } else { - Stage.displayState="normal"; - } - } - }; - - Key.addListener(fs_listen); - - - .end - - .sprite images - .put placeholder alpha=0% - .action: - the_presentation = "./]] .. document.presentation_filename .. [["; - first_loading = new Object(); - first_loading.onMouseDown = function () { - load_swf = new MovieClipLoader(); - load_swf.loadClip(the_presentation, placeholder); - listen_loading = new Object(); - listen_loading.onLoadStart = function(target) { - _root.dlprogress_mvclip.bar._xscale = 0; - _starttime = gettimer(); - }; - listen_loading.onLoadError = function(){ - _root.load_text = "Presentation cannot be loaded!"; - }; - listen_loading.onLoadProgress = function(target, bytesLoaded, bytesTotal) { - downldtime = (gettimer() - _starttime) / 1000; - _root.load_text = (String (Math.round ((bytesLoaded * 100) / bytesTotal)) + "% (" + Math.round((bytesLoaded / 1024) / downldtime) + " KB/s)"); - _root.dlprogress_mvclip.bar._xscale = Math.round(bytesLoaded/bytesTotal*100); - keeping_awake = setInterval(function(){}, 1000); - }; - listen_loading.onLoadComplete = function(target) { - clearInterval(keeping_awake); - _root.load_text = ""; - _root.dlprogress_mvclip._visible = 0; - _root.dlprogress_mvclip.bar._visible = 0; - _root.first_slide._visible = 0; - }; - load_swf.addListener(listen_loading); - }; - Mouse.addListener(first_loading); - .end - .end - - .put newloader - .stop newloader - .end]]) - - raw_times:close() - loader_times:close() - - os.execute('pdf2swf -f -p 1 -T 8 -s filloverlap -s linksopennewwindow "' .. document.main_file .. '" -o "' .. document.first_slide_swf .. '"') - os.execute('swfc "' .. document.loader_script .. '"') - if io.exists(document.loader_swf) then os.remove(document.loader_script) os.remove(document.first_slide_swf) end - \stopluacode -\stopbuffer - -\def\TimeLine#1% - {\cldcontext{ document.timeline_filename }} - -\def\SoundFile#1% - {\cldcontext{ document.compressed_audio }} - -\startbuffer[generate-timeline] - \startluacode - local raw_times = io.open(document.original_times) - local js_times = io.open(document.timeline_filename, "w") - - js_times:write("\\startJSpreamble times used now") - js_times:write("\n") - js_times:write("var times = [];") - js_times:write("\n") - js_times:write("var maxtimes = times[times.length - 1];") - js_times:write("\n") - js_times:write("times[0] = 0;") - js_times:write("\n") - line_number = 0 - while true do - line = raw_times:read() - if line == nil then break end - if line:match("%D") == nil then - line_number = line_number + 1 - print ("times["..line_number.."] = " .. line .. ";") - js_times:write("times["..line_number.."] = " .. line .. ";") - js_times:write("\n") - end - end - - js_times:write("\\stopJSpreamble") - - raw_times:close() - js_times:close() - \stopluacode -\stopbuffer - -\startmode[*first] -\getbuffer[generate-timeline] -\doiftext - {\ctxlua{if os.which('pdf2swf') and os.which('swfc') then context("a") end}} - {\getbuffer[flash-presentation] - \getbuffer[flash-loader]} -\stopmode - -\getfiguredimensions[\Presentation] - -\setupexternalfigures[interaction=all] - -\setupinteraction - [state=start, - color=, - contrastcolor=, - style=, - focus=standard] - -\useJSscripts[presvoz.mkxl] -\startnotmode[*first] - \useJSscripts[\TimeLine{\Presentation}] -\stopnotmode - -\definefontfamily - [mainface] - [rm] - [Latin Modern Sans] - -\definefontfamily - [mainface] - [ss] - [Flechitas] - -\setupbodyfont - [mainface, 25pt] - -\setupmakeup - [page] - [pagestate=start, - style=\bfd, - color=white, - footerstate=start, - align=center] - -\definecolor[transparent-gray] - [r=.45, g=.45, b=.45] - -\defineviewerlayer[fullscreen][state=start] -\defineviewerlayer[unfullscreen][state=stop] -\defineviewerlayer[play][state=start] -\defineviewerlayer[pause][state=stop] - -\definecolor[transparent][r=1, a=1, t=0] - -\startbuffer[fullscreen-button] - \startoverlay - {\viewerlayer[fullscreen]{C}} - {\viewerlayer[unfullscreen]{I}} - {\goto{\color[transparent]{C}}[JS(SwitchFS{})]} - \stopoverlay -\stopbuffer - -\startbuffer[play-pause-button] - \startoverlay - {\viewerlayer[play]{R}} - {\viewerlayer[pause]{H}} - {\goto{\color[transparent]{C}}[JS(PlayPauseSound{})]} - \stopoverlay -\stopbuffer - -\def\SlideNavigationButtons{% - \goto{F}[JS(GoToFirstSlide{})]\,% - \goto{B}[JS(GoToPreviousSlide{})]\,% - \inlinebuffer[play-pause-button]\,% - \goto{S}[JS(StopSound{})]\,% - \goto{N}[JS(GoToNextSlide{})]\,% - \goto{L}[JS(GoToLastSlide{})]\quad - \null\inlinebuffer[fullscreen-button]% - } - -\definelayer[player-buttons] - [x=.5\dimexpr\figurewidth\relax, - y=.9525\dimexpr\figureheight\relax, - location=middle, - state=repeat] - -\definelayer[placesound] - -\startbuffer[placesound] - \definerenderingwindow[soundplace] - [width=0pt, height=0pt, frame=on] - -\doiftextelse{\ctxlua{if document.compressed_audio == document.audio_opus then context("opus") end}} - {\userendering[mainsound][audio/opus][\SoundFile{\Presentation}][embed=yes, list=no]} - {\userendering[mainsound][audio/mp3][\SoundFile{\Presentation}][embed=yes, list=no]} - - \placerenderingwindow[soundplace][mainsound] -\stopbuffer - -\setupbackgrounds - [page] - [background={foreground, placesound, player-buttons}] - - -\setlayer[player-buttons] - {\switchtobodyfont[sans, \cldcontext{tex.dimen.paperwidth/1000000}pt]\color[transparent-gray]{\SlideNavigationButtons}} - -\resetpagenumber - -\dorecurse{\noffigurepages}{\startTEXpage[pagestate=start] -\ifnum\recurselevel=1 \setlayer[placesound]{\getbuffer[placesound]}\fi -\externalfigure[\Presentation][page=\recurselevel] -\stopTEXpage} -\stopnotmode - -\startluacode -luatex.wrapup( - function() - os.remove(presvoz_name) - os.rename(tex.jobname .. ".pdf", presvoz_name) - end -) -\stopluacode -\stoptext -\stoplmtxmode - -\startmkivmode -\setupinteractionscreen[option=max] -\startTEXpage[offset=2em, align=center] - \ssbf\color[darkgreen]{\LMTX\ required,\\I’m afraid.} -\stopTEXpage -\stopmkivmode -\stoptext diff --git a/macros/context/contrib/context-handlecsv/context-presvoz-master-5196bdec981cf48b83896ec7b7009fda20d9106f/tex/context/third/presvoz/presvoz.mkxl b/macros/context/contrib/context-handlecsv/context-presvoz-master-5196bdec981cf48b83896ec7b7009fda20d9106f/tex/context/third/presvoz/presvoz.mkxl deleted file mode 100644 index 8d8ecd3cde..0000000000 --- a/macros/context/contrib/context-handlecsv/context-presvoz-master-5196bdec981cf48b83896ec7b7009fda20d9106f/tex/context/third/presvoz/presvoz.mkxl +++ /dev/null @@ -1,183 +0,0 @@ -\startJSpreamble PresVoz used now -var ocgs = this.getOCGs(0); -this.pageNum = 0; - -var label = "mainsound" ; -var rendition = this.media.getRendition(label) ; -var screen = this.media.getAnnot({nPage: 0, cAnnotTitle: label}) ; -var main_sound_player; - -function ToogleFSButton() { - if (app.fs.isFullScreen) { - ocgs[0].state = false; - ocgs[3].state = true; - } else { - ocgs[0].state = true; - ocgs[3].state = false; - } -} - -function TooglePlayPauseButton() { - if (main_sound_player.isPlaying) { - ocgs[1].state = true; - ocgs[2].state = false; - } else { - ocgs[1].state = false; - ocgs[2].state = true; - } -} - -function timer_resume() { - check_time = app.setInterval("advance_slide()", 10); -} - -function timer_pause() { - app.clearInterval(check_time); -} - -function jump() { - if (!main_sound_player.isOpen) { main_sound_player.open(); } - - if ( typeof main_sound_player != "undefined" || ( typeof main_sound_player != "undefined" && main_sound_player.isOpen )) { - if (this.pageNum < times.length) { - if (!main_sound_player.isPlaying) { - timer_resume(); - } - - var jump_time = times[this.pageNum] / 1000; - - main_sound_player.pause(); - main_sound_player.seek({time: jump_time}); - main_sound_player.play(); - } - } -} - -function advance_slide() { - if (!main_sound_player.isOpen) { main_sound_player.open(); } - if ( typeof main_sound_player.where() != "undefined") { - var current_offset = 1000 * main_sound_player.where().time; - - if (current_offset >= times[this.pageNum + 1]) { - this.pageNum += 1; - } else if (current_offset <= times[this.pageNum - 1]) { - this.pageNum -= 1; - } - } -} - -function start_player() { - main_sound_player = app.media.createPlayer({ - rendition: rendition, - annot: screen, - settings: { - autoPlay: false, - }, - events: { - onDone: function() { - timer_pause(); - app.fs.isFullScreen = false; - ToogleFSButton(); - this.pageNum = this.numPages - 1; - }, - afterDone: function() { - main_sound_player.pause(); - TooglePlayPauseButton(); - main_sound_player.seek({time: maxtimes}); - this.pageNum = this.numPages - 1; - }, - onEscape: function() { - app.fs.isFullScreen = false; - ToogleFSButton(); - }, - afterEscape: function() { - main_sound_player.pause(); - TooglePlayPauseButton(); - }, - afterPause: function() { - timer_pause(); - TooglePlayPauseButton(); - }, - onPlay: function() { - app.fs.isFullScreen = true; - ToogleFSButton(); - }, - afterPlay: function() { - timer_resume(); - TooglePlayPauseButton(); - }, - afterReady: function() { - main_sound_player.play(); - }, - }, - }); - main_sound_player.open(); -} - -function GoToFirstSlide(label) { - this.pageNum = 0; - if ( typeof main_sound_player != "undefined" || ( typeof main_sound_player != "undefined" && main_sound_player.isOpen )) { - if ( main_sound_player.isPlaying ) { jump(); } - } -} - -function PlayPauseSound() { - if ( typeof main_sound_player == "undefined" ) { - start_player(); - } else if ( !main_sound_player.isPlaying ) { - if (!main_sound_player.isOpen) { main_sound_player.open(); } - if ( typeof main_sound_player.where() != "undefined" && main_sound_player.where().time == 0 ) - { this.pageNum = 0; } - timer_resume(); - main_sound_player.play(); - } else if ( main_sound_player.isPlaying ) { - timer_pause(); - main_sound_player.pause(); - } -} - -function StopSound() { - if ( typeof main_sound_player != "undefined" || ( typeof main_sound_player != "undefined" && main_sound_player.isOpen )) { - main_sound_player.pause(); - main_sound_player.seek({time: 0}); - } - this.pageNum = 0; -} - -function GoToLastSlide(label) { - this.pageNum = this.numPages - 1; - if ( typeof main_sound_player != "undefined" || ( typeof main_sound_player != "undefined" && main_sound_player.isOpen )) { - if ( main_sound_player.isPlaying ) { jump(); } - } -} - -function GoToNextSlide(label) { - ++this.pageNum; - if ( typeof main_sound_player != "undefined" || ( typeof main_sound_player != "undefined" && main_sound_player.isOpen )) { - if ( main_sound_player.isPlaying ) { jump(); } - } -} - -function GoToPreviousSlide(label) { - --this.pageNum; - if ( typeof main_sound_player != "undefined" || ( typeof main_sound_player != "undefined" && main_sound_player.isOpen )) { - if ( main_sound_player.isPlaying ) { jump(); } - } -} - -function SwitchFS() { - if (app.fs.isFullScreen == false) { - app.fs.isFullScreen = true; - if (app.fs.isFullScreen) { - ocgs[0].state = false; - ocgs[3].state = true; - } - } else { - app.fs.isFullScreen = false; - if (!app.fs.isFullScreen) { - ocgs[0].state = true; - ocgs[3].state = false; - } - } -} -\stopJSpreamble diff --git a/macros/context/contrib/context-handlecsv/doc/context/third/handlecsv/handlecsv.epub b/macros/context/contrib/context-handlecsv/doc/context/third/handlecsv/handlecsv.epub Binary files differnew file mode 100644 index 0000000000..9c84f899b5 --- /dev/null +++ b/macros/context/contrib/context-handlecsv/doc/context/third/handlecsv/handlecsv.epub diff --git a/macros/context/contrib/context-handlecsv/doc/context/third/handlecsv/handlecsv.pdf b/macros/context/contrib/context-handlecsv/doc/context/third/handlecsv/handlecsv.pdf Binary files differnew file mode 100644 index 0000000000..91b5ef03ec --- /dev/null +++ b/macros/context/contrib/context-handlecsv/doc/context/third/handlecsv/handlecsv.pdf diff --git a/macros/context/contrib/context-handlecsv/tex/context/third/handlecsv/t-handlecsv-extra.lua b/macros/context/contrib/context-handlecsv/tex/context/third/handlecsv/t-handlecsv-extra.lua new file mode 100644 index 0000000000..1efdcbb06d --- /dev/null +++ b/macros/context/contrib/context-handlecsv/tex/context/third/handlecsv/t-handlecsv-extra.lua @@ -0,0 +1,151 @@ +-- %D \module +-- %D [ file=t-handlecsv-extra.lua, +-- %D version=2019.05.27, +-- %D title=HandleCSV extra, +-- %D subtitle=CSV file analysis - extended functions and macros, +-- %D author=Jaroslav Hajtmar, +-- %D date=2019-05-27, +-- %D copyright=Jaroslav Hajtmar, +-- %D license=GNU General Public License] +-- +-- %C Copyright (C) 2019 Jaroslav Hajtmar +-- %C +-- %C This program is free software: you can redistribute it and/or modify +-- %C it under the terms of the GNU General Public License as published by +-- %C the Free Software Foundation, either version 3 of the License, or +-- %C (at your option) any later version. +-- %C +-- %C This program is distributed in the hope that it will be useful, +-- %C but WITHOUT ANY WARRANTY; without even the implied warranty of +-- %C MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- %C GNU General Public License for more details. +-- %C +-- %C You should have received a copy of the GNU General Public License +-- %C along with this program. If not, see <http://www.gnu.org/licenses/>. + + +thirddata = thirddata or { } + +thirddata = thirddata or { } + +thirddata.handlecsv = thirddata.handlecsv or { -- next global variables + +} + + +-- Initialize global variables etc. + + +-- Utility and documentation function and macros + + + +function thirddata.handlecsv.addleadingcharacters(character, tonumberortext, width) +-- Add leading characters to number to align with the width + local strcharacter=tostring(character) + local strnumberortext=tostring(tonumberortext) + strnumberortext = string.rep(strcharacter, width-#strnumberortext)..strnumberortext + return strnumberortext -- It returns a strange result unless the leading character is just one. +end + +function thirddata.handlecsv.addleadingzeros(tonumberortext, width) +-- Add leading zeros to number to align with the width + return thirddata.handlecsv.addleadingcharacters(0, tonumberortext, width) +end + +function thirddata.handlecsv.addzeros(tonumber) +-- Add leading zeroes depending on the number of rows + local width=string.len(tostring(thirddata.handlecsv.numrows())) + return thirddata.handlecsv.addleadingzeros(tonumber, width) +end + + + +-- function thirddata.handlecsv.cr_lines(s) +-- return s:gsub('\r\n?', '\n'):gmatch('(.-)\n') +-- end + + +function thirddata.handlecsv.file2Array(filename) +-- read CSV file into line array +local linesarray={} + for line in io.lines (filename) do + linesarray[#linesarray+1]=line + end +return linesarray +end + + + +function thirddata.handlecsv.writefileinreverseorder(inpfilename,outfilename) +-- write CSV file <inpfilename> into reverse order CSV file <outfilename> + local tLines = thirddata.handlecsv.file2Array(inpfilename) + local outfile = io.open(outfilename, "w") + local ifrom=#tLines + local ito=1 + if thirddata.handlecsv.gCSVHeader then -- when CSV file is with header, then header line is first line + outfile:write(tLines[1]) + outfile:write("\r\n") + ito=2 + end + for i = ifrom, ito, -1 do -- write rest of lines in reverse order + outfile:write(tLines[i]) + outfile:write("\r\n") + end +outfile:flush() +outfile:close() +end + + + +function thirddata.handlecsv.deletefile(filename) +-- remove file from disk + os.remove(filename) +end + + +function thirddata.handlecsv.varreverseorder(csvfilename) +-- CSV file <csvfilename> is stored in variable array gTableRows['csvfilename'][row][column] +-- this function rearrange gTableRows into reverse order +local templine={} +for i = 1, math.floor(thirddata.handlecsv.gNumRows[csvfilename]/2) do +templine=thirddata.handlecsv.gTableRows[csvfilename][i] +thirddata.handlecsv.gTableRows[csvfilename][i]=thirddata.handlecsv.gTableRows[csvfilename][thirddata.handlecsv.gNumRows[csvfilename]-i+1] +thirddata.handlecsv.gTableRows[csvfilename][thirddata.handlecsv.gNumRows[csvfilename]-i+1]=templine +end +end + + + + + +-- ConTeXt source: +local string2print=[[% + +\def\addleading#1#2#3{\ctxlua{context(thirddata.handlecsv.addleadingcharacters('#1','#2','#3'))}} +\def\addzeros#1#2{\ctxlua{context(thirddata.handlecsv.addleadingzeros('#1','#2'))}} +\def\zeroed#1{\ctxlua{context(thirddata.handlecsv.addzeros('#1'))}} +% \def\zeroedlineno{\ctxlua{context(string.rep( "0",(tostring(thirddata.handlecsv.numrows())):len() - (tostring(thirddata.handlecsv.linepointer())):len()) .. thirddata.handlecsv.linepointer())}}% from Pablo +\def\zeroedlineno{\zeroed{\lineno}}% from Pablo (and simplified by him) +\def\writefileinreverseorderfromto#1#2{\ctxlua{thirddata.handlecsv.writefileinreverseorder('#1','#2')}}% +\def\writecurrfileinreverseorderto#1{\ctxlua{thirddata.handlecsv.writefileinreverseorder(thirddata.handlecsv.gCurrentlyProcessedCSVFile,'#1')}}% +\def\deletefile#1{\ctxlua{thirddata.handlecsv.deletefile('#1')}}% +\def\reverseorderof#1{\ctxlua{thirddata.handlecsv.varreverseorder('#1')}} +\def\reverseorder{\ctxlua{thirddata.handlecsv.varreverseorder(thirddata.handlecsv.gCurrentlyProcessedCSVFile)}} + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Complete listing macros and commands that can be used (to keep track of all defined macros): +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% \addleading{}{}{}, \addzeros{}{}, \zeroed{}, \zeroedlineno (from Pablo) +% \writefileinreverseorderfromto{<inpfilename>}{<outfilename>} % create file <outfilename> in reverse order of file <inpfilename> +% \writecurrfileinreverseorderto{<outfilename>} % create file <outfilename> in reverse order +% \deletefile{<filename>} % close and delete file <filename> +% \reverseorderof{<csvfilename>} % reverse order of opened CSV file <csvfilename> +% \reverseorder % reverse order of currently processed CSV file +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +]] + +-- write definitions into ConTeXt: +thirddata.handlecsv.string2context(string2print) + diff --git a/macros/context/contrib/context-handlecsv/tex/context/third/handlecsv/t-handlecsv-tools.lua b/macros/context/contrib/context-handlecsv/tex/context/third/handlecsv/t-handlecsv-tools.lua new file mode 100644 index 0000000000..87806a9a03 --- /dev/null +++ b/macros/context/contrib/context-handlecsv/tex/context/third/handlecsv/t-handlecsv-tools.lua @@ -0,0 +1,178 @@ +-- %D \module +-- %D [ file=t-handlecsv-tools.lua, +-- %D version=2015.07.08, +-- %D title=HandleCSV tools, +-- %D subtitle=CSV file analysis, +-- %D author=Jaroslav Hajtmar, +-- %D date=\currentdate, +-- %D copyright=Jaroslav Hajtmar, +-- %D license=GNU General Public License] +-- +-- %C Copyright (C) 2015 Jaroslav Hajtmar +-- %C +-- %C This program is free software: you can redistribute it and/or modify +-- %C it under the terms of the GNU General Public License as published by +-- %C the Free Software Foundation, either version 3 of the License, or +-- %C (at your option) any later version. +-- %C +-- %C This program is distributed in the hope that it will be useful, +-- %C but WITHOUT ANY WARRANTY; without even the implied warranty of +-- %C MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- %C GNU General Public License for more details. +-- %C +-- %C You should have received a copy of the GNU General Public License +-- %C along with this program. If not, see <http://www.gnu.org/licenses/>. + + +-- use a feature that is part of the /texmf-dist/tex/context/base/util-prs.lua + +thirddata = thirddata or { } + +thirddata = thirddata or { } + +thirddata.handlecsv = thirddata.handlecsv or { -- next global variables + +} + + +-- Initialize global variables etc. + + +-- Utility and documentation function and macros + +function thirddata.handlecsv.csvreport(anyfilename) -- Listing report informations about opening a CSV file + local actualopenfile=thirddata.handlecsv.gCurrentlyProcessedCSVFile + thirddata.handlecsv.opencsvfile(anyfilename) + local coldelim = thirddata.handlecsv.gUserCSVSeparator or "" + local quot = thirddata.handlecsv.gUserCSVQuoter or "" + local currcoldelim = thirddata.handlecsv.gCSVSeparator or "" + local currquot = thirddata.handlecsv.gCSVQuoter or "" + infomakra=[[\crlf ]] + for i = 1, thirddata.handlecsv.gNumCols do -- for all fields in header + local makroname=[[{\bf\backslash ]]..thirddata.handlecsv.tmn(thirddata.handlecsv.gColumnNames[i])..[[}]] + headercolnames = [[{\bf\backslash c]]..thirddata.handlecsv.ar2colnum(i)..[[}=]]..makroname..[[, ]] + infomakra=infomakra..headercolnames -- list generating + end -- for i=1, #gCSV + -- Kvůli nastavení na zač. + infomakra=infomakra..'\\par' -- infomakra=infomakra..'\par' -- closing of opened group +local string2print=[[\title{Current CSV file report} +Input CSV file: {\bf ]]..'\\csvfilename'..[[} \crlf +Existing header of CSV file (ie first no data line) : {\tt ]]..tostring(thirddata.handlecsv.gCSVHeader)..[[}\crlf +Settings default CSV separator (see Lua variable {\tt gUserCSVSeparator}) : ]]..coldelim..[[\crlf +Settings default CSV field "quoter" (see Lua variable {\tt gUserCSVQuoter}) : ]]..quot..[[\crlf +Settings current CSV separator : ]]..currcoldelim..[[\crlf +Settings current CSV field "quoter" : ]]..currquot..[[\crlf +Current settings of delimiters and quoters: {\tt ]]..currquot..[[field1]]..currquot..currcoldelim..currquot..[[field2]]..currquot..currcoldelim..currquot..[[field3]]..currquot..currcoldelim..[[ } ... etc.\crlf +Using hooks (default is off) : {\tt ]]..tostring(thirddata.handlecsv.gUseHooks)..[[}\crlf +Number of columns in a table: {\bf]]..'\\numcols'..[[}\crlf +Number of rows in the table: {\bf ]]..'\\numrows'..[[}\crlf +Macros supplying columns data in each row of table: ]]..infomakra..[[ +\crlf +Additional predefined macros: \crlf +{\bf\backslash csvfilename} -- name of open CSV file ({\bf]]..'\\csvfilename'..[[})\crlf +{\bf\backslash numcols} -- number of table columns ({\bf]]..'\\numcols'..[[})\crlf +{\bf\backslash numrows} -- number of table lines ({\bf]]..'\\numrows'..[[})\crlf +{\bf\backslash numline} -- number of the currently loaded row (for use in print reports) \crlf +{\bf\backslash lineno} -- serial number of the actual loaded line of CSV table \crlf +{\bf\backslash csvreport} -- prints the report on file open \crlf +{\bf\backslash printline} -- lists the current CSV row table in a condensed form \crlf +{\bf\backslash printall} -- CSV output table in a condensed form \crlf +{\bf\backslash setfiletoscan}\{{\it filename}\} -- setting of name of CSV file\crlf +{\bf\backslash opencsvfile}{\{\it filename}\} -- open CSV table\crlf +{\bf\backslash setheader} -- set a header flag\crlf +{\bf\backslash resetheader} -- unset a header flag\crlf +{\bf\backslash nextrow} -- next row of CSV table (with test of EOF)\crlf +{\bf\backslash setsep}{\{\it delimiter}\} -- set delimiter of columns\crlf +{\bf\backslash resetsep} -- unset to default values\crlf +{\bf\backslash setld}\{{\it delimiter}\} -- set left quoter\crlf +{\bf\backslash resetld} -- unset left quoter to default values\crlf +{\bf\backslash setrd}\{{\it delimiter}\} -- set right quoter\crlf +{\bf\backslash resetrd} -- unset right quoter to default values\crlf +{\bf\backslash blinehook} -- begin line hook macro (process before first column value of each row)\crlf +{\bf\backslash elinehook} -- end line hook macro (process after last column value of each row)\crlf +{\bf\backslash bfilehook} -- begin file hook macro (process before whole file processing)\crlf +{\bf\backslash efilehook} -- end file hook macro (process after whole file processing)\crlf +\vfill\break ]] +thirddata.handlecsv.string2context(string2print) +thirddata.handlecsv.opencsvfile(actualopenfile) +end -- thirddata.handlecsv.csvreport() + +function thirddata.handlecsv.xprintline() -- lists the current CSV row table (needed to define macro \printline) + for i=1,thirddata.handlecsv.gNumCols do + context([[\csvcell]]..'['..i..','..thirddata.handlecsv.gCurrentLinePointer..']'..thirddata.handlecsv.gCSVSeparator..[[ ]]) + end +end + + +function thirddata.handlecsv.xprintall() -- lists all the csv table (necessary to define macros \printall) +-- http://www.pragma-ade.nl/general/manuals/hybrid.pdf + thirddata.handlecsv.opencsvfile() + local basespec = { + framecolor = "blue", + split="yes", + align= "middle", + style = "sans", + offset="2pt", + } + context.bTABLE(basespec) + for i=1, thirddata.handlecsv.gNumRows do + context.bTR() + for j=1,thirddata.handlecsv.gNumCols do + context.bTD() + context([[\csvcell]]..'['..j..','..i..']') -- Writing real values ... + -- context(thirddata.handlecsv.gTableRows[j][i]..' ') -- Writing real values ... + context.eTD() + end + context.eTR() + end -- of for +context.eTABLE() +end + + + +-- ConTeXt source: +local string2print=[[% + +% CSV file report. Syntax: \csvreport or \csvreport{filename}. +\def\csvreport{\dosingleempty\docsvreport}% +\def\docsvreport[#1]{\dosinglegroupempty\dodocsvreport}% +\def\dodocsvreport#1{\iffirstargument\ctxlua{thirddata.handlecsv.csvreport("#1")}\else\ctxlua{thirddata.handlecsv.csvreport()}\fi}% + +%\def\xprintline{\ctxlua{context(thirddata.handlecsv.printline())}} + + +% Původní verze: +% \def\xprintall{\ctxlua{context(thirddata.handlecsv.xprintall())}} + +\def\printline{\dorecurse{\numcols}{\csvcell[\recurselevel,\linepointer], }\crlf} + + +\def\printall{% +\setuppapersize[A3,landscape][A3,landscape] +\catcode`\#=12 %CSV file contains # characters (i.e. TeX problematic character) +\switchtobodyfont[10pt] +\setupTABLE[background=color,backgroundcolor=yellow] +\setupTABLE[row][first][background=color,backgroundcolor=lightgray] +\bTABLE[offset=2pt, split=yes] + \dorecurse{\numexpr(\numrows+1)} + {\bTR + \dorecurse{\numcols} + {\bTD \csvcell[\currentTABLEcolumn,\currentTABLErow-1] \eTD} + \eTR} +\eTABLE +} + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Complete listing macros and commands that can be used (to keep track of all defined macros): +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% \csvreport, \csvreport{<filename>} +% \printline +% \printall + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +]] + +-- write definitions into ConTeXt: +thirddata.handlecsv.string2context(string2print) + diff --git a/macros/context/contrib/context-handlecsv/tex/context/third/handlecsv/t-handlecsv.lua b/macros/context/contrib/context-handlecsv/tex/context/third/handlecsv/t-handlecsv.lua new file mode 100644 index 0000000000..16ba045aa2 --- /dev/null +++ b/macros/context/contrib/context-handlecsv/tex/context/third/handlecsv/t-handlecsv.lua @@ -0,0 +1,1403 @@ +-- %D \module +-- %D [ file=t-handlecsv.lua, +-- %D version=2019.03.30, +-- %D title=HandleCSV module, +-- %D subtitle=CSV file handling, +-- %D author=Jaroslav Hajtmar, +-- %D date=\currentdate, +-- %D copyright=Jaroslav Hajtmar, +-- %D email=hajtmar@gyza.cz, +-- %D license=GNU General Public License] +-- +-- %C Copyright (C) 2019 Jaroslav Hajtmar +-- %C +-- %C This program is free software: you can redistribute it and/or modify +-- %C it under the terms of the GNU General Public License as published by +-- %C the Free Software Foundation, either version 3 of the License, or +-- %C (at your option) any later version. +-- %C +-- %C This program is distributed in the hope that it will be useful, +-- %C but WITHOUT ANY WARRANTY; without even the implied warranty of +-- %C MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- %C GNU General Public License for more details. +-- %C +-- %C You should have received a copy of the GNU General Public License +-- %C along with this program. If not, see <http://www.gnu.org/licenses/>. + + +-- use a feature that is part of the /texmf-dist/tex/context/base/util-prs.lua + +thirddata = thirddata or { } + +thirddata.handlecsv = { -- Global variables +-- gCSVSeparator + gUserCSVSeparator=';', -- the most widely used field separator in CSV tables +-- gCSVQuoter + gUserCSVQuoter='"', -- +-- gCSVHeader + gUserCSVHeader=false, -- CSV file is by default considered as a CSV file without the header (in header are treated as column names of macros + gUserUseHooks=false, -- In default setting is not use "hooks" when process CSV file + gUserColumnNumbering='XLS', -- Something other than the XLS or undefined variable value (eg commenting that line) to set the Roman numbering ... + gCurrentlyProcessedCSVFile=nil, + gMarkingEmptyLines=false, + gUserMarkingEmptyLines=false, -- if true, then module mark empty rows in CSV file else module accept empty lines as regular lines + gTableEmptyRows={}, -- array of indexes of empty lines of CSV table -> gTableEmptyRows['csvfilename'][1]= 3 etc + gTableNotEmptyRows={}, -- array of indexes of nonempty lines of CSV table -> gTableNotEmptyRows['csvfilename'][1]= 3 etc + gCSVHandleBuffer={}, -- temporary buffer +-- NEW variables + gOpenFiles={}, -- array of all opened files + gNumLine={}, -- global variable - gNumLine['csvfilename.csv']=0 + gNumRows={}, -- global variable - save number of rows of csv table: gNumRows['csvfilename']=0 + gNumEmptyRows={}, -- global variable - save number of empty rows of csv table: gNumEmptyRows['csvfilename']=0 + gNumNotEmptyRows={}, -- global variable - save number of empty rows of csv table: gNumNotEmptyRows['csvfilename']=0 + gNumCols={}, -- global variable - save number of columns of csv table: gNumCols['csvfilename']=0 + gCurrentLinePointer={}, -- ie. CSV line number ie. number of the currently processed row: gCurrentLinePointer['csvfilename']=0 + gColumnNames={}, -- array with column names (readings from header of CSV file): gColumnNames['csvfilename'] + gColNames={}, -- associative array with column names for indexing use f.e. gColNames['csvfilename']['Firstname']=1, etc... + gTableRows={}, -- array of contents of cells of CSV table -> gTableRows['csvfilename'][row][column] + gTableRowsIndex={}, -- array of flags of lines of CSV table -> gTableEmptyRowsIndex['csvfilename'][i]= true or false + gSavedLinePointerNo=1, -- global variable to keep the line number +} + +local setmacro = interfaces.setmacro or "" + +-- Initialize global variables etc. + +-- Default value is saved in glob. variable gUseHooks (default is FALSE) +if thirddata.handlecsv.gUseHooks == nil then thirddata.handlecsv.gUseHooks = thirddata.handlecsv.gUserUseHooks end +-- Default value is saved in glob. variable gUserCSVHeader (default FALSE) +if thirddata.handlecsv.gCSVHeader == nil then thirddata.handlecsv.gCSVHeader = thirddata.handlecsv.gUserCSVHeader end +-- Default value is saved in glob. variable gCSVSeparator (default COMMA) +if thirddata.handlecsv.gCSVSeparator == nil then thirddata.handlecsv.gCSVSeparator = thirddata.handlecsv.gUserCSVSeparator end +-- Default value is saved in glob. variable gCSVSeparator (default ") +if thirddata.handlecsv.gCSVQuoter == nil then thirddata.handlecsv.gCSVQuoter = thirddata.handlecsv.gUserCSVQuoter end +-- Default value is saved in glob. variable gMarkingEmptyLines (default is FALSE) +if thirddata.handlecsv.gMarkingEmptyLines==nil then thirddata.handlecsv.gMarkingEmptyLines = thirddata.handlecsv.gUserMarkingEmptyLines end + + +-- Tools block: Contain auxiliary functions and tools + + +function thirddata.handlecsv.texmacroisdefined(macroname) -- check whether macroname macro is defined in ConTeXt +-- function is used to test whether the user has defined the macro \macroname. If not, it needs to define any default value + return token.get_cmdname(token.create(macroname)) ~= "undefined_cs" +end + +function thirddata.handlecsv.ParseCSVLine(line,sep) +-- tool function ParseCSVLine is defined for compatibility. Parsing string (or line). + local mycsvsplitter = utilities.parsers.rfc4180splitter{ + separator = sep, + quote = '"', + strict=true, -- add 15.2.2016 + } + local list = mycsvsplitter(line) inspect(list) + return list[1] +end + + +function thirddata.handlecsv.tmn(s) -- TeX Macro Name. Name of TeX macro should not contain forbidden characters + if string.len(s) == 0 then s='nil' end -- When the parameter 's' does not contain any character that is not the separator character, it is necessary to create macro name + maxmacrolength=50 -- if the first string in line longer "than is healthy, so about 50 characters is sufficient + -- ATTENTION! In the case that 1st CSV table row header that is a different column for content, which coincides with the first 'maxmacrolength' characters, the names of macros in different columns are the same (ie, the macro will give the correct result for the column) + diachar= {"á","ä","č","ď","é","ě","í","ň","ó","ř","š","ť","ú","ů","ý","ž","Á","Ä","Č","Ď","É","Ě","Í","Ň","Ó","Ř","Š","Ť","Ú","Ů","Ý","Ž"} + asciichar={"a","a","c","d","e","e","i","n","o","r","s","t","u","u","y","z","A","A","C","D","E","E","I","N","O","R","S","T","U","U","Y","Z"} + for i=1, 32 do + s=string.gsub(s, diachar[i], asciichar[i]) -- change diakritics chars + end + --s=string.gsub(s, "%d", "n") -- replace the numbers in name + -- For 0-9 to replace the letter O or Roman numerals + s=string.gsub(s, "0", "O") -- replace the numbers in name + s=string.gsub(s, "1", "I") -- replace the numbers in name + s=string.gsub(s, "2", "II") -- + s=string.gsub(s, "3", "III") -- + s=string.gsub(s, "4", "IV") -- + s=string.gsub(s, "5", "V") -- + s=string.gsub(s, "6", "VI") -- + s=string.gsub(s, "7", "VII") -- + s=string.gsub(s, "8", "VIII") -- + s=string.gsub(s, "9", "IX") -- + s=string.gsub(s, "%A", "x") -- Finally still removes all nealfabetic characters that were left there + if string.len(s) > maxmacrolength+1 then s=string.sub(s, 1, maxmacrolength) end -- to limit the maximum length of a macro +return s +end + + +function thirddata.handlecsv.xls2ar(colname) -- convert Excel column name (like A, B, ... AA, AB, ...) into serial number of column (A->1, B->2, ...) + -- No for more than 702 columns (ie last column parametr for this function is ZZ) + -- for example Excel 2003 can handle only up to the column IV! + local colnumber=0 + local colname=colname:upper() + for i=1, string.len(colname) do + local onechar = string.sub(colname,i,i) + colnumber=26*colnumber + (string.byte(onechar) - string.byte('A') + 1) + end + return colnumber +end + + + +function thirddata.handlecsv.ar2xls(arnum) -- convert number to Excel name column + -- For more than 703 columns (ie column A to ZZ) should be a function to modify + -- Excel 2003 can handle only up to the column IV! + local part=math.floor(arnum/26) + local remainder = math.mod(arnum,26) + part = part - (math.mod(arnum,26)==0 and 1 or 0) + remainder = remainder + (math.mod(arnum,26)==0 and 26 or 0) + local ctl ='' + if arnum < 703 then + if part > 0 then + ctl=string.char(64+part) + end + ctl = ctl .. string.char(64+remainder) + else + ctl = 'overZZ' + end + return ctl +end + + +function thirddata.handlecsv.ar2colnum(arnum) -- According to the settings glob. variable returns the column designation of TeX macros + -- generated TeX macros referring to values in columns are numbered a`la EXCEL ie cA, cB, ..., cAA, etc + -- or a`la roman number ie. cI, cII, cIII, cIV, ..., cXVIII, etc + -- if it is "romannumbers" setting, then columns wil numbered by Romna else ala Excel + if string.lower(thirddata.handlecsv.gUserColumnNumbering) == 'xls' then + return thirddata.handlecsv.ar2xls(arnum) -- a la EXCEL + else + return string.upper(converters.romannumerals(arnum)) -- a la big ROMAN - convert Arabic numbers to big Roman. Used for "numbering" column in the TeX macros + end +end + +function thirddata.handlecsv.substitutecontentofcellof(csvfile,column,row,whattoreplace,substitution) +-- Substitute text in cell content of specified CSV file with other text + local csvfile=thirddata.handlecsv.handlecsvfile(csvfile) + local column=thirddata.handlecsv.gColNames[csvfile][column] + local whattoreplace=tostring(whattoreplace) + local substitution=tostring(substitution) + return thirddata.handlecsv.getcellcontentof(csvfile,column,row):gsub(whattoreplace,substitution) +end + +function thirddata.handlecsv.substitutecontentofcell(column,row,whattoreplace,substitution) +-- Substitute text in cell content of current CSV file with other text + local csvfile=thirddata.handlecsv.getcurrentcsvfilename() + local column=thirddata.handlecsv.gColNames[csvfile][column] + return thirddata.handlecsv.substitutecontentofcellof(csvfile,column,row,whattoreplace,substitution) +end + +function thirddata.handlecsv.substitutecontentofcellofcurrentrow(column,whattoreplace,substitution) +-- Substitute text in cell content of current row of current CSV file with other text + local row=thirddata.handlecsv.linepointer() + return thirddata.handlecsv.substitutecontentofcell(column,row,whattoreplace,substitution) +end + +function thirddata.handlecsv.processinputvalue(inputparameter,replacingnumber) +-- when inputparameter is not correct, then return replacingnumber +local returnparameter=inputparameter + if type(inputparameter)~= 'number' then + returnparameter=replacingnumber + end -- +return returnparameter +end + + +-- Main functions and macros: + +function thirddata.handlecsv.hookson() + thirddata.handlecsv.gUseHooks=true +end + +function thirddata.handlecsv.hooksoff() + thirddata.handlecsv.gUseHooks=false +end + +function thirddata.handlecsv.setfiletoscan(filetoscan) + local inpcsvfile=thirddata.handlecsv.handlecsvfile(filetoscan) + thirddata.handlecsv.gCurrentlyProcessedCSVFile=inpcsvfile +end + + +function thirddata.handlecsv.setheader() + thirddata.handlecsv.gCSVHeader=true + context([[\global\issetheadertrue%]]) + context([[\global\notsetheaderfalse%]]) +end + + +function thirddata.handlecsv.unsetheader() + thirddata.handlecsv.gCSVHeader=false + context([[\global\issetheaderfalse%]]) + context([[\global\notsetheadertrue%]]) +end + +function thirddata.handlecsv.setsep(sep) + thirddata.handlecsv.gCSVSeparator=sep +end + +function thirddata.handlecsv.unsetsep() + thirddata.handlecsv.gCSVSeparator=thirddata.handlecsv.gUserCSVSeparator +end + +function thirddata.handlecsv.indexofnotemptyline(sernumline) +local csvfilename=thirddata.handlecsv.getcurrentcsvfilename() + return thirddata.handlecsv.gTableNotEmptyRows[csvfilename][sernumline] +end + +function thirddata.handlecsv.indexofemptyline(sernumline) +local csvfilename=thirddata.handlecsv.getcurrentcsvfilename() + return thirddata.handlecsv.gTableEmptyRows[csvfilename][sernumline] +end + +function thirddata.handlecsv.notmarkemptylines() +local csvfilename=thirddata.handlecsv.getcurrentcsvfilename() + thirddata.handlecsv.gMarkingEmptyLines=false + for row=1,thirddata.handlecsv.gNumRows[csvfilename] do + thirddata.handlecsv.gTableNotEmptyRows[csvfilename][row]=row + end + thirddata.handlecsv.gTableEmptyRows[csvfilename]={} + thirddata.handlecsv.gNumEmptyRows[csvfilename]=0 + thirddata.handlecsv.gNumNotEmptyRows[csvfilename]=thirddata.handlecsv.gNumRows[csvfilename] + context([[\global\emptylinefalse%]]) + context([[\global\notemptylinetrue%]]) + context([[\global\emptylinesmarkingfalse%]]) + context([[\global\emptylinesnotmarkingtrue%]]) +end + +function thirddata.handlecsv.markemptylines() +local csvfilename=thirddata.handlecsv.getcurrentcsvfilename() + thirddata.handlecsv.gTableEmptyRows[csvfilename]={} + thirddata.handlecsv.gTableNotEmptyRows[csvfilename]={} + thirddata.handlecsv.gMarkingEmptyLines=true + local counteremptylines=0 + local counternotemptylines=0 + for row=1,thirddata.handlecsv.gNumRows[csvfilename] do + if thirddata.handlecsv.testemptyrow(row) then + counteremptylines=counteremptylines+1 + thirddata.handlecsv.gTableEmptyRows[csvfilename][counteremptylines]=row + else + counternotemptylines=counternotemptylines+1 + thirddata.handlecsv.gTableNotEmptyRows[csvfilename][counternotemptylines]=row + end + end -- for + thirddata.handlecsv.gNumEmptyRows[csvfilename]=counteremptylines + thirddata.handlecsv.gNumNotEmptyRows[csvfilename]=counternotemptylines + context([[\global\emptylinesmarkingtrue%]]) + context([[\global\emptylinesnotmarkingfalse%]]) +end + + +function thirddata.handlecsv.resetmarkemptylines() +-- do following lines only when file contain completely empty rows and is requiring testing empty lines +local csvfilename=thirddata.handlecsv.getcurrentcsvfilename() + thirddata.handlecsv.gMarkingEmptyLines = thirddata.handlecsv.gUserMarkingEmptyLines + if thirddata.handlecsv.gMarkingEmptyLines then + thirddata.handlecsv.markemptylines() + else thirddata.handlecsv.notmarkemptylines() + end -- if thirddata.handlecsv.gMarkingEmptyLines +end + + +function thirddata.handlecsv.testemptyrow(lineindex) +local csvfilename=thirddata.handlecsv.getcurrentcsvfilename() +local linecontent="" +local isemptyline=false + for column=1,thirddata.handlecsv.gNumCols[csvfilename] do + linecontent=linecontent..thirddata.handlecsv.gTableRows[csvfilename][lineindex][column] + end + if linecontent=="" or linecontent==nil then + isemptyline=true +-- thirddata.handlecsv.gNumEmptyRows[csvfilename]=thirddata.handlecsv.gNumEmptyRows[csvfilename]+1 + end + thirddata.handlecsv.gTableRowsIndex[csvfilename][lineindex]=isemptyline + return isemptyline +end + + +function thirddata.handlecsv.emptylineevaluation(lineindex) + if thirddata.handlecsv.gTableRowsIndex[thirddata.handlecsv.getcurrentcsvfilename()][lineindex] then + context([[\global\emptylinetrue%]]) + context([[\global\notemptylinefalse%]]) + else + context([[\global\emptylinefalse%]]) + context([[\global\notemptylinetrue%]]) + end + return thirddata.handlecsv.gTableRowsIndex[thirddata.handlecsv.getcurrentcsvfilename()][lineindex] +end + + +function thirddata.handlecsv.removeemptylines() +-- This function remove empty rows only from field of variables thirddata.handlecsv.gTableRows! +-- The field is only re-indexed and function does not affect onto the physical input CSV file! +-- When the physical CSV file is reopened by using \open macro, the global field variable +-- thirddata.handlecsv.gTableRows[csvfile] is reset into original state! + thirddata.handlecsv.markemptylines() + local csvfilename=thirddata.handlecsv.getcurrentcsvfilename() + + for i=1,thirddata.handlecsv.gNumNotEmptyRows[csvfilename] do + local indexofnotemptyrow=thirddata.handlecsv.gTableNotEmptyRows[csvfilename][i] + -- i<--indexofnotemptyrow + thirddata.handlecsv.gTableRows[csvfilename][i]=thirddata.handlecsv.gTableRows[csvfilename][indexofnotemptyrow] + end + + for i=thirddata.handlecsv.gNumNotEmptyRows[csvfilename]+1,thirddata.handlecsv.gNumRows[csvfilename] do + thirddata.handlecsv.gTableRows[csvfilename][i]=nil + end + + thirddata.handlecsv.gNumRows[csvfilename]=thirddata.handlecsv.gNumNotEmptyRows[csvfilename] + thirddata.handlecsv.markemptylines() + thirddata.handlecsv.gTableEmptyRows[csvfilename]={} + thirddata.handlecsv.gTableNotEmptyRows[csvfilename]={} +end + + +function thirddata.handlecsv.hooksevaluation() + for i=1,#thirddata.handlecsv.gColumnNames[thirddata.handlecsv.getcurrentcsvfilename()] do + if not thirddata.handlecsv.texmacroisdefined('bch'..thirddata.handlecsv.gColumnNames[thirddata.handlecsv.getcurrentcsvfilename()][i]) then + context.setgvalue('bch'..thirddata.handlecsv.gColumnNames[thirddata.handlecsv.getcurrentcsvfilename()][i],'\\relax') + end + if not thirddata.handlecsv.texmacroisdefined('ech'..thirddata.handlecsv.gColumnNames[thirddata.handlecsv.getcurrentcsvfilename()][i]) then + context.setgvalue('ech'..thirddata.handlecsv.gColumnNames[thirddata.handlecsv.getcurrentcsvfilename()][i],'\\relax') + end + end +end + + +function thirddata.handlecsv.setgetcurrentcsvfile(filename) +-- In the absence of the file name to use the global variable + thirddata.handlecsv.gCurrentlyProcessedCSVFile = (filename ~= nil) and filename or thirddata.handlecsv.gCurrentlyProcessedCSVFile + thirddata.handlecsv.gCurrentlyProcessedCSVFile = (thirddata.handlecsv.gCurrentlyProcessedCSVFile == nil) and filename or thirddata.handlecsv.gCurrentlyProcessedCSVFile + local filename = filename ~= nil and filename or thirddata.handlecsv.gCurrentlyProcessedCSVFile +-- thirddata.handlecsv.gCurrentlyProcessedCSVFile = tostring(filename) + return tostring(filename) +end + +function thirddata.handlecsv.handlecsvfile(filename) +-- not used yet +local filename = tostring(filename) + filename = string.gsub(filename, '"', '') + filename = string.gsub(filename, "'", "") +if not (thirddata.handlecsv.isopenfile(filename)) then + filename = (filename ~= nil) and filename or thirddata.handlecsv.gCurrentlyProcessedCSVFile + filename = (thirddata.handlecsv.gCurrentlyProcessedCSVFile == nil) and filename or thirddata.handlecsv.gCurrentlyProcessedCSVFile + filename = filename ~= nil and filename or thirddata.handlecsv.gCurrentlyProcessedCSVFile + filename = filename ~= '' and filename or thirddata.handlecsv.gCurrentlyProcessedCSVFile +end + return filename +end + +function thirddata.handlecsv.getcurrentcsvfilename() +-- return current (actual) CSV file + return tostring(thirddata.handlecsv.gCurrentlyProcessedCSVFile) +end + + +function thirddata.handlecsv.isopenfile(csvfilename) +-- testing of opening CSV files + local retval=(thirddata.handlecsv.gOpenFiles[csvfilename] ~= nil) + return retval +end + +function thirddata.handlecsv.closecsvfile(csvfilename) +-- manual closing of CSV files + thirddata.handlecsv.gOpenFiles[csvfilename] = nil +end + + +function thirddata.handlecsv.getnumberofopencsvfiles() +-- get the number of open files +local count = 0 +for k, v in pairs(thirddata.handlecsv.gOpenFiles) do + count = count + 1 +end + return count +end + + + +function thirddata.handlecsv.setpointersofopeningcsvfile(inpcsvfile) + thirddata.handlecsv.gCurrentLinePointer[inpcsvfile]=1 + thirddata.handlecsv.gNumLine[inpcsvfile]=1 -- set numline counter of file inpcsvfile + thirddata.handlecsv.resetlinepointerof(inpcsvfile) -- set pointer to begin table (first row) + thirddata.handlecsv.setnumlineof(inpcsvfile,1) + context([[\global\EOFfalse%]]) + context([[\global\notEOFtrue%]]) + thirddata.handlecsv.resetmarkemptylines() +end + +function thirddata.handlecsv.opencsvfile(filetoscan) +-- Open CSV tabule, inicialize variables + -- open the table and load it into the global variable thirddata.handlecsv.gTableRows[filetoscan] + -- if the option thirddata.handlecsv.gCSVHeader==true is enabled, then into glob variable thirddata.handlecsv.gColumnNames[filetoscan] + -- sets the column names from the title, if not then sets XLS notation, ie. cA, cB, cC, ... + -- into global variables thirddata.handlecsv.gNumRows[filetoscan] and thirddata.handlecsv.gNumCols[filetoscan] it saves the number of rows and columns of the table + -- if the file header and the header line does not count the number of rows in the table + -- Additionally, they can defined ConTeXt macros \csvfilename, \numrows a \numcols + + local inpcsvfile=thirddata.handlecsv.setgetcurrentcsvfile(filetoscan) -- set filetoscan as current processed csv file + + if thirddata.handlecsv.isopenfile(inpcsvfile) then -- if file is open, then set needed pointers at first line of file only + thirddata.handlecsv.setpointersofopeningcsvfile(inpcsvfile) + else -- if CSV file is not open, then open it and set all needed variables + + local inpcsvfile=thirddata.handlecsv.setgetcurrentcsvfile(inpcsvfile) + thirddata.handlecsv.gOpenFiles[inpcsvfile]=inpcsvfile -- memory opening file + thirddata.handlecsv.gColNames[inpcsvfile]={} + thirddata.handlecsv.gColumnNames[inpcsvfile]={} + thirddata.handlecsv.gTableRowsIndex[inpcsvfile]={} + thirddata.handlecsv.gTableRows[inpcsvfile]={} + thirddata.handlecsv.gTableEmptyRows[inpcsvfile]={} + thirddata.handlecsv.gTableNotEmptyRows[inpcsvfile]={} + + + local currentlyprocessedcsvfile = io.loaddata(inpcsvfile) + local mycsvsplitter = utilities.parsers.rfc4180splitter{ + separator = thirddata.handlecsv.gCSVSeparator, + quote = thirddata.handlecsv.gCSVQuoter, + strict = true, + } + if thirddata.handlecsv.gCSVHeader then + thirddata.handlecsv.gTableRows[inpcsvfile], thirddata.handlecsv.gColumnNames[inpcsvfile] = mycsvsplitter(currentlyprocessedcsvfile,true) + inspect(thirddata.handlecsv.gTableRows[inpcsvfile]) + inspect(thirddata.handlecsv.gColumnNames[inpcsvfile]) + else -- if thirddata.handlecsv.gCSVHeader + thirddata.handlecsv.gTableRows[inpcsvfile], thirddata.handlecsv.gColumnNames[inpcsvfile] = mycsvsplitter(currentlyprocessedcsvfile) + inspect(thirddata.handlecsv.gTableRows[inpcsvfile]) + thirddata.handlecsv.gColumnNames[inpcsvfile]={} + -- ad now set column names for withoutheader situation: + for i=1,#thirddata.handlecsv.gTableRows[inpcsvfile][1] do + -- OK, but not used: thirddata.handlecsv.gColumnNames[inpcsvfile][i]=thirddata.handlecsv.tmn(thirddata.handlecsv.gTableRows[inpcsvfile][1][i]) + thirddata.handlecsv.gColumnNames[inpcsvfile][i]=tostring(thirddata.handlecsv.ar2xls(i)) -- set XLS notation (fill array with XLS names of columns like 'cA', 'cB', etc.) + end -- for + end -- if thirddata.handlecsv.gCSVHeader + for i=1,#thirddata.handlecsv.gTableRows[inpcsvfile][1] do + thirddata.handlecsv.gColNames[inpcsvfile][tostring(thirddata.handlecsv.tmn(thirddata.handlecsv.gColumnNames[inpcsvfile][i]))] = i -- for indexing use (register names of macros ie 'Firstname' etc...) + thirddata.handlecsv.gColNames[inpcsvfile][tostring(thirddata.handlecsv.gColumnNames[inpcsvfile][i])] = i -- for indexing use (register names of macros ie 'Firstname' etc...) + thirddata.handlecsv.gColNames[inpcsvfile][tostring(thirddata.handlecsv.ar2xls(i))] = i -- for indexcolname macro (register names of macros ie 'A', 'B', etc...) + thirddata.handlecsv.gColNames[inpcsvfile][tostring('c'..thirddata.handlecsv.ar2xls(i))] = i -- for indexcolname macro (register names of macros ie 'cA', 'cB', etc...) + thirddata.handlecsv.gColNames[inpcsvfile][tostring(i)] = i -- for indexcolname macro (register names of macros ie 'cA', 'cB', etc...) + thirddata.handlecsv.gColNames[inpcsvfile][i] = i -- for indexcolname macro (register names of macros ie 'cA', 'cB', etc...) + end -- for + local j=#thirddata.handlecsv.gTableRows[inpcsvfile][1] + for i=1,#thirddata.handlecsv.gTableRows[inpcsvfile][1] do + j=j+1 + thirddata.handlecsv.gColumnNames[inpcsvfile][j]=tostring('c'..thirddata.handlecsv.ar2xls(i)) -- set XLS notation (fill array with XLS names of columns like 'cA', 'cB', etc.) + end -- for + if thirddata.handlecsv.gCSVHeader then + for i=1,#thirddata.handlecsv.gTableRows[inpcsvfile][1] do + j=j+1 + thirddata.handlecsv.gColumnNames[inpcsvfile][j]=tostring(thirddata.handlecsv.ar2xls(i)) -- set XLS notation (fill array with XLS names of columns like 'cA', 'cB', etc.) + end -- for + for i=1,#thirddata.handlecsv.gTableRows[inpcsvfile][1] do + j=j+1 + thirddata.handlecsv.gColumnNames[inpcsvfile][j]=tostring(thirddata.handlecsv.tmn(thirddata.handlecsv.gColumnNames[inpcsvfile][i])) -- maybe TeX incorect names of columns + end -- for + end -- if thirddata.handlecsv.gCSVHeader then + + thirddata.handlecsv.gNumRows[inpcsvfile]=#thirddata.handlecsv.gTableRows[inpcsvfile] -- Getting number of rows + thirddata.handlecsv.gNumCols[inpcsvfile]=#thirddata.handlecsv.gTableRows[inpcsvfile][1] -- Getting number of columns + thirddata.handlecsv.gNumEmptyRows[inpcsvfile]=0 + thirddata.handlecsv.gNumNotEmptyRows[inpcsvfile]=#thirddata.handlecsv.gTableRows[inpcsvfile] + thirddata.handlecsv.setpointersofopeningcsvfile(inpcsvfile) -- set pointers + + if thirddata.handlecsv.gUseHooks then thirddata.handlecsv.hooksevaluation() end + + end -- if thirddata.handlecsv.isopenfile(inpcsvfile) then +return +end -- of thirddata.handlecsv.opencsvfile(file) + + +function thirddata.handlecsv.readlineof(inpcsvfile,numberofline) -- +-- Main function. Read data from specific line of specific file, parse them etc. + local inpcsvfile=thirddata.handlecsv.handlecsvfile(inpcsvfile) + local numberofline=numberofline + local returnpar=false + if type(numberofline)~= 'number' then + if numberofline==nil then + numberofline=thirddata.handlecsv.gCurrentLinePointer[inpcsvfile] + returnpar=true + else numberofline = 0 + end -- if numberofline==nil + end -- if type(numberofline) + if (numberofline > 0 and numberofline <=thirddata.handlecsv.gNumRows[inpcsvfile]) then + thirddata.handlecsv.addtonumlineof(inpcsvfile,1) + thirddata.handlecsv.gCurrentLinePointer[inpcsvfile]=numberofline + returnpar=true + thirddata.handlecsv.assigncontentsof(inpcsvfile,thirddata.handlecsv.gTableRows[inpcsvfile][numberofline]) + context([[\global\EOFfalse\global\notEOFtrue%]]) + else + thirddata.handlecsv.assigncontentsof(inpcsvfile,'nil_line') + if numberofline > thirddata.handlecsv.gNumRows[inpcsvfile] then + context([[\global\EOFtrue\global\notEOFfalse%]]) + end + end -- if (numberofline > 0 +--řešit thirddata.handlecsv.emptylineevaluation(numberofline) + return returnpar -- return true if numberofline is regular line, else return false +end -- function thirddata.handlecsv.readlineof(inpcsvfile,numberofline) -- + + +function thirddata.handlecsv.readline(numberofline) -- +-- Main function. Read data from specific line of specific file, parse them etc. + local csvfile=thirddata.handlecsv.getcurrentcsvfilename() + if type(numberofline) == 'number' then + thirddata.handlecsv.readlineof(csvfile,numberofline) -- + else + thirddata.handlecsv.readlineof(csvfile,thirddata.handlecsv.gCurrentLinePointer[csvfile]) -- + end +end + + +function thirddata.handlecsv.createxlscommandof(xlsname,csvfile) +local inpcsvfile=thirddata.handlecsv.handlecsvfile(csvfile) +local cxlsname=tostring('col'..xlsname) +local docxlsname=tostring('docol'..xlsname) +local xlsname=tostring(''..xlsname) + +-- context([[\def\definice]]..xlsname..[[#1{\ctxlua{context(thirddata.handlecsv.getcellcontentof(']]..inpcsvfile..[[',']]..xlsname..[[','#1'))}}]]) + + interfaces.definecommand (docxlsname, { + arguments = { { "option", "string" } }, + macro = function (opt_1) + if #opt_1>0 then + context(thirddata.handlecsv.getcellcontentof(inpcsvfile,xlsname,tonumber(opt_1))) + else + context(thirddata.handlecsv.getcellcontentof(inpcsvfile,xlsname,thirddata.handlecsv.gCurrentLinePointer[inpcsvfile])) + end + end + }) + interfaces.definecommand(cxlsname, { + macro = function () + context.dosingleempty() + context[docxlsname]() + end + }) +-- interfaces.definecommand ("column"..xlsname, { +-- arguments = { { "option"} }, +-- macro = function (opt_1) +-- if opt_1~="" then +-- context(thirddata.handlecsv.getcellcontentof(inpcsvfile,xlsname,tonumber(opt_1))) +-- else +-- context(thirddata.handlecsv.getcellcontentof(inpcsvfile,xlsname,thirddata.handlecsv.gCurrentLinePointer[inpcsvfile])) +-- end +-- end +-- }) +end + + +function thirddata.handlecsv.createxlscommand(xlsname) +local inpcsvfile=thirddata.handlecsv.getcurrentcsvfilename() +thirddata.handlecsv.createxlscommandof(xlsname,inpcsvfile) +end + + +function thirddata.handlecsv.assigncontentsof(inpcsvfile,line) -- put data into columns macros +-- after read of line this function put content of columns into specific TeX macros... +--if tex.modes['XXL'] then context("XXL mode") else context("not XXL mode") end + local inpcsvfile=thirddata.handlecsv.handlecsvfile(inpcsvfile) + local cutoffinpcsvfile=thirddata.handlecsv.ParseCSVLine(inpcsvfile,".")[1] -- cut filename extension + for i=1,thirddata.handlecsv.gNumCols[inpcsvfile] do + content='nil' -- 1.10.2015 + if line ~= 'nil_line' then content = line[i] end + local puremacroname=thirddata.handlecsv.gColumnNames[inpcsvfile][i] +-- local macroname=cutoffinpcsvfile..thirddata.handlecsv.gColumnNames[inpcsvfile][i] + local macroname=thirddata.handlecsv.gColumnNames[inpcsvfile][i] +-- context("macroname: "..macroname.."\\crlf") + local purexlsname=thirddata.handlecsv.ar2colnum(i) +-- context("purexlsname: "..purexlsname.."\\crlf") + local xlsname='c'..purexlsname +-- context("xlsname: "..xlsname.."\\crlf") + local xlsfilename=thirddata.handlecsv.tmn(cutoffinpcsvfile)..'c'..purexlsname +-- context("xlsfilename: "..xlsfilename.."\\crlf") + local hookxlsname='h'..xlsname + local macroname=thirddata.handlecsv.tmn(macroname) + local puremacroname=thirddata.handlecsv.tmn(puremacroname) +-- context("macroname: "..macroname.."\\crlf") + local hookmacroname='h'..macroname +-- if content == ' ' then tex.print('space') end +-- if content == '' then tex.print('empty') content=[[\empty]] end + context.setgvalue(xlsname, content) -- defining automatic TeX macros \cA, \cB, atd. resp. \cI, \cII, ... containing the contents of the line. Macros with names of the headers are updated automatically + context.setgvalue(xlsfilename, content) -- defining automatic TeX macros \filenamecA, \filenamecB, atd. resp. \cI, \cII, ... containing the contents of the line. Macros with names of the headers are updated automatically + -- was context.setgvalue(macroname,'\\'..xlsname) -- ie for example \let\Name\cA +-- context.setgvalue(macroname,content) -- defining automatic TeX macros \Name, \Date, etc. (names gets from header), containing the contents of the line. Macros with names of the headers are updated automatically + context.setgvalue(puremacroname,content) -- defining automatic TeX macros \Name, \Date, etc. (names gets from header), containing the contents of the line. Macros with names of the headers are updated automatically + -- experimental version in next two lines: + -- this define variants of macros \colA, \colA[8], ... and \colFirstname, \colFirstname[11] etc. + thirddata.handlecsv.createxlscommandof(''..purexlsname,inpcsvfile) -- create macros \colA, \colB, etc. and their variants \colA[row], ... +--if tex.modes['XXX'] then +--context("XXX-"..macroname.."-XXX") +--end + context.setgvalue('col'..macroname,'\\col'..purexlsname) -- and create fullname macros \colFirstname, \colFirstname[5], etc... +-- context.setgvalue(''..macroname,'\\col'..purexlsname) -- and create fullname macros \colFirstname, \colFirstname[5], etc... +-- context.setgvalue(''..macroname,'\\col'..purexlsname) -- and create fullname macros \colFirstname, \colFirstname[5], etc... + -- + interfaces.definecommand ("column"..purexlsname, { + arguments = { { "string"} }, + macro = function (opt_1) + if opt_1~="" then + context(thirddata.handlecsv.getcellcontentof(inpcsvfile,xlsname,tonumber(opt_1))) + else + context(thirddata.handlecsv.getcellcontentof(inpcsvfile,xlsname,thirddata.handlecsv.gCurrentLinePointer[inpcsvfile])) + end + end + }) + -- + -- and now create hooks macros: + if thirddata.handlecsv.gUseHooks then + context.setgvalue(hookxlsname,'\\bch\\bch'..xlsname..'\\'..xlsname..'\\ech'..xlsname..'\\ech') -- defining automatic TeX macros \hcA, \hcB, atd. resp. \hcI, \hcII, ... containing 'hooked' contents of the line. Macros with names of the headers are updated automatically) + context.setgvalue(hookmacroname,'\\bch\\bch'..macroname..'\\'..xlsname..'\\ech'..macroname..'\\ech ') -- defining automatic TeX macros \hName, \hDate, etc. (names gets from header), containing 'hooked' contents of the line. Macros with names of the headers are updated automatically) + end + end -- for i=1, +end -- function thirddata.handlecsv.assigncontentsof(inpcsvfile,line) -- put data into columns macros + + +function thirddata.handlecsv.assigncontents(line) -- put data into columns macros +thirddata.handlecsv.assigncontentsof(thirddata.handlecsv.getcurrentcsvfilename(),line) +end + + +function thirddata.handlecsv.getcellcontentof(csvfile,column,row) +-- Read data from specific cell of specific the csv table + -- local returnparametr='nil' -- 1.10.2015 + local csvfile=thirddata.handlecsv.handlecsvfile(csvfile) + local returnparametr='' -- 9.1.2016 + local column=column + local row=row + if type(column)=='string' then + local testcolumn=thirddata.handlecsv.gColNames[csvfile][column] + if testcolumn==nil then + column=thirddata.handlecsv.xls2ar(column) + else + column=testcolumn + end + else + testcolumn=tonumber(column) + if testcolumn==nil then + column=0 + else + column=testcolumn + end + end + if column<=0 then column=1 end + if column>thirddata.handlecsv.gNumCols[csvfile] then column=thirddata.handlecsv.gNumCols[csvfile] end + if type(row)=='string' then + local testrow=tonumber(row) + if testrow==nil then + row=0 + else + row=testrow + end + end + if type(column)=='number' and type(row)=='number' then + if row>0 and row <=thirddata.handlecsv.gNumRows[csvfile] and column>=0 and column<=thirddata.handlecsv.gNumCols[csvfile] then + returnparametr=thirddata.handlecsv.gTableRows[csvfile][row][column] + elseif row==0 then + returnparametr=thirddata.handlecsv.gColumnNames[csvfile][column] + end + end + return returnparametr +end + + +function thirddata.handlecsv.getcellcontent(column,row) +-- Read data from specific cell of current open csv table + local csvfile=thirddata.handlecsv.getcurrentcsvfilename() + local returnparametr=thirddata.handlecsv.getcellcontentof(csvfile,column,row) + return returnparametr +end + + +function thirddata.handlecsv.nextlineof(csvfile) +-- Move line pointer to next line. + local csvfile=thirddata.handlecsv.handlecsvfile(csvfile) + if thirddata.handlecsv.gCurrentLinePointer[csvfile] > thirddata.handlecsv.gNumRows[csvfile] then + thirddata.handlecsv.gCurrentLinePointer[csvfile]=thirddata.handlecsv.gNumRows[csvfile] + context([[\global\EOFtrue%]]) + context([[\global\notEOFfalse%]]) + else + thirddata.handlecsv.gCurrentLinePointer[csvfile]=thirddata.handlecsv.gCurrentLinePointer[csvfile]+1 + context([[\global\EOFfalse%]]) + context([[\global\notEOFtrue%]]) + end +end + + +function thirddata.handlecsv.nextline() +-- Move line pointer to next line. + local csvfile=thirddata.handlecsv.getcurrentcsvfilename() + thirddata.handlecsv.nextlineof(csvfile) +end + + +function thirddata.handlecsv.previouslineof(csvfile) +-- Move line pointer to previous line. + local csvfile=thirddata.handlecsv.handlecsvfile(csvfile) + if thirddata.handlecsv.gCurrentLinePointer[csvfile] < 2 then + thirddata.handlecsv.gCurrentLinePointer[csvfile] = 1 + else + thirddata.handlecsv.gCurrentLinePointer[csvfile]=thirddata.handlecsv.gCurrentLinePointer[csvfile] - 1 + end + context([[\global\EOFfalse%]]) + context([[\global\notEOFtrue%]]) +end + + +function thirddata.handlecsv.previousline() +-- Move line pointer to previous line. + local csvfile=thirddata.handlecsv.getcurrentcsvfilename() + thirddata.handlecsv.previouslineof(csvfile) +end + + +function thirddata.handlecsv.setlinepointerof(csvfile,numberofline) + local csvfile=thirddata.handlecsv.handlecsvfile(csvfile) + local numberofline = thirddata.handlecsv.processinputvalue(numberofline,thirddata.handlecsv.gCurrentLinePointer[csvfile]) + if numberofline < 1 then numberofline = 1 end + if numberofline > thirddata.handlecsv.gNumRows[csvfile] then + numberofline=thirddata.handlecsv.gNumRows[csvfile] + end + thirddata.handlecsv.gCurrentLinePointer[csvfile]=numberofline + thirddata.handlecsv.readlineof(csvfile,numberofline) +end + + +function thirddata.handlecsv.setlinepointer(numberofline) + local csvfile=thirddata.handlecsv.getcurrentcsvfilename() + thirddata.handlecsv.setlinepointerof(csvfile,numberofline) +end + + +function thirddata.handlecsv.savelinepointer() + local csvfile=thirddata.handlecsv.getcurrentcsvfilename() + thirddata.handlecsv.gSavedLinePointerNo = thirddata.handlecsv.gCurrentLinePointer[csvfile] +end + + +function thirddata.handlecsv.setsavedlinepointer() + thirddata.handlecsv.setlinepointer(thirddata.handlecsv.gSavedLinePointerNo) +end + + +function thirddata.handlecsv.resetlinepointerof(csvfile) +-- Take pointer to first row of table + local csvfile=thirddata.handlecsv.handlecsvfile(csvfile) + thirddata.handlecsv.setlinepointerof(csvfile,1) +end + + +function thirddata.handlecsv.resetlinepointer() +-- Take pointer to first row of table + local csvfile=thirddata.handlecsv.getcurrentcsvfilename() + thirddata.handlecsv.setlinepointerof(csvfile,1) +end + + +function thirddata.handlecsv.linepointerof(csvfile) + local csvfile=thirddata.handlecsv.handlecsvfile(csvfile) + return thirddata.handlecsv.gCurrentLinePointer[csvfile] +end + + +function thirddata.handlecsv.linepointer() + local csvfile=thirddata.handlecsv.getcurrentcsvfilename() + -- return thirddata.handlecsv.gCurrentLinePointer[csvfile] -- cause problem with decimal point for higher versions of Lua + -- return math.tointeger(thirddata.handlecsv.gCurrentLinePointer[csvfile]) -- cause incompatibility for lower version of Lua + return math.floor(tonumber(thirddata.handlecsv.gCurrentLinePointer[csvfile])) -- compatible with lower and higher versions of Lua +end + + +function thirddata.handlecsv.getcurrentlinepointer() -- for compatibility + return thirddata.handlecsv.linepointer() +end + + +function thirddata.handlecsv.getlinepointer() -- for compatibility + return thirddata.handlecsv.linepointer() +end + + +function thirddata.handlecsv.setnumlineof(csvfile,numline) + local csvfile=thirddata.handlecsv.handlecsvfile(csvfile) +thirddata.handlecsv.gNumLine[csvfile]=numline +end + + +function thirddata.handlecsv.setnumline(numline) + local csvfile=thirddata.handlecsv.getcurrentcsvfilename() +thirddata.handlecsv.setnumlineof(csvfile,numline) +end + + +function thirddata.handlecsv.resetnumlineof(csvfile) +local csvfile=thirddata.handlecsv.handlecsvfile(csvfile) + thirddata.handlecsv.setnumlineof(csvfile,0) +end + +function thirddata.handlecsv.resetnumline() +local csvfile=thirddata.handlecsv.getcurrentcsvfilename() + thirddata.handlecsv.resetnumlineof(csvfile) +end + +function thirddata.handlecsv.addtonumlineof(inpcsvfile,numline) + local inpcsvfile=thirddata.handlecsv.handlecsvfile(inpcsvfile) + thirddata.handlecsv.gNumLine[inpcsvfile]=thirddata.handlecsv.gNumLine[inpcsvfile]+numline +end + + +function thirddata.handlecsv.addtonumline(numline) + local inpcsvfile=thirddata.handlecsv.getcurrentcsvfilename() + thirddata.handlecsv.addtonumlineof(inpcsvfile,numline) +end + +function thirddata.handlecsv.numlineof(csvfile) +local csvfile=thirddata.handlecsv.handlecsvfile(csvfile) + return thirddata.handlecsv.gNumLine[csvfile] +end + +function thirddata.handlecsv.numline() +local csvfile=thirddata.handlecsv.getcurrentcsvfilename() + return thirddata.handlecsv.gNumLine[csvfile] +end + + +function thirddata.handlecsv.nextnumlineof(csvfile) +-- Move numline pointer to next number. +local csvfile=thirddata.handlecsv.handlecsvfile(csvfile) + thirddata.handlecsv.gNumLine[csvfile]=thirddata.handlecsv.gNumLine[csvfile]+1 +end + + +function thirddata.handlecsv.nextnumline() +-- Move numline pointer to next number. +local csvfile=thirddata.handlecsv.getcurrentcsvfilename() + thirddata.handlecsv.gNumLine[csvfile]=thirddata.handlecsv.gNumLine[csvfile]+1 +end + + +function thirddata.handlecsv.numrowsof(csvfile) +local csvfile=thirddata.handlecsv.handlecsvfile(csvfile) +-- context(thirddata.handlecsv.gNumRows[csvfile]) + return thirddata.handlecsv.gNumRows[csvfile] +end + +function thirddata.handlecsv.numrows() +local csvfile=thirddata.handlecsv.getcurrentcsvfilename() +-- context(thirddata.handlecsv.gNumRows[csvfile]) + return thirddata.handlecsv.gNumRows[csvfile] +end + + +function thirddata.handlecsv.numemptyrows() + return thirddata.handlecsv.gNumEmptyRows[thirddata.handlecsv.getcurrentcsvfilename()] +end + + +function thirddata.handlecsv.numnotemptyrows() +return thirddata.handlecsv.gNumRows[thirddata.handlecsv.getcurrentcsvfilename()]-thirddata.handlecsv.gNumEmptyRows[thirddata.handlecsv.getcurrentcsvfilename()] +end + + +function thirddata.handlecsv.numcolsof(csvfile) +local csvfile=thirddata.handlecsv.handlecsvfile(csvfile) + context(thirddata.handlecsv.gNumCols[csvfile]) +end + +function thirddata.handlecsv.numcols() +local csvfile=thirddata.handlecsv.getcurrentcsvfilename() + context(thirddata.handlecsv.gNumCols[csvfile]) +-- thirddata.handlecsv.numcolsof(csvfile) +end + + +function thirddata.handlecsv.resethooks() +-- initialize ConTeXt hooks + context([[% + \letvalue{blinehook}=\relax% + \letvalue{elinehook}=\relax% + \letvalue{bfilehook}=\relax% + \letvalue{efilehook}=\relax% + \letvalue{bch}=\relax% + \letvalue{ech}=\relax% + ]]) +end + + +function thirddata.handlecsv.string2context(str2ctx) +-- for safety writen + local s=str2ctx + s=string.gsub(s, "%%(.-)\n", "\n") -- remove TeX comments from string. From % character to the end of line + -- s=string.gsub(s, '\n', "") + context(s) + -- texsprint(s) -- for debugging ... +end + + +function thirddata.handlecsv.doloopfromto(from, to, action) + context[[\opencsvfile]] + context[[\edef\tempnumline{\numline}]] -- 23.6.2017 + context[[\resetnumline]] -- uncommented 23.6.2017 + if thirddata.handlecsv.gUseHooks then context[[\bfilehook]] end + context[[\removeunwantedspaces]] + local csvfile=thirddata.handlecsv.getcurrentcsvfilename() + local gnumrows=thirddata.handlecsv.gNumRows[csvfile]+0 + local from=from+0 + local to=to+0 + local step=1 + local docycle=true + if (from>gnumrows and to>gnumrows) then docycle=false end + if docycle then + if from>to then + step=-1 + if from>gnumrows then from=gnumrows end + if to<0 then to=0 end + else -- if from<=to + if to>gnumrows then to=gnumrows end + if from<0 then from=1 end + end + for i=from, to, step do + if thirddata.handlecsv.gUseHooks then context[[\blinehook]] end + context([[\readline{]]..i..[[}]]) -- + context(action) + if thirddata.handlecsv.gUseHooks then context[[\elinehook]] end + end + end -- docycle +-- context[[\removeunwantedspaces]] +if thirddata.handlecsv.gUseHooks then context[[\efilehook]] end +context[[\setnumline{\tempnumline}]] -- 23.6.2017 +end -- function thirddata.handlecsv.doloopfromto + + +function thirddata.handlecsv.doloopfornext(numberofrows, action) + if thirddata.handlecsv.gUseHooks then context[[\bfilehook]] end + context[[\removeunwantedspaces]] + local csvfile=thirddata.handlecsv.getcurrentcsvfilename() + local gnumrows=thirddata.handlecsv.gNumRows[csvfile]+0 + local from=thirddata.handlecsv.gCurrentLinePointer[csvfile]+0 + local to=thirddata.handlecsv.gCurrentLinePointer[csvfile]+numberofrows + local step=1 + local docycle=true + if from>to then + step=-1 + if from>gnumrows then from=gnumrows end + if to<0 then to=0 end + else -- if from<=to + if to>gnumrows then to=gnumrows end + if from<0 then from=1 end + end + for i=from, to-step, step do + if thirddata.handlecsv.gUseHooks then context[[\blinehook]] end + context([[\readline{]]..i..[[}]]) -- context(thirddata.handlecsv.readline(i)) + context(action) + if thirddata.handlecsv.gUseHooks then context[[\elinehook]] end + end + thirddata.handlecsv.addtonumline(-1) +context[[\removeunwantedspaces]] +if thirddata.handlecsv.gUseHooks then context[[\efilehook]] end +context[[\nextrow]] +end -- function thirddata.handlecsv.doloopfornext + + + +-- ConTeXt source: +local string2print=[[% +% library newifs for testing during processing CSV table +\newif\ifissetheader% +\newif\ifnotsetheader% +\newif\ifEOF% +\newif\ifnotEOF% +\newif\ifemptyline% +\newif\ifnotemptyline% +\newif\ifemptylinesmarking% setting by macros \markemptylines and \notmarkemptylines +\newif\ifemptylinesnotmarking% setting by \markemptylines and \notmarkemptylines + + +% Macros defining above in source text: +\let\lineaction\empty% set user define macro into default value +\def\resethooks{\ctxlua{context(thirddata.handlecsv.resethooks())}} +\resethooks % -- DO IT NOW !!! +\def\hookson{\ctxlua{thirddata.handlecsv.hookson()}} +\let\usehooks\hookson % -- synonym only +\def\hooksoff{\ctxlua{thirddata.handlecsv.hooksoff()}} +\def\setheader{\ctxlua{thirddata.handlecsv.setheader()}} +\def\unsetheader{\ctxlua{thirddata.handlecsv.unsetheader()}} +\let\resetheader\unsetheader % -- for compatibility +\def\setsep#1{\ctxlua{thirddata.handlecsv.setsep('#1')}} +\def\unsetsep{\ctxlua{thirddata.handlecsv.unsetsep()}} +\let\resetsep\unsetsep % -- for compatibility +\def\setfiletoscan#1{\ctxlua{thirddata.handlecsv.setfiletoscan('#1');thirddata.handlecsv.opencsvfile()}} +\def\setcurrentcsvfile[#1]{\ctxlua{thirddata.handlecsv.setgetcurrentcsvfile('#1')}} + + +\def\numrows{\ctxlua{context(thirddata.handlecsv.numrows())}} +\def\numrowsof[#1]{\ctxlua{context(thirddata.handlecsv.numrowsof('#1'))}} +\def\numcols{\ctxlua{context(thirddata.handlecsv.gNumCols[thirddata.handlecsv.gCurrentlyProcessedCSVFile])}} +\def\numcolsof[#1]{\ctxlua{context(thirddata.handlecsv.gNumCols['#1'])}} +\def\currentcsvfile{\ctxlua{context(thirddata.handlecsv.getcurrentcsvfilename())}} +\let\csvfilename\currentcsvfile % for compatibility using + + +\def\numemptyrows{\ctxlua{context(thirddata.handlecsv.numemptyrows())}} +\def\numnotemptyrows{\ctxlua{context(thirddata.handlecsv.numnotemptyrows())}} + + +% usefull tool macros : + +% Pass the contents of the macro into parameter +\def\thenumexpr#1{\the\numexpr(#1+0)} +% Add content (#2) into content of macro #1 +\long\def\addto#1#2{\expandafter\def\expandafter#1\expandafter{#1#2}} +% Expanded version of previous macro +\long\def\eaddto#1#2{\edef#1{#1#2}} + + + +% Get content of specific cell of CSV table. Calling: \csvcell[column number,row number] OR \csvcell['ColumnName',row number] +\def\getcsvcell[#1,#2]{\ctxlua{context(thirddata.handlecsv.getcellcontent(#1,#2))}}% +%%%%%\def\getcsvcell[#1,#2]{\if!#2!\ctxlua{context(thirddata.handlecsv.getcellcontent(#1,thirddata.handlecsv.gCurrentLinePointer[thirddata.handlecsv.getcurrentcsvfilename()]))}\else\ctxlua{context(thirddata.handlecsv.getcellcontent(#1,#2))}\fi}% + +% Get content of specific cell of CSV table. Calling: \csvcell[column number,row number] OR \csvcell['ColumnName',row number] +\def\getcsvcellof[#1][#2,#3]{\ctxlua{context(thirddata.handlecsv.getcellcontentof("#1",#2,#3))}}% + + +% Get content of specific cell of CSV table. Calling: \csvcell[column number,row number or row number getting from macro] OR \csvcell['ColumnName',row number or row number getting from macro] +\def\csvcell[#1,#2]{\getcsvcell[#1,\the\numexpr(#2+0)]}% +%\def\csvcell\getcsvcell + + +% Get content of specific cell of current line of CSV table. Calling: \currentcell{column number} OR \currentcell{'ColumnName'} +\def\currentcsvcell#1{\getcsvcell[#1,\thenumexpr{\linepointer}]}% +\let\currcell\currentcsvcell + +% Get content of specific cell of next line of CSV table. Calling: \nextcell{column number} OR \nextcell{'ColumnName'} +\def\nextcsvcell#1{\ifnum\linepointer<\numrows{\getcsvcell[#1,\thenumexpr{\linepointer+1}]}\fi}% +\let\nextcell\nextcsvcell + +% Get content of specific cell of previous line of CSV table. Calling: \previouscell{column number} OR \previouscell{'ColumnName'} +\def\previouscsvcell#1{\ifnum\linepointer>1{\getcsvcell[#1,\thenumexpr{\linepointer-1}]}\fi}% +\let\prevcell\previouscsvcell + + +% Get column name of n-th column of CSV table. When is set header, then get headername else get XLSname +\def\colnameof[#1][#2]{\ctxlua{context(thirddata.handlecsv.gColumnNames['#1'][#2])}}% +\def\colname[#1]{\ctxlua{context(thirddata.handlecsv.gColumnNames[thirddata.handlecsv.getcurrentcsvfilename()][#1])}}% + +% Get index (ie serrial number) of strings columns names (own name or XLS name) +\def\indexcolnameof[#1][#2]{\ctxlua{context(thirddata.handlecsv.gColNames['#1'][#2])}}% +\def\indexcolname[#1]{\ctxlua{context(thirddata.handlecsv.gColNames[thirddata.handlecsv.getcurrentcsvfilename()][#1])}}% + +% Get (alternative) XLS column name (of n-th column) +\def\xlscolname[#1]{\ctxlua{context(thirddata.handlecsv.ar2colnum(#1))}}% + +% Get (alternative) XLS column name (of n-th column) +\def\cxlscolname[#1]{\ctxlua{context('c'..thirddata.handlecsv.ar2colnum(#1))}}% + +% Get column TeX name of n-th column of CSV table. When is set header, then get headername else get XLSname +\def\texcolname[#1]{\ctxlua{context(thirddata.handlecsv.tmn(thirddata.handlecsv.gColumnNames[thirddata.handlecsv.getcurrentcsvfilename()][#1]))}}% + + +% Get content of n-th column of current row +\def\columncontent[#1]{% +\getcsvcell[#1,\ctxlua{context(thirddata.handlecsv.linepointer())}] % +%\getcsvcell[#1,\linepointer]% +%\getcsvcell[#1,\ctxlua{context(thirddata.handlecsv.linepointer())}]% +%\ctxlua{context(tostring(thirddata.handlecsv.getcellcontent(#1,8)))} +}% + +% Substitution of text #2 in cell content by text #3. Substitution is done in the current column of column #1 (number, XLS name or cX name) +\def\replacecontentin#1#2#3{\ctxlua{context(thirddata.handlecsv.substitutecontentofcellofcurrentrow('#1','#2','#3'))}}% + +% Get number from XLS column name (ie n-th column) +\def\numberxlscolname[#1]{\ctxlua{context(thirddata.handlecsv.xls2ar(#1))}}% +%%%\def\columncontent[#1]{\ctxlua{context(thirddata.handlecsv.getcellcontent(#1,thirddata.handlecsv.linepointer()))}} +%%%\def\columncontent[#1]{\ctxlua{context(thirddata.handlecsv.getcellcontent(thirddata.handlecsv.gColNames[#1],thirddata.handlecsv.linepointer()))}} +\def\columncontentof[#1][#2]{\ctxlua{context(thirddata.handlecsv.getcellcontentof('#1',thirddata.handlecsv.gColNames['#1'][#2],thirddata.handlecsv.linepointerof('#1')))}} +\def\columncontent[#1]{\ctxlua{context(thirddata.handlecsv.getcellcontent(thirddata.handlecsv.gColNames[thirddata.handlecsv.getcurrentcsvfilename()][#1],thirddata.handlecsv.linepointerof(thirddata.handlecsv.getcurrentcsvfilename())))}} +\def\resetlinepointer{\ctxlua{context(thirddata.handlecsv.resetlinepointer())}} +\def\resetlinepointerof[#1]{\ctxlua{context(thirddata.handlecsv.resetlinepointerof('#1'))}} +\let\resetlineno\resetlinepointer +\let\resetsernumline\resetlinepointer +\def\setnumline#1{\ctxlua{thirddata.handlecsv.setnumline(#1)}} +\def\resetnumline{\ctxlua{context(thirddata.handlecsv.resetnumline())}} +\resetnumline % DO IT NOW +\def\linepointer{\ctxlua{context(thirddata.handlecsv.linepointer())}} +\def\linepointerof[#1]{\ctxlua{context(thirddata.handlecsv.linepointerof('#1'))}} +\let\lineno\linepointer +\let\sernumline\linepointer +\def\numline{\ctxlua{context(thirddata.handlecsv.numline())}} +\def\addtonumline#1{\ctxlua{thirddata.handlecsv.addtonumline(#1)}} +%\def\setlinepointer#1{\ctxlua{thirddata.handlecsv.setlinepointer(#1);thirddata.handlecsv.readline(#1)}} +\def\setlinepointerof[#1]#2{\ctxlua{thirddata.handlecsv.setlinepointerof('#1',#2)}} +\def\setlinepointer#1{\ctxlua{thirddata.handlecsv.setlinepointer(#1)}} +\def\savelinepointer{\ctxlua{thirddata.handlecsv.savelinepointer()}} +\let\savelineno\savelinepointer % synonym +\def\setsavedlinepointer{\ctxlua{thirddata.handlecsv.setsavedlinepointer()}} +\let\setsavedlineno\setsavedlinepointer % synonym +\def\indexofnotemptyline#1{\ctxlua{context(thirddata.handlecsv.indexofnotemptyline(#1))}} +\def\indexofemptyline#1{\ctxlua{context(thirddata.handlecsv.indexofemptyline(#1))}} +\def\notmarkemptylines{\ctxlua{thirddata.handlecsv.notmarkemptylines()}} +\def\markemptylines{\ctxlua{thirddata.handlecsv.markemptylines()}} +\def\resetmarkemptylines{\ctxlua{thirddata.handlecsv.resetmarkemptylines()}}% +\def\removeemptylines{\ctxlua{thirddata.handlecsv.removeemptylines()}}% +\def\nextlineof[#1]{\ctxlua{thirddata.handlecsv.nextlineof('#1')}} % -- macro for skip to next line. \nextlineof no read data from current line unlike \nextrow macro. +\def\nextline{\ctxlua{thirddata.handlecsv.nextline()}} % -- macro for skip to next line. \nextline no read data from current line unlike \nextrow macro. +\def\prevlineof[#1]{\ctxlua{thirddata.handlecsv.previouslineof('#1')}} % -- macro for skip to previous line. \prevlineof no read data from current line unlike \prevrowof macro. +\def\prevline{\ctxlua{thirddata.handlecsv.previousline()}} % -- macro for skip to previous line. \prevline no read data from current line unlike \prevrow macro. +\def\nextnumline{\ctxlua{thirddata.handlecsv.nextnumline()}} % -- macro for add numline counter. +%\def\nextrow{\readline\nextline} % -- For compatibility +\def\nextrow{\nextline\readline} % -- For compatibility (changed 2015-09-22) +\def\nextrowof[#1]{\nextlineof[#1]\readlineof[#1]{\ctxlua{context(thirddata.handlecsv.linepointerof('#1'))}}} % -- For compatibility (changed 2015-09-22) +%\def\nextrowof[#1]{\nextlineof[#1]\readlineof[#1]{\ctxlua{context(thirddata.handlecsv.gCurrentLinePointer['#1'])}}} % -- For compatibility (changed 2015-09-22) +\def\prevrow{\prevline\readline} +\def\prevrowof[#1]{\prevlineof[#1]\readlineof[#1]{\ctxlua{context(thirddata.handlecsv.linepointerof('#1'))}}} +\def\exitlooptest{\ifEOF\exitloop\else\nextrow\fi} + + + + +% MAIN CONTEXT MACRO DEFINITIONS + +% Open CSV file. Syntax: \opencsvfile or \opencsvfile{filename}. +\def\opencsvfile{% + \dosingleempty\doopencsvfile% +}% + +\def\doopencsvfile[#1]{% + \dosinglegroupempty\dodoopencsvfile% +}% + +\def\dodoopencsvfile#1{% + \iffirstargument% + \ctxlua{thirddata.handlecsv.opencsvfile("#1")}% + \doifnot{\env{MainLinePointer}}{}{\setlinepointer{\env{MainLinePointer}}}% added by Pablo + \else% + \ctxlua{thirddata.handlecsv.opencsvfile()}% + \fi% +}% + + +% manual closing of CSV file +\def\closecsvfile#1{\ctxlua{thirddata.handlecsv.closecsvfile("#1")}} + +% Read data from n-th line of CSV table. Calling without parameter read current line (pointered by global variable) +\def\readline{\dosingleempty\doreadline}% + +\def\doreadline[#1]{\dosinglegroupempty\dodoreadline}% + +% They must remain in such a compact form, otherwise it returns unwanted gaps !!!! +\def\dodoreadline#1{\iffirstargument\ctxlua{thirddata.handlecsv.readline(#1)}\else\ctxlua{thirddata.handlecsv.readline(thirddata.handlecsv.gCurrentLinePointer[thirddata.handlecsv.gCurrentlyProcessedCSVFile])}\fi}% + + +\def\readlineof[#1]#2{\ctxlua{thirddata.handlecsv.readlineof('#1',#2)}} + +%\def\readline{\ctxlua{thirddata.handlecsv.readline(thirddata.handlecsv.gCurrentLinePointer[thirddata.handlecsv.gCurrentlyProcessedCSVFile])}}% + + +\def\readandprocessparameters#1#2#3#4{% + \edef\firstparam{#1}% + \edef\secondparam{#2}% + \edef\thirdparam{#3}% + \def\fourthparam{#4}% + \edef\paroperator{#2}% + % operator '==' is for strings comparing converted to 'eq' operator; a blank space before the percent sign is strictly required!!! + \ctxlua{if '#2'=="==" and not(type(tonumber('#1'))=='number' and type(tonumber('#3'))=='number') then context('\\def\\paroperator{eq}') end}% + % operator '~=' is for strings comparing converted to 'neq' operator; a blank space before the percent sign is strictly required !!! + \ctxlua{if '#2'=="~=" and not(type(tonumber('#1'))=='number' and type(tonumber('#3'))=='number') then context('\\def\\paroperator{neq}') end}% +}% + +% MACROS FOR CYCLES PROCESSING. DO ACTIONS IN CYCLES + + +% In this function to remove unwanted gaps +% 1. \doloopfromto{from}{to}{action} +% do action "action" from line "from" to line "to" of open CSV file +\def\doloopfromto#1#2#3{\ctxlua{thirddata.handlecsv.doloopfromto([==[\thenumexpr{#1}]==],[==[\thenumexpr{#2}]==],[==[\detokenize{#3}]==])}}% +%\def\doloopfromto#1#2#3{\ctxlua{thirddata.handlecsv.doloopfromto([==[\thenumexpr{#1}]==],[==[\thenumexpr{#2}]==],[==[\expanded{#3}]==])}}% + +\def\Doloopfromto#1#2#3{% deprecated - old version - no longer recommended + {\opencsvfile}% + {\resetnumline}% + \bfilehook% + \removeunwantedspaces% + \ifnum#1<#2\dostepwiserecurse{#1}{#2}{1}{\blinehook{\readline{\recurselevel}}#3\elinehook}% + \else\dostepwiserecurse{#1}{#2}{-1}{\blinehook{\readline{\recurselevel}}#3\elinehook}% + \fi% + \removeunwantedspaces% + \efilehook% +}% + +% 2. \doloopforall % implicit do \lineaction for all lines of open CSV table +% \doloopforall{\action} % do \action macro for all lines of open CSV table +\def\doloopforall{\dosinglegroupempty\doloopforAll}% + +\def\doloopforAll#1{% + \doifsomethingelse{#1}{%1 args. + \doloopfromto{1}{\numrows}{#1}% + }{% + \doloopfromto{1}{\numrows}{\lineaction}% + }% +}% + +% 3. \doloopaction % implicit use \lineaction macro +% \doloopaction{\action} % use \action macro for all lines of open CSV file +% \doloopaction{\action}{4} % use \action macro for first 4 lines +% \doloopaction{\action}{2}{5} % use \action macro for lines from 2 to 5 +\def\doloopaction{\dotriplegroupempty\doloopAction} + +\def\doloopAction#1#2#3{% +\opencsvfile% +% \resetnumline % commented 22.6.2017 +\doifsomethingelse{#3}{%3 args. + \doloopfromto{#2}{#3}{#1}% if 3 arguments then do #1 macro from #2 line to #3 line + }{% + \doifsomethingelse{#2}{%2 args. + \doloopfromto{1}{#2}{#1}% if 2 arguments then do #1 macro for first #2 lines + }% + {\doifsomethingelse{#1}{% 1 arg. + \doloopfromto{1}{\numrows}{#1}% + }{% if without arguments then do \lineaction macro for all lines + \doloopfromto{1}{\numrows}{\lineaction}% + }% + }% + }% +}% + + +% 4. \doloopif{value1}{[compare_operator]}{value2}{macro_for_doing} % [compareoperators] <, >, ==(eq), ~=(neq), >=, <=, in, ~in, until, while +% actions for rows of open CSV file which are responded of condition +\def\doloopif#1#2#3#4{% + \edef\tempnumline{\numline}% 23.6.2017 + \readandprocessparameters{#1}{#2}{#3}{#4}% + \removeunwantedspaces% 25.3.2019 + % \resetnumline % 22.6.2017 + \bfilehook% + % and now process actual operator + \processaction[\paroperator][% + <=>{% {number1}{<}{number2} ... Less + \doloopfromto{1}{\numrows}{\ctxlua{if #1<#3 then context('\\blinehook\\fourthparam\\elinehook') else thirddata.handlecsv.addtonumline(-1) end}}% + },% end < ... Less + >=>{% {number1}{>}{number2} ... Greater + \doloopfromto{1}{\numrows}{\ctxlua{if #1>#3 then context('\\blinehook\\fourthparam\\elinehook') else thirddata.handlecsv.addtonumline(-1) end}}% + },% end > ... Greater + ===>{% {number1}{==}{number2} ... Equal + \doloopfromto{1}{\numrows}{\ctxlua{if #1==#3 then context('\\blinehook\\fourthparam\\elinehook') else thirddata.handlecsv.addtonumline(-1) end}}% + },% end == ... Equal + ~==>{% {number1}{~=}{number2} ... Not Equal + \doloopfromto{1}{\numrows}{\ctxlua{if #1~=#3 then context('\\blinehook\\fourthparam\\elinehook') else thirddata.handlecsv.addtonumline(-1) end}}% + },% end ~= ... Not Equal + >==>{% {number1}{>=}{number2} ... GreaterOrEqual + \doloopfromto{1}{\numrows}{\ctxlua{if #1>=#3 then context('\\blinehook\\fourthparam\\elinehook') else thirddata.handlecsv.addtonumline(-1) end}}% + },% end >= ... GreaterOrEqual + <==>{% {number1}{<=}{number2} ... LessOrEqual + \doloopfromto{1}{\numrows}{\ctxlua{if #1<=#3 then context('\\blinehook\\fourthparam\\elinehook') else thirddata.handlecsv.addtonumline(-1) end}}% + },% end <= ... LessOrEqual + eq=>{% command {string1}{==}{string2} is converted to command command {string1}{eq}{string2} ... string1 is equal string2 + \doloopfromto{1}{\numrows}{\doifelse{#1}{#3}{\blinehook\fourthparam\elinehook}{\addtonumline{-1}}}% 23.06.2017 + %%%%%\doloopfromto{1}{\numrows}{\ctxlua{if '#1'=='#3' then context('\\blinehook\\fourthparam\\elinehook') else thirddata.handlecsv.addtonumline(-1) end}}% + },% end eq + neq=>{% command {string1}{~=}{string2} is converted to command command {string1}{neq}{string2} ... string1 is not equal string2 + \doloopfromto{1}{\numrows}{\doifelse{#1}{#3}{\ctxlua{thirddata.handlecsv.addtonumline(-1)}}{\blinehook\fourthparam\elinehook}}% 23.06.2017 + %%%%%\doloopfromto{1}{\numrows}{\ctxlua{if '#1'~='#3' then context('\\blinehook\\fourthparam\\elinehook') else thirddata.handlecsv.addtonumline(-1) end}}% + },% end neq + in=>{% {substring}{in}{string} ... substring is contained inside string + \doloopfromto{1}{\numrows}{\doifinstringelse{#1}{#3}{\blinehook\fourthparam\elinehook}{\addtonumline{-1}}}% \doifincsnameelse + },% end in + ~in=>{% {substring}{~in}{string} ... substring is not contained inside string + \doloopfromto{1}{\numrows}{\doifinstringelse{#1}{#3}{\addtonumline{-1}}{\blinehook\fourthparam\elinehook}}% \doifincsnameelse + },% end notin + repeatuntil=>{% {substring}{until}{string} ... % Repeats the action until the condition is met. If it is not never met, will list all record + \doloop{\ctxlua{if '#1'=='#3' then context('\\exitloop') else context('\\ifEOF\\exitloop\\else\\blinehook\\fourthparam\\elinehook\\nextrow\\fi') end}}% + },% end until % the comma , is very important here!!! + whiledo=>{% {substring}{untilneq}{string} ... % Repeat action when the condition is met. When the condition is not met for the first line, the action will NOT BE performed! + \doloop{\ctxlua{if '#1'~='#3' then context('\\exitloop') else context('\\removeunwantedspaces\\blinehook\\fourthparam\\elinehook\\ifEOF\\exitloop\\else\\nextrow\\fi') end}}% + },% end untilneq % the comma , is very important here!!! + ]% end of \processaction% + \efilehook% + \setnumline{\tempnumline}% + \removeunwantedspaces% 30.3.2019 +} % end of \doloopif + + +% specific variations of previous macro \doloopif +\letvalue{doloopifnum}=\doloopif %\doloopifnum{value1}{[compare_operator]}{value2}{macro_for_doing}% [compareoperators] ==, ~=, >, <, >=, <= % FOR COMPATIBILITY ONLY +\def\doloopuntil#1#2#3{\doloopif{#1}{repeatuntil}{#2}{#3}}% \doloopuntil{\Trida}{3.A}{\tableaction}% REPEAT-UNTIL loop: Repeats the action until the condition is met. +\letvalue{repeatuntil}=\doloopuntil% +\def\doloopwhile#1#2#3{\doloopif{#1}{whiledo}{#2}{#3}}% \doloopwhile{\Trida}{3.A}{\tableaction}% Repeat action when the condition is met. +\letvalue{whiledo}=\doloopwhile% + +% 5. \filelineaction % implicit do \lineaction for all lines of current open CSV table +% \filelineaction{filename.csv} % do \lineaction macro for all lines of specific CSV table (filename.csv) +\def\filelineaction{\dotriplegroupempty\dofilelineaction}% + +\def\dofilelineaction#1#2#3{% + \doifelsenothing{#1}% + {\opencsvfile\doloopaction%0 parameter - open actual CSV file and do action + }% + {\doifelsenothing{#2}% + {\opencsvfile{#1}\doloopaction%1 parameter - parameter = filename + }% + {\doifelsenothing{#3}% + {\opencsvfile{#1}\doloopaction{\lineaction}{#2}%2 parameters, 1st parameter = filename, 2nd parameter = num of lines + }% + {\opencsvfile{#1}\doloopaction{\lineaction}{#2}{#3}%3 parameters, 1st parameter = filename, 2nd parameter = from line, 3rd parameter = to line + }}}% +}% + +% 6. \doloopfornext{<numberofrows>}{<action>} +% do action <action> for next <number> of rows from current line of open CSV file +\def\doloopfornext#1#2{\ctxlua{thirddata.handlecsv.doloopfornext([==[\thenumexpr{#1}]==],[==[\detokenize{#2}]==])}}% + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Complete listing macros and commands that can be used (to keep track of all defined macros): +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% \ifissetheader, \ifnotsetheader +% \ifEOF, \ifnotEOF +% \ifemptyline, \ifnotemptyline +% \ifemptylinesmarking, \ifemptylinesnotmarking (they can be set by macros \markemptylines, \notmarkemptylines and \resetmarkemptylines) +% \hookson, \hooksoff +% \resethooks +% user defined hooks macros: \bfilehook, \efilehook, \blinehook, \elinehook, +% \setheader, \unsetheader, (\resetheader - compatibility synonym) +% \setsep{<columnseparator>}, \unsetsep, (\resetsep - compatibility synonym) +% \setfiletoscan{<filetoprocess>} +% \numrows, \numemptyrows, \numnotemptyrows +% \numcols +% \csvfilename +% \thenumexp{<expression>} +% \addto\anymacro{<addingnonexpandedcontent>}, \eaddto\anymacro{<addingexpandedcontent>} +% \getcsvcell[<columnnumber or columnname>,<rownumber>], \csvcell[<columnnumber or columnname>,<rownumber>] +% \currentcell{<columnnumber or columnname}, \nextcell{<columnnumber or columnname}, \previouscell{<columnnumber or columnname} +% and their synonyms \currcell{}, \nextcell{}, \prevcell{} +% \colname[numberofcolumn], \xlscolname[<numberofcolumn>], \cxlscolname[<numberofcolumn>], \texcolname[<numberofcolumn>] +% \indexcolname[<'columnname' or 'xlsname'>] +% \columncontent[<numberofcolumn> or <'columnname'> or <'xlsname'>] +% \numberxlscolname[<'xlsname'>] +% \linepointer, (\lineno, \sernumline are synonyms), \resetlinepointer, \resetlinepointerof[<csvfile>], (\resetlineno, \resetsernumline are synonyms), \setlinepointer{<numberofline>} +% \savelineno=\savelinepointer, \setsavedlineno=\setsavedlinepointer +% \numline, \setnumline{<numberofline>}, \resetnumline +% \addtonumline{<number>} +% \indexofnotemptyline{}, \indexofemptyline{} +% \markemptylines, \notmarkemptylines, \resetmarkemptylines, \removeemptylines +% \nextlineof[csvfile], \prevlineof[csvfile], \nextline, \prevline +% \nextnumline +% \nextrowof[csvfile], \prevrowof[csvfile], \nextrow, \prevrow +% \exitlooptest +% \opencsvfile, \opencsvfile{<filename>}, \closecsvfile{<filename>} +% \readline, \readline{<numberofline>} +% \readandprocessparameters#1#2#3#4 -- for internal use only +% \replacecontentin{<colname/colnumber>}{<substitutefrom>}{<substituteto>} +% +% Module predefined cycles for processing of lines CSV table: +% \doloopfromto{<fromnumblerline>}{<tonumblerline}{<\actionmacro>} +% \doloopforall, \doloopforall{<\actionmacro>} +% \doloopaction, \doloopaction{<\actionmacro>}, \doloopaction{<\actionmacro>}{<tonumblerline>}, \doloopaction{<\actionmacro>}{<fromnumblerline>}{<tonumblerline>} +% \doloopif{<value1>}{<compare_operator>}{value2}{<\actionmacro>}, (\doloopifnum{<value1>}{<compare_operator>}{value2}{<\actionmacro>} is synonym) +% \doloopuntil{<value1>}{<value2>}{<\actionmacro>} = \repeatuntil{<value1>}{<value2>}{<\actionmacro>} +% \doloopwhile{<value1>}{<value2>}{<\actionmacro>} = \doloopwhiledo{<value1>}{<value2>}{<\actionmacro>} +% \filelineaction, \filelineaction{<filename>} +% \doloopfornext{<+/-numberofrows>}{<\actionmacro>} % use \setlinepointer, \resetlinepointer (and then set it up \setnumline) to set line pointer. Opening of CSV file automatically reset line pointer. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +]] + +-- write definitions into ConTeXt: +thirddata.handlecsv.string2context(string2print) + diff --git a/macros/context/contrib/context-handlecsv/tex/context/third/handlecsv/t-handlecsv.tex b/macros/context/contrib/context-handlecsv/tex/context/third/handlecsv/t-handlecsv.tex new file mode 100644 index 0000000000..b7f2a97db3 --- /dev/null +++ b/macros/context/contrib/context-handlecsv/tex/context/third/handlecsv/t-handlecsv.tex @@ -0,0 +1,29 @@ +%D \module +%D [ file=t-handlecsv.tex, +%D version=2018.04.07, +%D title=HandleCSV module, +%D subtitle=CSV file handling, +%D author=Jaroslav Hajtmar, +%D date=\currentdate, +%D copyright=Jaroslav Hajtmar, +%D email=hajtmar@gyza.cz, +%D license=GNU General Public License] +% +%C Copyright (C) 2018 Jaroslav Hajtmar +%C +%C This program is free software: you can redistribute it and/or modify +%C it under the terms of the GNU General Public License as published by +%C the Free Software Foundation, either version 3 of the License, or +%C (at your option) any later version. +%C +%C This program is distributed in the hope that it will be useful, +%C but WITHOUT ANY WARRANTY; without even the implied warranty of +%C MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +%C GNU General Public License for more details. +%C +%C You should have received a copy of the GNU General Public License +%C along with this program. If not, see <http://www.gnu.org/licenses/>. + +\usemodule[handlecsv.lua] +\usemodule[handlecsv-extra.lua] +\usemodule[handlecsv-tools.lua] |