lingo 1.8.0 → 1.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/ChangeLog +13 -0
- data/README +49 -29
- data/Rakefile +28 -4
- data/TODO +2 -9
- data/bin/lingo +24 -0
- data/bin/lingoctl +24 -0
- data/de/lingo-dic.txt +559 -74
- data/info/gpl-hdr.txt +21 -24
- data/lib/lingo.rb +83 -112
- data/lib/lingo/agenda_item.rb +53 -0
- data/lib/lingo/attendee.rb +261 -0
- data/lib/lingo/attendee/abbreviator.rb +95 -97
- data/lib/lingo/attendee/debugger.rb +94 -93
- data/lib/lingo/attendee/decomposer.rb +76 -83
- data/lib/lingo/attendee/dehyphenizer.rb +141 -144
- data/lib/lingo/attendee/formatter.rb +65 -0
- data/lib/lingo/attendee/multi_worder.rb +302 -0
- data/lib/lingo/attendee/noneword_filter.rb +89 -84
- data/lib/lingo/attendee/object_filter.rb +91 -0
- data/lib/lingo/attendee/sequencer.rb +159 -158
- data/lib/lingo/attendee/synonymer.rb +81 -84
- data/lib/lingo/attendee/text_reader.rb +242 -0
- data/lib/lingo/attendee/text_writer.rb +169 -0
- data/lib/lingo/attendee/tokenizer.rb +192 -191
- data/lib/lingo/attendee/variator.rb +152 -156
- data/lib/lingo/attendee/vector_filter.rb +140 -135
- data/lib/lingo/attendee/word_searcher.rb +98 -0
- data/lib/lingo/buffered_attendee.rb +69 -0
- data/lib/lingo/cachable.rb +58 -0
- data/lib/lingo/call.rb +72 -0
- data/lib/lingo/cli.rb +26 -0
- data/lib/lingo/config.rb +23 -26
- data/lib/lingo/core_ext.rb +42 -0
- data/lib/lingo/ctl.rb +239 -173
- data/lib/lingo/database.rb +148 -496
- data/lib/lingo/database/crypter.rb +85 -0
- data/lib/lingo/database/gdbm_store.rb +49 -0
- data/lib/lingo/database/hash_store.rb +67 -0
- data/lib/lingo/database/libcdb_store.rb +58 -0
- data/lib/lingo/database/sdbm_store.rb +64 -0
- data/lib/lingo/database/show_progress.rb +81 -0
- data/lib/lingo/database/source.rb +134 -0
- data/lib/lingo/database/source/key_value.rb +62 -0
- data/lib/lingo/database/source/multi_key.rb +65 -0
- data/lib/lingo/database/source/multi_value.rb +65 -0
- data/lib/lingo/database/source/single_word.rb +60 -0
- data/lib/lingo/database/source/word_class.rb +64 -0
- data/lib/lingo/error.rb +122 -0
- data/lib/lingo/language.rb +78 -518
- data/lib/lingo/language/dictionary.rb +173 -0
- data/lib/lingo/language/grammar.rb +211 -0
- data/lib/lingo/language/lexical.rb +66 -0
- data/lib/lingo/language/lexical_hash.rb +88 -0
- data/lib/lingo/language/token.rb +48 -0
- data/lib/lingo/language/word.rb +130 -0
- data/lib/lingo/language/word_form.rb +83 -0
- data/lib/lingo/reportable.rb +59 -0
- data/lib/lingo/version.rb +1 -1
- data/lingo-all.cfg +14 -10
- data/lingo-call.cfg +5 -5
- data/lingo.cfg +14 -12
- data/lingo.rb +26 -0
- data/lir.cfg +13 -9
- data/spec/spec_helper.rb +1 -0
- data/test.cfg +11 -11
- data/test/attendee/ts_abbreviator.rb +0 -6
- data/test/attendee/ts_decomposer.rb +0 -6
- data/test/attendee/{ts_multiworder.rb → ts_multi_worder.rb} +1 -7
- data/test/attendee/ts_noneword_filter.rb +1 -7
- data/test/attendee/{ts_objectfilter.rb → ts_object_filter.rb} +1 -7
- data/test/attendee/ts_sequencer.rb +0 -6
- data/test/attendee/ts_synonymer.rb +0 -6
- data/test/attendee/{ts_textreader.rb → ts_text_reader.rb} +1 -7
- data/test/attendee/{ts_textwriter.rb → ts_text_writer.rb} +1 -7
- data/test/attendee/ts_tokenizer.rb +0 -6
- data/test/attendee/ts_variator.rb +0 -6
- data/test/attendee/ts_vector_filter.rb +1 -7
- data/test/attendee/{ts_wordsearcher.rb → ts_word_searcher.rb} +1 -7
- data/test/ref/artikel.non +2 -29
- data/test/ref/artikel.seq +13 -8
- data/test/ref/artikel.vec +30 -15
- data/test/ref/artikel.ven +29 -14
- data/test/ref/artikel.ver +58 -43
- data/test/ref/lir.csv +146 -145
- data/test/ref/lir.non +186 -210
- data/test/ref/lir.seq +54 -50
- data/test/test_helper.rb +41 -36
- data/test/ts_database.rb +12 -11
- data/test/ts_language.rb +118 -68
- metadata +67 -29
- data/lib/lingo/attendee/multiworder.rb +0 -301
- data/lib/lingo/attendee/objectfilter.rb +0 -86
- data/lib/lingo/attendee/textreader.rb +0 -237
- data/lib/lingo/attendee/textwriter.rb +0 -196
- data/lib/lingo/attendee/wordsearcher.rb +0 -96
- data/lib/lingo/attendees.rb +0 -289
- data/lib/lingo/const.rb +0 -131
- data/lib/lingo/modules.rb +0 -98
- data/lib/lingo/types.rb +0 -285
- data/lib/lingo/utilities.rb +0 -40
|
@@ -1,103 +1,100 @@
|
|
|
1
1
|
# encoding: utf-8
|
|
2
2
|
|
|
3
3
|
#--
|
|
4
|
-
|
|
5
|
-
#
|
|
6
|
-
#
|
|
7
|
-
#
|
|
8
|
-
# Copyright (C) 2007
|
|
9
|
-
#
|
|
10
|
-
#
|
|
11
|
-
#
|
|
12
|
-
#
|
|
13
|
-
#
|
|
14
|
-
#
|
|
15
|
-
#
|
|
16
|
-
#
|
|
17
|
-
#
|
|
18
|
-
#
|
|
19
|
-
#
|
|
20
|
-
#
|
|
21
|
-
#
|
|
22
|
-
#
|
|
23
|
-
#
|
|
24
|
-
|
|
25
|
-
# welcomeATlex-lingoDOTde near 50°55'N+6°55'E.
|
|
26
|
-
#
|
|
27
|
-
# Lex Lingo rules from here on
|
|
4
|
+
###############################################################################
|
|
5
|
+
# #
|
|
6
|
+
# Lingo -- A full-featured automatic indexing system #
|
|
7
|
+
# #
|
|
8
|
+
# Copyright (C) 2005-2007 John Vorhauer #
|
|
9
|
+
# Copyright (C) 2007-2012 John Vorhauer, Jens Wille #
|
|
10
|
+
# #
|
|
11
|
+
# Lingo is free software; you can redistribute it and/or modify it under the #
|
|
12
|
+
# terms of the GNU Affero General Public License as published by the Free #
|
|
13
|
+
# Software Foundation; either version 3 of the License, or (at your option) #
|
|
14
|
+
# any later version. #
|
|
15
|
+
# #
|
|
16
|
+
# Lingo is distributed in the hope that it will be useful, but WITHOUT ANY #
|
|
17
|
+
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS #
|
|
18
|
+
# FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for #
|
|
19
|
+
# more details. #
|
|
20
|
+
# #
|
|
21
|
+
# You should have received a copy of the GNU Affero General Public License #
|
|
22
|
+
# along with Lingo. If not, see <http://www.gnu.org/licenses/>. #
|
|
23
|
+
# #
|
|
24
|
+
###############################################################################
|
|
28
25
|
#++
|
|
29
26
|
|
|
30
27
|
class Lingo
|
|
31
28
|
|
|
32
|
-
|
|
33
|
-
# und sucht in den angegebenen Wörterbüchern nach Relationen zu anderen Grundformen.
|
|
34
|
-
# Gefundene Relationen erweitern die Liste des Word-Objektes und werden zur späteren
|
|
35
|
-
# Identifizierung mit der Wortklasse 'y' gekennzeichnet.
|
|
36
|
-
#
|
|
37
|
-
# === Mögliche Verlinkung
|
|
38
|
-
# Erwartet:: Daten vom Typ *Word* z.B. von Wordsearcher, Decomposer, Ocr_variator, Multiworder
|
|
39
|
-
# Erzeugt:: Daten vom Typ *Word* (ggf. um Relationen ergänzt) z.B. für Decomposer, Ocr_variator, Multiworder, Sequencer, Noneword_filter, Vector_filter
|
|
40
|
-
#
|
|
41
|
-
# === Parameter
|
|
42
|
-
# Kursiv dargestellte Parameter sind optional (ggf. mit Angabe der Voreinstellung).
|
|
43
|
-
# Alle anderen Parameter müssen zwingend angegeben werden.
|
|
44
|
-
# <b>in</b>:: siehe allgemeine Beschreibung des Attendee
|
|
45
|
-
# <b>out</b>:: siehe allgemeine Beschreibung des Attendee
|
|
46
|
-
# <b>source</b>:: siehe allgemeine Beschreibung des Dictionary
|
|
47
|
-
# <b><i>mode</i></b>:: (Standard: all) siehe allgemeine Beschreibung des Dictionary
|
|
48
|
-
# <b><i>skip</i></b>:: (Standard: WA_UNKNOWN [siehe strings.rb]) Veranlasst den Synonymer
|
|
49
|
-
# Wörter mit diesem Attribut zu überspringen.
|
|
50
|
-
#
|
|
51
|
-
# === Beispiele
|
|
52
|
-
# Bei der Verarbeitung einer normalen Textdatei mit der Ablaufkonfiguration <tt>t1.cfg</tt>
|
|
53
|
-
# meeting:
|
|
54
|
-
# attendees:
|
|
55
|
-
# - textreader: { out: lines, files: '$(files)' }
|
|
56
|
-
# - tokenizer: { in: lines, out: token }
|
|
57
|
-
# - abbreviator: { in: token, out: abbrev, source: 'sys-abk' }
|
|
58
|
-
# - wordsearcher: { in: abbrev, out: words, source: 'sys-dic' }
|
|
59
|
-
# - synonymer: { in: words, out: synos, source: 'sys-syn' }
|
|
60
|
-
# - debugger: { in: words, prompt: 'out>' }
|
|
61
|
-
# ergibt die Ausgabe über den Debugger: <tt>lingo -c t1 test.txt</tt>
|
|
62
|
-
# out> *FILE('test.txt')
|
|
63
|
-
# out> <Dies = [(dies/w), (das/y), (dies/y)]>
|
|
64
|
-
# out> <ist = [(sein/v), ((sich) befinden/y), (dasein/y), (existenz/y), (sein/y), (vorhandensein/y)]>
|
|
65
|
-
# out> <ggf. = [(gegebenenfalls/w), (bei bedarf/y), (gegebenenfalls/y), (ggf./y), (notfalls/y)]>
|
|
66
|
-
# out> <eine = [(einen/v), (ein/w)]>
|
|
67
|
-
# out> <Abk³rzung = [(abk³rzung/s), (abbreviation/y), (abbreviatur/y), (abk³rzung/y), (akronym/y), (kurzbezeichnung/y)]>
|
|
68
|
-
# out> :./PUNC:
|
|
69
|
-
# out> *EOL('test.txt')
|
|
70
|
-
# out> *EOF('test.txt')
|
|
29
|
+
class Attendee
|
|
71
30
|
|
|
72
|
-
|
|
31
|
+
# Der Synonymer untersucht die von anderen Attendees ermittelten Grundformen eines Wortes
|
|
32
|
+
# und sucht in den angegebenen Wörterbüchern nach Relationen zu anderen Grundformen.
|
|
33
|
+
# Gefundene Relationen erweitern die Liste des Word-Objektes und werden zur späteren
|
|
34
|
+
# Identifizierung mit der Wortklasse 'y' gekennzeichnet.
|
|
35
|
+
#
|
|
36
|
+
# === Mögliche Verlinkung
|
|
37
|
+
# Erwartet:: Daten vom Typ *Word* z.B. von Wordsearcher, Decomposer, Ocr_variator, Multiworder
|
|
38
|
+
# Erzeugt:: Daten vom Typ *Word* (ggf. um Relationen ergänzt) z.B. für Decomposer, Ocr_variator, Multiworder, Sequencer, Noneword_filter, Vector_filter
|
|
39
|
+
#
|
|
40
|
+
# === Parameter
|
|
41
|
+
# Kursiv dargestellte Parameter sind optional (ggf. mit Angabe der Voreinstellung).
|
|
42
|
+
# Alle anderen Parameter müssen zwingend angegeben werden.
|
|
43
|
+
# <b>in</b>:: siehe allgemeine Beschreibung des Attendee
|
|
44
|
+
# <b>out</b>:: siehe allgemeine Beschreibung des Attendee
|
|
45
|
+
# <b>source</b>:: siehe allgemeine Beschreibung des Dictionary
|
|
46
|
+
# <b><i>mode</i></b>:: (Standard: all) siehe allgemeine Beschreibung des Dictionary
|
|
47
|
+
# <b><i>skip</i></b>:: (Standard: WA_UNKNOWN [siehe strings.rb]) Veranlasst den Synonymer
|
|
48
|
+
# Wörter mit diesem Attribut zu überspringen.
|
|
49
|
+
#
|
|
50
|
+
# === Beispiele
|
|
51
|
+
# Bei der Verarbeitung einer normalen Textdatei mit der Ablaufkonfiguration <tt>t1.cfg</tt>
|
|
52
|
+
# meeting:
|
|
53
|
+
# attendees:
|
|
54
|
+
# - text_reader: { out: lines, files: '$(files)' }
|
|
55
|
+
# - tokenizer: { in: lines, out: token }
|
|
56
|
+
# - abbreviator: { in: token, out: abbrev, source: 'sys-abk' }
|
|
57
|
+
# - word_searcher: { in: abbrev, out: words, source: 'sys-dic' }
|
|
58
|
+
# - synonymer: { in: words, out: synos, source: 'sys-syn' }
|
|
59
|
+
# - debugger: { in: words, prompt: 'out>' }
|
|
60
|
+
# ergibt die Ausgabe über den Debugger: <tt>lingo -c t1 test.txt</tt>
|
|
61
|
+
# out> *FILE('test.txt')
|
|
62
|
+
# out> <Dies = [(dies/w), (das/y), (dies/y)]>
|
|
63
|
+
# out> <ist = [(sein/v), ((sich) befinden/y), (dasein/y), (existenz/y), (sein/y), (vorhandensein/y)]>
|
|
64
|
+
# out> <ggf. = [(gegebenenfalls/w), (bei bedarf/y), (gegebenenfalls/y), (ggf./y), (notfalls/y)]>
|
|
65
|
+
# out> <eine = [(einen/v), (ein/w)]>
|
|
66
|
+
# out> <Abk³rzung = [(abk³rzung/s), (abbreviation/y), (abbreviatur/y), (abk³rzung/y), (akronym/y), (kurzbezeichnung/y)]>
|
|
67
|
+
# out> :./PUNC:
|
|
68
|
+
# out> *EOL('test.txt')
|
|
69
|
+
# out> *EOF('test.txt')
|
|
73
70
|
|
|
74
|
-
|
|
71
|
+
class Synonymer < self
|
|
75
72
|
|
|
76
|
-
|
|
77
|
-
# Wörterbuch bereitstellen
|
|
78
|
-
src = get_array('source')
|
|
79
|
-
mod = get_key('mode', 'all')
|
|
80
|
-
@dic = Dictionary.new({'source'=>src, 'mode'=>mod}, @lingo)
|
|
73
|
+
protected
|
|
81
74
|
|
|
82
|
-
|
|
83
|
-
|
|
75
|
+
def init
|
|
76
|
+
set_dic
|
|
77
|
+
@skip = get_array('skip', WA_UNKNOWN).map(&:upcase)
|
|
78
|
+
end
|
|
84
79
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
80
|
+
def control(cmd, par)
|
|
81
|
+
@dic.report.each_pair { |k, v| set( k, v ) } if cmd == STR_CMD_STATUS
|
|
82
|
+
end
|
|
88
83
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
84
|
+
def process(obj)
|
|
85
|
+
if obj.is_a?(Word) && @skip.index(obj.attr).nil?
|
|
86
|
+
inc('Anzahl gesuchter Wörter')
|
|
92
87
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
88
|
+
# finde die Synonyme für alle Lexicals des Wortes
|
|
89
|
+
synos = @dic.find_synonyms(obj)
|
|
90
|
+
obj.lexicals += synos.sort.uniq
|
|
96
91
|
|
|
97
|
-
|
|
98
|
-
|
|
92
|
+
inc('Anzahl erweiteter Wörter') if synos.size>0
|
|
93
|
+
add('Anzahl gefundener Synonyme', synos.size)
|
|
94
|
+
end
|
|
95
|
+
forward(obj)
|
|
99
96
|
end
|
|
100
|
-
|
|
97
|
+
|
|
101
98
|
end
|
|
102
99
|
|
|
103
100
|
end
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
#--
|
|
4
|
+
###############################################################################
|
|
5
|
+
# #
|
|
6
|
+
# Lingo -- A full-featured automatic indexing system #
|
|
7
|
+
# #
|
|
8
|
+
# Copyright (C) 2005-2007 John Vorhauer #
|
|
9
|
+
# Copyright (C) 2007-2012 John Vorhauer, Jens Wille #
|
|
10
|
+
# #
|
|
11
|
+
# Lingo is free software; you can redistribute it and/or modify it under the #
|
|
12
|
+
# terms of the GNU Affero General Public License as published by the Free #
|
|
13
|
+
# Software Foundation; either version 3 of the License, or (at your option) #
|
|
14
|
+
# any later version. #
|
|
15
|
+
# #
|
|
16
|
+
# Lingo is distributed in the hope that it will be useful, but WITHOUT ANY #
|
|
17
|
+
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS #
|
|
18
|
+
# FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for #
|
|
19
|
+
# more details. #
|
|
20
|
+
# #
|
|
21
|
+
# You should have received a copy of the GNU Affero General Public License #
|
|
22
|
+
# along with Lingo. If not, see <http://www.gnu.org/licenses/>. #
|
|
23
|
+
# #
|
|
24
|
+
###############################################################################
|
|
25
|
+
#++
|
|
26
|
+
|
|
27
|
+
%w[filemagic mime/types hpricot pdf-reader].each { |lib|
|
|
28
|
+
begin
|
|
29
|
+
require lib
|
|
30
|
+
rescue LoadError
|
|
31
|
+
end
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
class Lingo
|
|
35
|
+
|
|
36
|
+
class Attendee
|
|
37
|
+
|
|
38
|
+
# Der TextReader ist eine klassische Datenquelle. Er liest eine oder mehrere Dateien
|
|
39
|
+
# und gibt sie Zeilenweise in den Ausgabekanal. Der Start bzw. Wechsel einer Datei
|
|
40
|
+
# wird dabei über den Kommandokanal angekündigt, ebenso wie das Ende.
|
|
41
|
+
#
|
|
42
|
+
# Der TextReader kann ebenfalls ein spezielles Dateiformat verarbeiten, welches zum
|
|
43
|
+
# Austausch mit dem LIR-System dient. Dabei enthält die Datei Record-basierte Informationen,
|
|
44
|
+
# die wie mehrere Dateien verarbeitet werden.
|
|
45
|
+
#
|
|
46
|
+
# === Mögliche Verlinkung
|
|
47
|
+
# Erzeugt:: Daten des Typs *String* (Textzeile) z.B. für Tokenizer, Textwriter
|
|
48
|
+
#
|
|
49
|
+
# === Parameter
|
|
50
|
+
# Kursiv dargestellte Parameter sind optional (ggf. mit Angabe der Voreinstellung).
|
|
51
|
+
# Alle anderen Parameter müssen zwingend angegeben werden.
|
|
52
|
+
# <b>out</b>:: siehe allgemeine Beschreibung des Attendee
|
|
53
|
+
# <b>files</b>:: Es können eine oder mehrere Dateien angegeben werden, die nacheinander
|
|
54
|
+
# eingelesen und zeilenweise weitergeleitet werden. Die Dateien werden mit
|
|
55
|
+
# Komma voneinander getrennt, z.B.
|
|
56
|
+
# files: 'readme.txt'
|
|
57
|
+
# files: 'readme.txt,lingo.cfg'
|
|
58
|
+
# <b><i>lir-record-pattern</i></b>:: Mit diesem Parameter wird angegeben, woran der Anfang
|
|
59
|
+
# eines neuen Records erkannt werden kann und wie die
|
|
60
|
+
# Record-Nummer identifiziert wird. Das Format einer
|
|
61
|
+
# LIR-Datei ist z.B.
|
|
62
|
+
# [00001.]
|
|
63
|
+
# 020: ¬Die Aufgabenteilung zwischen Wortschatz und Grammatik.
|
|
64
|
+
#
|
|
65
|
+
# [00002.]
|
|
66
|
+
# 020: Nicht-konventionelle Thesaurusrelationen als Orientierungshilfen.
|
|
67
|
+
# Mit der Angabe von
|
|
68
|
+
# lir-record-pattern: "^\[(\d+)\.\]"
|
|
69
|
+
# werden die Record-Zeilen erkannt und jeweils die Record-Nummer +00001+,
|
|
70
|
+
# bzw. +00002+ erkannt.
|
|
71
|
+
#
|
|
72
|
+
# === Generierte Kommandos
|
|
73
|
+
# Damit der nachfolgende Datenstrom einwandfrei verarbeitet werden kann, generiert der TextReader
|
|
74
|
+
# Kommandos, die mit in den Datenstrom eingefügt werden.
|
|
75
|
+
# <b>*FILE(<dateiname>)</b>:: Kennzeichnet den Beginn der Datei <dateiname>
|
|
76
|
+
# <b>*EOF(<dateiname>)</b>:: Kennzeichnet das Ende der Datei <dateiname>
|
|
77
|
+
# <b>*LIR_FORMAT('')</b>:: Kennzeichnet die Verarbeitung einer Datei im LIR-Format (nur bei LIR-Format).
|
|
78
|
+
# <b>*RECORD(<nummer>)</b>:: Kennzeichnet den Beginn eines neuen Records (nur bei LIR-Format).
|
|
79
|
+
# === Beispiele
|
|
80
|
+
# Bei der Verarbeitung einer normalen Textdatei mit der Ablaufkonfiguration <tt>t1.cfg</tt>
|
|
81
|
+
# meeting:
|
|
82
|
+
# attendees:
|
|
83
|
+
# - text_reader: { out: lines, files: '$(files)' }
|
|
84
|
+
# - debugger: { in: lines, prompt: 'out>' }
|
|
85
|
+
# ergibt die Ausgabe über den Debugger: <tt>lingo -c t1 test.txt</tt>
|
|
86
|
+
# out> *FILE('test.txt')
|
|
87
|
+
# out> "Dies ist eine Zeile."
|
|
88
|
+
# out> "Dies ist noch eine."
|
|
89
|
+
# out> *EOF('test.txt')
|
|
90
|
+
# Bei der Verarbeitung einer LIR-Datei mit der Ablaufkonfiguration <tt>t2.cfg</tt>
|
|
91
|
+
# meeting:
|
|
92
|
+
# attendees:
|
|
93
|
+
# - text_reader: { out: lines, files: '$(files)', lir-record-pattern: "^\[(\d+)\.\]" }
|
|
94
|
+
# - debugger: { in: lines, prompt: 'out>'}
|
|
95
|
+
# ergibt die Ausgabe mit <tt>lingo -c t2 lir.txt</tt>
|
|
96
|
+
# out> *LIR-FORMAT('')
|
|
97
|
+
# out> *FILE('lir.txt')
|
|
98
|
+
# out> *RECORD('00001')
|
|
99
|
+
# out> "020: \254Die Aufgabenteilung zwischen Wortschatz und Grammatik."
|
|
100
|
+
# out> *RECORD('00002')
|
|
101
|
+
# out> "020: Nicht-konventionelle Thesaurusrelationen als Orientierungshilfen."
|
|
102
|
+
# out> *EOF('lir.txt')
|
|
103
|
+
|
|
104
|
+
class TextReader < self
|
|
105
|
+
|
|
106
|
+
protected
|
|
107
|
+
|
|
108
|
+
# TODO: FILE und LIR-FILE
|
|
109
|
+
# TODO: lir-record-pattern abkürzen
|
|
110
|
+
# Interpretation der Parameter
|
|
111
|
+
def init
|
|
112
|
+
@files = Array(get_key('files', '-'))
|
|
113
|
+
@rec_pat = Regexp.new(get_key('lir-record-pattern', ''))
|
|
114
|
+
@is_LIR_file = has_key?('lir-record-pattern')
|
|
115
|
+
@chomp = get_key('chomp', true)
|
|
116
|
+
@filter = get_key('filter', false)
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def control(cmd, param)
|
|
120
|
+
if cmd==STR_CMD_TALK
|
|
121
|
+
forward(STR_CMD_LIR, '') if @is_LIR_file
|
|
122
|
+
@files.each { |filename| spool(filename) }
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
private
|
|
127
|
+
|
|
128
|
+
# Gibt eine Datei zeilenweise in den Ausgabekanal
|
|
129
|
+
def spool(filename)
|
|
130
|
+
unless stdin?(filename)
|
|
131
|
+
raise FileNotFoundError.new(filename) unless File.exist?(filename)
|
|
132
|
+
|
|
133
|
+
inc('Anzahl Dateien')
|
|
134
|
+
add('Anzahl Bytes', File.stat(filename).size)
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
forward(STR_CMD_FILE, filename)
|
|
138
|
+
|
|
139
|
+
filter(filename) { |line|
|
|
140
|
+
inc('Anzahl Zeilen')
|
|
141
|
+
line.chomp! if @chomp
|
|
142
|
+
line.gsub!(/\303\237/, "ß")
|
|
143
|
+
### HACK
|
|
144
|
+
if @is_LIR_file && line =~ @rec_pat
|
|
145
|
+
forward(STR_CMD_RECORD, $1)
|
|
146
|
+
else
|
|
147
|
+
forward(line) if line.size>0
|
|
148
|
+
end
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
forward(STR_CMD_EOF, filename)
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
def filter(filename, &block)
|
|
155
|
+
file = stdin?(filename) ?
|
|
156
|
+
@lingo.config.stdin.set_encoding(ENC) :
|
|
157
|
+
File.open(filename, 'rb', encoding: ENC)
|
|
158
|
+
|
|
159
|
+
file = case @filter == true ? file_type(filename, file) : @filter.to_s
|
|
160
|
+
when /html/ then filter_html(file)
|
|
161
|
+
when /xml/ then filter_html(file, true)
|
|
162
|
+
when /pdf/ then filter_pdf(file, &block) or return
|
|
163
|
+
else file
|
|
164
|
+
end if @filter
|
|
165
|
+
|
|
166
|
+
file.each_line(&block)
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
def filter_pdf(file, &block)
|
|
170
|
+
if Object.const_defined?(:PDF) && PDF.const_defined?(:Reader)
|
|
171
|
+
PDFFilter.filter(file, &block)
|
|
172
|
+
nil
|
|
173
|
+
else
|
|
174
|
+
warn "PDF filter not available. Please install `pdf-reader'."
|
|
175
|
+
file
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
def filter_html(file, xml = false)
|
|
180
|
+
if Object.const_defined?(:Hpricot)
|
|
181
|
+
Hpricot(file, xml: xml).inner_text
|
|
182
|
+
else
|
|
183
|
+
warn "#{xml ? 'X' : 'HT'}ML filter not available. Please install `hpricot'."
|
|
184
|
+
file
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
def file_type(filename, file)
|
|
189
|
+
if Object.const_defined?(:FileMagic) && file.respond_to?(:rewind)
|
|
190
|
+
type = FileMagic.fm(:mime, simplified: true).buffer(file.read(256))
|
|
191
|
+
file.rewind
|
|
192
|
+
type
|
|
193
|
+
elsif Object.const_defined?(:MIME) && MIME.const_defined?(:Types)
|
|
194
|
+
if type = MIME::Types.of(filename).first
|
|
195
|
+
type.content_type
|
|
196
|
+
else
|
|
197
|
+
warn 'Filters not available. File type could not be determined.'
|
|
198
|
+
nil
|
|
199
|
+
end
|
|
200
|
+
else
|
|
201
|
+
warn "Filters not available. Please install `ruby-filemagic' or `mime-types'."
|
|
202
|
+
nil
|
|
203
|
+
end
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
def stdin?(filename)
|
|
207
|
+
%w[STDIN -].include?(filename)
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
class PDFFilter
|
|
211
|
+
|
|
212
|
+
def self.filter(file, &block)
|
|
213
|
+
PDF::Reader.new.parse(file, new(&block))
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
def initialize(&block)
|
|
217
|
+
@block = block
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
def show_text(string, *params)
|
|
221
|
+
@block[string << '|']
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
alias_method :super_show_text, :show_text
|
|
225
|
+
alias_method :move_to_next_line_and_show_text, :show_text
|
|
226
|
+
alias_method :set_spacing_next_line_show_text, :show_text
|
|
227
|
+
|
|
228
|
+
def show_text_with_positioning(params, *)
|
|
229
|
+
params.each { |param| show_text(param) if param.is_a?(String) }
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
# For backwards compatibility.
|
|
237
|
+
Textreader = TextReader
|
|
238
|
+
Text_reader = TextReader
|
|
239
|
+
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
end
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
#--
|
|
4
|
+
###############################################################################
|
|
5
|
+
# #
|
|
6
|
+
# Lingo -- A full-featured automatic indexing system #
|
|
7
|
+
# #
|
|
8
|
+
# Copyright (C) 2005-2007 John Vorhauer #
|
|
9
|
+
# Copyright (C) 2007-2012 John Vorhauer, Jens Wille #
|
|
10
|
+
# #
|
|
11
|
+
# Lingo is free software; you can redistribute it and/or modify it under the #
|
|
12
|
+
# terms of the GNU Affero General Public License as published by the Free #
|
|
13
|
+
# Software Foundation; either version 3 of the License, or (at your option) #
|
|
14
|
+
# any later version. #
|
|
15
|
+
# #
|
|
16
|
+
# Lingo is distributed in the hope that it will be useful, but WITHOUT ANY #
|
|
17
|
+
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS #
|
|
18
|
+
# FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for #
|
|
19
|
+
# more details. #
|
|
20
|
+
# #
|
|
21
|
+
# You should have received a copy of the GNU Affero General Public License #
|
|
22
|
+
# along with Lingo. If not, see <http://www.gnu.org/licenses/>. #
|
|
23
|
+
# #
|
|
24
|
+
###############################################################################
|
|
25
|
+
#++
|
|
26
|
+
|
|
27
|
+
class Lingo
|
|
28
|
+
|
|
29
|
+
class Attendee
|
|
30
|
+
|
|
31
|
+
# Der TextWriter ermöglicht die Umleitung des Datenstroms in eine Textdatei. Dabei werden
|
|
32
|
+
# Objekte, die nicht vom Typ String sind in eine sinnvolle Textrepresentation gewandelt.
|
|
33
|
+
# Der Name der Ausgabedatei wird durch den Namen der Eingabedatei (des Textreaders) bestimmt.
|
|
34
|
+
# Es kann lediglich die Extension verändert werden. Der TextWriter kann auch das LIR-Format
|
|
35
|
+
# erzeugen.
|
|
36
|
+
#
|
|
37
|
+
# === Mögliche Verlinkung
|
|
38
|
+
# Erwartet:: Daten verschiedenen Typs
|
|
39
|
+
#
|
|
40
|
+
# === Parameter
|
|
41
|
+
# Kursiv dargestellte Parameter sind optional (ggf. mit Angabe der Voreinstellung).
|
|
42
|
+
# Alle anderen Parameter müssen zwingend angegeben werden.
|
|
43
|
+
# <b>in</b>:: siehe allgemeine Beschreibung des Attendee
|
|
44
|
+
# <b>out</b>:: siehe allgemeine Beschreibung des Attendee
|
|
45
|
+
# <b><i>ext</i></b>:: (Standard: txt2) Gibt die Dateinamen-Erweiertung für die Ausgabedatei an.
|
|
46
|
+
# Wird z.B. dem TextReader die Datei <tt>Dokument.txt</tt> angegeben und
|
|
47
|
+
# über die Lingo-Konfiguration alle Indexwörter herausgefiltert, kann mit
|
|
48
|
+
# <tt>ext: 'idx'</tt> der TextWriter veranlasst werden, die Indexwörter in
|
|
49
|
+
# die Datei <tt>Dokument.idx</tt> zu schreiben.
|
|
50
|
+
# <b><i>sep</i></b>:: (Standard: ' ') Gibt an, mit welchem Trennzeichen zwei aufeinanderfolgende
|
|
51
|
+
# Objekte in der Ausgabedatei getrennt werden sollen. Gängige Werte sind auch
|
|
52
|
+
# noch '\n', welches die Ausgabe jedes Objektes in eine Zeile ermöglicht.
|
|
53
|
+
# <b><i>lir-format</i></b>:: (Standard: false) Dieser Parameter hat keinen Wert. Wird er angegeben,
|
|
54
|
+
# dann wird er als true ausgewertet. Damit ist es möglich, die Ausgabedatei
|
|
55
|
+
# im für LIR lesbarem Format zu erstellen.
|
|
56
|
+
#
|
|
57
|
+
# === Beispiele
|
|
58
|
+
# Bei der Verarbeitung der oben angegebenen Funktionsbeschreibung des Textwriters mit der Ablaufkonfiguration <tt>t1.cfg</tt>
|
|
59
|
+
# meeting:
|
|
60
|
+
# attendees:
|
|
61
|
+
# - text_reader: { out: lines, files: '$(files)' }
|
|
62
|
+
# - tokenizer: { in: lines, out: token }
|
|
63
|
+
# - word_searcher: { in: token, out: words, source: 'sys-dic' }
|
|
64
|
+
# - vector_filter: { in: words, out: filtr, sort: 'term_rel' }
|
|
65
|
+
# - text_writer: { in: filtr, ext: 'vec', sep: '\n' }
|
|
66
|
+
# ergibt die Ausgabe in der Datei <tt>test.vec</tt>
|
|
67
|
+
# 0.03846 name
|
|
68
|
+
# 0.01923 ausgabedatei
|
|
69
|
+
# 0.01923 datenstrom
|
|
70
|
+
# 0.01923 extension
|
|
71
|
+
# 0.01923 format
|
|
72
|
+
# 0.01923 objekt
|
|
73
|
+
# 0.01923 string
|
|
74
|
+
# 0.01923 textdatei
|
|
75
|
+
# 0.01923 typ
|
|
76
|
+
# 0.01923 umleitung
|
|
77
|
+
|
|
78
|
+
class TextWriter < self
|
|
79
|
+
|
|
80
|
+
protected
|
|
81
|
+
|
|
82
|
+
def init
|
|
83
|
+
@ext = get_key('ext', 'txt2')
|
|
84
|
+
@lir = get_key('lir-format', false)
|
|
85
|
+
@sep = @lir ? ' ' : eval("\"#{@config['sep'] || ' '}\"")
|
|
86
|
+
@no_sep, @no_puts = true, false
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def control(cmd, par)
|
|
90
|
+
case cmd
|
|
91
|
+
when STR_CMD_LIR
|
|
92
|
+
@lir = true
|
|
93
|
+
when STR_CMD_FILE
|
|
94
|
+
@no_sep = true
|
|
95
|
+
|
|
96
|
+
if stdout?(@ext)
|
|
97
|
+
@filename = @ext
|
|
98
|
+
@file = @lingo.config.stdout
|
|
99
|
+
else
|
|
100
|
+
@filename = par.sub(/(\.[^.]+)?$/, '.'+@ext)
|
|
101
|
+
@file = File.new(@filename,'w')
|
|
102
|
+
inc('Anzahl Dateien')
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
@lir_rec_no = ''
|
|
106
|
+
@lir_rec_buf = Array.new
|
|
107
|
+
when STR_CMD_RECORD
|
|
108
|
+
@no_sep = true
|
|
109
|
+
if @lir
|
|
110
|
+
flush_lir_buffer
|
|
111
|
+
@lir_rec_no = par
|
|
112
|
+
end
|
|
113
|
+
when STR_CMD_EOL
|
|
114
|
+
@no_sep = true
|
|
115
|
+
unless @lir
|
|
116
|
+
@file.puts unless @no_puts # unless @sep=="\n"
|
|
117
|
+
inc('Anzahl Zeilen')
|
|
118
|
+
end
|
|
119
|
+
when STR_CMD_EOF
|
|
120
|
+
flush_lir_buffer if @lir
|
|
121
|
+
|
|
122
|
+
unless stdout?(@filename)
|
|
123
|
+
@file.close
|
|
124
|
+
add('Anzahl Bytes', File.stat(@filename).size)
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def process(obj)
|
|
130
|
+
if @lir
|
|
131
|
+
@lir_rec_buf << (obj.kind_of?(Token) ? obj.form : obj.to_s)
|
|
132
|
+
else
|
|
133
|
+
@file.print @sep unless @no_sep
|
|
134
|
+
@no_sep=false if @no_sep
|
|
135
|
+
if obj.is_a?(Word) || obj.is_a?(Token)
|
|
136
|
+
@file.print obj.form
|
|
137
|
+
else
|
|
138
|
+
@file.print obj
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
private
|
|
144
|
+
|
|
145
|
+
def flush_lir_buffer
|
|
146
|
+
unless @lir_rec_no.empty? || @lir_rec_buf.empty?
|
|
147
|
+
if @sep =~ /\n/
|
|
148
|
+
@file.print '*', @lir_rec_no, "\n", @lir_rec_buf.join(@sep), "\n"
|
|
149
|
+
else
|
|
150
|
+
@file.print @lir_rec_no, '*', @lir_rec_buf.join(@sep), "\n"
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
@lir_rec_no = ''
|
|
154
|
+
@lir_rec_buf.clear
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def stdout?(filename)
|
|
158
|
+
%w[STDOUT -].include?(filename)
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
# For backwards compatibility.
|
|
164
|
+
Textwriter = TextWriter
|
|
165
|
+
Text_writer = TextWriter
|
|
166
|
+
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
end
|