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.
Files changed (100) hide show
  1. data/ChangeLog +13 -0
  2. data/README +49 -29
  3. data/Rakefile +28 -4
  4. data/TODO +2 -9
  5. data/bin/lingo +24 -0
  6. data/bin/lingoctl +24 -0
  7. data/de/lingo-dic.txt +559 -74
  8. data/info/gpl-hdr.txt +21 -24
  9. data/lib/lingo.rb +83 -112
  10. data/lib/lingo/agenda_item.rb +53 -0
  11. data/lib/lingo/attendee.rb +261 -0
  12. data/lib/lingo/attendee/abbreviator.rb +95 -97
  13. data/lib/lingo/attendee/debugger.rb +94 -93
  14. data/lib/lingo/attendee/decomposer.rb +76 -83
  15. data/lib/lingo/attendee/dehyphenizer.rb +141 -144
  16. data/lib/lingo/attendee/formatter.rb +65 -0
  17. data/lib/lingo/attendee/multi_worder.rb +302 -0
  18. data/lib/lingo/attendee/noneword_filter.rb +89 -84
  19. data/lib/lingo/attendee/object_filter.rb +91 -0
  20. data/lib/lingo/attendee/sequencer.rb +159 -158
  21. data/lib/lingo/attendee/synonymer.rb +81 -84
  22. data/lib/lingo/attendee/text_reader.rb +242 -0
  23. data/lib/lingo/attendee/text_writer.rb +169 -0
  24. data/lib/lingo/attendee/tokenizer.rb +192 -191
  25. data/lib/lingo/attendee/variator.rb +152 -156
  26. data/lib/lingo/attendee/vector_filter.rb +140 -135
  27. data/lib/lingo/attendee/word_searcher.rb +98 -0
  28. data/lib/lingo/buffered_attendee.rb +69 -0
  29. data/lib/lingo/cachable.rb +58 -0
  30. data/lib/lingo/call.rb +72 -0
  31. data/lib/lingo/cli.rb +26 -0
  32. data/lib/lingo/config.rb +23 -26
  33. data/lib/lingo/core_ext.rb +42 -0
  34. data/lib/lingo/ctl.rb +239 -173
  35. data/lib/lingo/database.rb +148 -496
  36. data/lib/lingo/database/crypter.rb +85 -0
  37. data/lib/lingo/database/gdbm_store.rb +49 -0
  38. data/lib/lingo/database/hash_store.rb +67 -0
  39. data/lib/lingo/database/libcdb_store.rb +58 -0
  40. data/lib/lingo/database/sdbm_store.rb +64 -0
  41. data/lib/lingo/database/show_progress.rb +81 -0
  42. data/lib/lingo/database/source.rb +134 -0
  43. data/lib/lingo/database/source/key_value.rb +62 -0
  44. data/lib/lingo/database/source/multi_key.rb +65 -0
  45. data/lib/lingo/database/source/multi_value.rb +65 -0
  46. data/lib/lingo/database/source/single_word.rb +60 -0
  47. data/lib/lingo/database/source/word_class.rb +64 -0
  48. data/lib/lingo/error.rb +122 -0
  49. data/lib/lingo/language.rb +78 -518
  50. data/lib/lingo/language/dictionary.rb +173 -0
  51. data/lib/lingo/language/grammar.rb +211 -0
  52. data/lib/lingo/language/lexical.rb +66 -0
  53. data/lib/lingo/language/lexical_hash.rb +88 -0
  54. data/lib/lingo/language/token.rb +48 -0
  55. data/lib/lingo/language/word.rb +130 -0
  56. data/lib/lingo/language/word_form.rb +83 -0
  57. data/lib/lingo/reportable.rb +59 -0
  58. data/lib/lingo/version.rb +1 -1
  59. data/lingo-all.cfg +14 -10
  60. data/lingo-call.cfg +5 -5
  61. data/lingo.cfg +14 -12
  62. data/lingo.rb +26 -0
  63. data/lir.cfg +13 -9
  64. data/spec/spec_helper.rb +1 -0
  65. data/test.cfg +11 -11
  66. data/test/attendee/ts_abbreviator.rb +0 -6
  67. data/test/attendee/ts_decomposer.rb +0 -6
  68. data/test/attendee/{ts_multiworder.rb → ts_multi_worder.rb} +1 -7
  69. data/test/attendee/ts_noneword_filter.rb +1 -7
  70. data/test/attendee/{ts_objectfilter.rb → ts_object_filter.rb} +1 -7
  71. data/test/attendee/ts_sequencer.rb +0 -6
  72. data/test/attendee/ts_synonymer.rb +0 -6
  73. data/test/attendee/{ts_textreader.rb → ts_text_reader.rb} +1 -7
  74. data/test/attendee/{ts_textwriter.rb → ts_text_writer.rb} +1 -7
  75. data/test/attendee/ts_tokenizer.rb +0 -6
  76. data/test/attendee/ts_variator.rb +0 -6
  77. data/test/attendee/ts_vector_filter.rb +1 -7
  78. data/test/attendee/{ts_wordsearcher.rb → ts_word_searcher.rb} +1 -7
  79. data/test/ref/artikel.non +2 -29
  80. data/test/ref/artikel.seq +13 -8
  81. data/test/ref/artikel.vec +30 -15
  82. data/test/ref/artikel.ven +29 -14
  83. data/test/ref/artikel.ver +58 -43
  84. data/test/ref/lir.csv +146 -145
  85. data/test/ref/lir.non +186 -210
  86. data/test/ref/lir.seq +54 -50
  87. data/test/test_helper.rb +41 -36
  88. data/test/ts_database.rb +12 -11
  89. data/test/ts_language.rb +118 -68
  90. metadata +67 -29
  91. data/lib/lingo/attendee/multiworder.rb +0 -301
  92. data/lib/lingo/attendee/objectfilter.rb +0 -86
  93. data/lib/lingo/attendee/textreader.rb +0 -237
  94. data/lib/lingo/attendee/textwriter.rb +0 -196
  95. data/lib/lingo/attendee/wordsearcher.rb +0 -96
  96. data/lib/lingo/attendees.rb +0 -289
  97. data/lib/lingo/const.rb +0 -131
  98. data/lib/lingo/modules.rb +0 -98
  99. data/lib/lingo/types.rb +0 -285
  100. data/lib/lingo/utilities.rb +0 -40
@@ -1,103 +1,100 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  #--
4
- # LINGO ist ein Indexierungssystem mit Grundformreduktion, Kompositumzerlegung,
5
- # Mehrworterkennung und Relationierung.
6
- #
7
- # Copyright (C) 2005-2007 John Vorhauer
8
- # Copyright (C) 2007-2011 John Vorhauer, Jens Wille
9
- #
10
- # This program is free software; you can redistribute it and/or modify it under
11
- # the terms of the GNU Affero General Public License as published by the Free
12
- # Software Foundation; either version 3 of the License, or (at your option)
13
- # any later version.
14
- #
15
- # This program is distributed in the hope that it will be useful, but WITHOUT
16
- # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17
- # FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
18
- # details.
19
- #
20
- # You should have received a copy of the GNU Affero General Public License along
21
- # with this program; if not, write to the Free Software Foundation, Inc.,
22
- # 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
23
- #
24
- # For more information visit http://www.lex-lingo.de or contact me at
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
- # Der Synonymer untersucht die von anderen Attendees ermittelten Grundformen eines Wortes
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
- class Attendee::Synonymer < Attendee
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
- protected
71
+ class Synonymer < self
75
72
 
76
- def init
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
- @skip = get_array('skip', WA_UNKNOWN).collect {|s| s.upcase }
83
- end
75
+ def init
76
+ set_dic
77
+ @skip = get_array('skip', WA_UNKNOWN).map(&:upcase)
78
+ end
84
79
 
85
- def control(cmd, par)
86
- @dic.report.each_pair { |k, v| set( k, v ) } if cmd == STR_CMD_STATUS
87
- end
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
- def process(obj)
90
- if obj.is_a?(Word) && @skip.index(obj.attr).nil?
91
- inc('Anzahl gesuchter Wörter')
84
+ def process(obj)
85
+ if obj.is_a?(Word) && @skip.index(obj.attr).nil?
86
+ inc('Anzahl gesuchter Wörter')
92
87
 
93
- # finde die Synonyme für alle Lexicals des Wortes
94
- synos = @dic.find_synonyms(obj)
95
- obj.lexicals += synos.sort.uniq
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
- inc('Anzahl erweiteter Wörter') if synos.size>0
98
- add('Anzahl gefundener Synonyme', synos.size)
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
- forward(obj)
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