pidgin2adium 2.0.2 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/.autotest ADDED
@@ -0,0 +1,9 @@
1
+ Autotest.add_hook :initialize do |at|
2
+ at.add_mapping(/ext\/.*\/(.*)\.[ch]/) do |_, m|
3
+ ["test/test_#{m[1]}_extn.rb"]
4
+ end
5
+ end
6
+
7
+ Autotest.add_hook :run_command do |at|
8
+ system "rake compile"
9
+ end
data/History.txt CHANGED
@@ -1,3 +1,12 @@
1
+ === 3.0.0 / 2010-01-31
2
+ * balance_tags.rb is now a C extension (Pidgin2Adium.balance_tags_c)
3
+ - the pure-ruby mixin balance_tags (without the trailing "_c") is gone
4
+ * Better handling of command-line arguments
5
+ * Format time zones offsets correctly (e.g. "+0500", not "+-0500")
6
+ * Write Yahoo! and Jabber logs to correct directories (#27710)
7
+ * Better matching of regexes against time strings
8
+ * Better documentation
9
+
1
10
  === 2.0.2 / 2009-12-18
2
11
  * Much better documentation (more of it, and higher quality too!)
3
12
  * Allow user-provided output dir at commandline
data/Manifest.txt CHANGED
@@ -1,10 +1,18 @@
1
+ .autotest
1
2
  History.txt
2
3
  Manifest.txt
3
4
  README.rdoc
4
5
  Rakefile.rb
5
6
  bin/pidgin2adium
7
+ ext/balance_tags_c/balance_tags_c.c
8
+ ext/balance_tags_c/extconf.rb
6
9
  lib/pidgin2adium.rb
7
- lib/pidgin2adium/balance_tags.rb
8
10
  lib/pidgin2adium/log_converter.rb
9
11
  lib/pidgin2adium/log_file.rb
10
12
  lib/pidgin2adium/log_parser.rb
13
+ script/console
14
+ script/destroy
15
+ script/generate
16
+ tasks/extconf.rake
17
+ tasks/extconf/balance_tags_c.rake
18
+ test/test_balance_tags_c_extn.rb
data/README.rdoc CHANGED
@@ -37,10 +37,7 @@ Or:
37
37
  $ pidgin2adium -i pidgin-logs -a gabe,gabeb-w,gbw
38
38
 
39
39
  ===Example (using library)
40
- The library style allows you to parse a log file and get back a
41
- LogFile[link:classes/Pidgin2Adium/LogFile.html] instance for easy reading, manipulation, etc.
42
- You can also create log files yourself using Pidgin2Adium.parse_and_generate[link:classes/Pidgin2Adium.html#M000006].
43
- For batch processing, use LogConverter[link:classes/Pidgin2Adium/LogConverter.html].
40
+ The library style allows you to parse a log file and get back a LogFile[link:classes/Pidgin2Adium/LogFile.html] instance for easy reading, manipulation, etc. If you don't need to do anything with the individual messages, use Pidgin2Adium.parse[link:classes/Pidgin2Adium.html#M000002].
44
41
 
45
42
  require 'pidgin2adium'
46
43
  logfile = Pidgin2Adium.parse("/path/to/log/file.html", "gabe,gbw,gabeb-w")
@@ -81,15 +78,17 @@ For batch processing, use LogConverter[link:classes/Pidgin2Adium/LogConverter.ht
81
78
  puts "Successfully wrote out log file!"
82
79
  puts "Path to output file: #{success}"
83
80
  end
84
- # This deletes search indexes to Adium re-indexes the new chat logs.
85
- # Not automatically called after log_file.write_out()
86
- # If you're converting >1 log, call it after converting all of them, since
87
- # it takes up a tiny bit of processing power.
81
+ # This deletes search indexes so Adium re-indexes the new chat logs.
82
+ # It is not automatically called after log_file.write_out()
83
+ # Call it after converting all the logs, since it takes up a bit of
84
+ # processing power.
88
85
  Pidgin2Adium.delete_search_indexes()
89
86
  end
90
87
 
91
88
  ===Example 2 (using library)
92
- If you want to output the logfile to an output dir instead of just parsing it, use Pidgin2Adium.parse_and_generate:
89
+ If you want to parse the file and write it out instead of just parsing it, use Pidgin2Adium.parse_and_generate.
90
+
91
+ Note: For batch processing, use LogConverter[link:classes/Pidgin2Adium/LogConverter.html].
93
92
 
94
93
  require 'pidgin2adium'
95
94
  # Both options are optional; without :output_dir, writes to Adium log dir
data/Rakefile.rb CHANGED
@@ -18,12 +18,23 @@ $hoe = Hoe.spec 'pidgin2adium' do
18
18
  #self.post_install_message = 'PostInstall.txt' # TODO remove if post-install message not required
19
19
  self.rubyforge_name = self.name # this is default value
20
20
  # self.extra_deps = [['activesupport','>= 2.0.2']]
21
+
22
+ self.spec_extras[:extensions] = "ext/balance_tags_c/extconf.rb"
23
+ end
24
+
25
+ $hoe.spec.rdoc_options = %w{--main README.rdoc}
26
+
27
+ # Use hanna RDoc template, if available
28
+ begin
29
+ gem "hanna"
30
+ $hoe.spec.rdoc_options << '-T hanna'
31
+ rescue GEM::LoadError
32
+ # hanna not installed, continue
21
33
  end
22
- # Use hanna RDoc template
23
- $hoe.spec.rdoc_options = %w{--main README.rdoc -T hanna}
24
34
 
25
35
  require 'newgem/tasks'
26
36
  Dir['tasks/**/*.rake'].each { |t| load t }
37
+ task :postrelease => [:publish_docs, :announce]
27
38
 
28
39
  # TODO - want other tests/tasks run by default? Add them to the list
29
40
  # remove_task :default
data/bin/pidgin2adium CHANGED
@@ -32,7 +32,7 @@ oparser = OptionParser.new do |opts|
32
32
  "is you. Whitespace and case do not matter.") do |aliases|
33
33
  options[:aliases] = aliases
34
34
  end
35
- opts.on('-o', '--out [OUT_DIR]',
35
+ opts.on('-o', '--out OUT_DIR',
36
36
  'The top-level directory under which to',
37
37
  'store the logs (each in its own folder',
38
38
  'by screen name).',
@@ -0,0 +1,198 @@
1
+ /*
2
+ * Balances tags of string using a modified stack. Returns a balanced string.
3
+ *
4
+ * From Wordpress's formatting.php and rewritten in C by
5
+ * Gabe Berke-Williams, 2010.
6
+ *
7
+ * Original Author:: Leonard Lin <leonard@acm.org>
8
+ * License:: GPL v2.0
9
+ * Copyright:: November 4, 2001
10
+ */
11
+
12
+ #include <ruby.h>
13
+
14
+ #ifndef RARRAY_PTR
15
+ #define RARRAY_PTR(arr) RARRAY(arr)->ptr
16
+ #endif
17
+
18
+ #ifndef RSTRING_LEN
19
+ #define RSTRING_LEN(str) RSTRING(str)->len
20
+ #endif
21
+
22
+ VALUE balance_tags_c(VALUE, VALUE);
23
+ static VALUE mP2A;
24
+
25
+ /*
26
+ * call-seq: Pidgin2Adium.balance_tags_c(text) => text with balanced HTML tags
27
+ *
28
+ * Balances tags of _text_. Returns modified text.
29
+ */
30
+ VALUE balance_tags_c(VALUE mod, VALUE text){
31
+ if( TYPE(text) != T_STRING ){
32
+ rb_raise(rb_eArgError, "bad argument to balance_tags_c, String only please.");
33
+ }
34
+ VALUE tagstack = rb_ary_new2(1);
35
+ int stacksize = 0;
36
+ VALUE tagqueue = rb_str_new2("");
37
+ VALUE ZERO = INT2FIX(0),
38
+ ONE = INT2FIX(1);
39
+ VALUE newtext = rb_str_new2("");
40
+ // Known single-entity/self-closing tags
41
+ VALUE single_tags = rb_ary_new3(5,
42
+ rb_str_new2("br"),
43
+ rb_str_new2("hr"),
44
+ rb_str_new2("img"),
45
+ rb_str_new2("input"),
46
+ rb_str_new2("meta"));
47
+ // Tags that can be immediately nested within themselves
48
+ VALUE nestable_tags = rb_ary_new3(4,
49
+ rb_str_new2("blockquote"),
50
+ rb_str_new2("div"),
51
+ rb_str_new2("span"),
52
+ rb_str_new2("font"));
53
+ // 1: tagname, with possible leading "/"
54
+ // 2: attributes
55
+ VALUE tag_regex = rb_reg_regcomp(rb_str_new2("<(\\/?\\w*)\\s*([^>]*)>"));
56
+ VALUE pos; // position in text
57
+ VALUE match;
58
+ VALUE tag;
59
+ VALUE attributes;
60
+ VALUE t; // loop variable when iterating over tagstack at end of while loop
61
+ int matchlen;
62
+ int done = 0;
63
+ int j, k, i; // loop counters
64
+
65
+ // WP bug fix for comments - in case you REALLY meant to type '< !--'
66
+ rb_funcall(text, rb_intern("gsub!"), 2,
67
+ rb_str_new2("< !--"),
68
+ rb_str_new2("< !--"));
69
+
70
+ // WP bug fix for LOVE <3 (and other situations with '<' before a number)
71
+ rb_funcall(text, rb_intern("gsub!"), 2,
72
+ rb_reg_regcomp(rb_str_new2("<([0-9]{1})")),
73
+ rb_str_new2("&lt;\\1"));
74
+
75
+ pos = rb_funcall(text, rb_intern("=~"), 1, tag_regex);
76
+ done = (pos == Qnil);
77
+ while ( ! done ){
78
+ rb_str_concat(newtext, tagqueue);
79
+ match = rb_funcall(text, rb_intern("match"), 1, tag_regex);
80
+ tag = rb_funcall(rb_reg_nth_match(1, match), rb_intern("downcase"), 0);
81
+ attributes = rb_reg_nth_match(2, match);
82
+
83
+ matchlen = NUM2INT(rb_funcall(rb_reg_nth_match(0, match), rb_intern("size"), 0));
84
+
85
+ // clear the shifter
86
+ tagqueue = rb_str_new2("");
87
+ // Pop or Push
88
+ if (0 == rb_str_cmp(rb_str_substr(tag, 0, 1), rb_str_new2("/"))){ // End Tag
89
+ rb_funcall(tag, rb_intern("slice!"), 2, ZERO, ONE);
90
+ // if too many closing tags
91
+ if(stacksize <= 0){
92
+ tag = rb_str_new2("");
93
+ //or close to be safe: tag = '/' << tag
94
+ } else if (0 == rb_str_cmp(RARRAY_PTR(tagstack)[stacksize - 1], tag)){
95
+ // found closing tag
96
+ // if stacktop value == tag close value then pop
97
+ // Close Tag
98
+ tag = rb_str_append(rb_str_new2("</"), tag);
99
+ rb_str_concat(tag, rb_str_new2(">"));
100
+ // Pop
101
+ rb_ary_pop(tagstack);
102
+ stacksize--;
103
+ } else { // closing tag not at top, search for it
104
+ for(j=stacksize-1; j>=0; j--){
105
+ if(0 == rb_str_cmp(RARRAY_PTR(tagstack)[j], tag) ){
106
+ // add tag to tagqueue
107
+ for(k = stacksize-1;k>=j;k--){
108
+ rb_str_concat(tagqueue, rb_str_new2("</"));
109
+ rb_str_concat(tagqueue, rb_ary_pop(tagstack));
110
+ rb_str_concat(tagqueue, rb_str_new2(">"));
111
+ stacksize--;
112
+ }
113
+ break;
114
+ }
115
+ }
116
+ tag = rb_str_new2("");
117
+ }
118
+ } else {
119
+ // Begin Tag
120
+
121
+ // Tag Cleaning
122
+
123
+ if( ( RSTRING_LEN(attributes) > 0 && // test length before rb_str_substr
124
+ (0 == rb_str_cmp(rb_str_substr(attributes, -1, 1), rb_str_new2("/"))) ) ||
125
+ (0 == rb_str_cmp(tag, rb_str_new2(""))) ){
126
+ // If: self-closing or '', don't do anything.
127
+ } else if ( rb_ary_includes(single_tags, tag) ) {
128
+ // ElseIf: it's a known single-entity tag but it doesn't close itself, do so
129
+ rb_str_concat(attributes, rb_str_new2("/"));
130
+ } else {
131
+ // Push the tag onto the stack
132
+ // If the top of the stack is the same as the tag we want
133
+ // to push, close previous tag
134
+ if ( (stacksize > 0) &&
135
+ (Qfalse == rb_ary_includes(nestable_tags, tag)) &&
136
+ (0 == rb_str_cmp(rb_ary_entry(tagstack, stacksize - 1), tag))){
137
+ tagqueue = rb_str_new2("</");
138
+ rb_str_concat(tagqueue, rb_ary_pop(tagstack));
139
+ rb_str_concat(tagqueue, rb_str_new2(">"));
140
+ stacksize--;
141
+ }
142
+ rb_ary_push(tagstack, tag);
143
+ stacksize++;
144
+ }
145
+
146
+ // Attributes
147
+ if( 0 != rb_str_cmp(attributes, rb_str_new2("")) ){
148
+ attributes = rb_str_plus(rb_str_new2(" "), attributes);
149
+ }
150
+ tag = rb_str_plus(rb_str_new2("<"), tag);
151
+ rb_str_concat(tag, attributes);
152
+ rb_str_concat(tag, rb_str_new2(">"));
153
+ //If already queuing a close tag, then put this tag on, too
154
+ if( RSTRING_LEN(tagqueue) > 0 ){
155
+ rb_str_concat(tagqueue, tag);
156
+ tag = rb_str_new2("");
157
+ }
158
+ }
159
+ rb_str_concat(newtext,
160
+ rb_str_plus(rb_str_substr(text, 0, pos-1), tag));
161
+ text = rb_str_substr(text,
162
+ NUM2INT(pos)+matchlen,
163
+ RSTRING_LEN(text) - (NUM2INT(pos)+matchlen));
164
+ pos = rb_funcall(text, rb_intern("=~"), 1, tag_regex);
165
+ done = (pos == Qnil);
166
+ }
167
+
168
+ // Clear Tag Queue
169
+ rb_str_concat(newtext, tagqueue);
170
+
171
+ // Add Remaining text
172
+ rb_str_concat(newtext, text);
173
+
174
+ i = NUM2INT(rb_funcall(tagstack, rb_intern("length"), 0)) - 1;
175
+ // Empty Stack
176
+ for(; i >= 0; i--){
177
+ // Add remaining tags to close
178
+ t = RARRAY_PTR(tagstack)[i];
179
+ rb_str_concat(newtext, rb_str_new2("</"));
180
+ rb_str_concat(newtext, t);
181
+ rb_str_concat(newtext, rb_str_new2(">"));
182
+ }
183
+
184
+ // WP fix for the bug with HTML comments
185
+ rb_funcall(newtext, rb_intern("gsub!"), 2,
186
+ rb_str_new2("< !--"),
187
+ rb_str_new2("<!--"));
188
+ rb_funcall(newtext, rb_intern("gsub!"), 2,
189
+ rb_str_new2("< !--"),
190
+ rb_str_new2("< !--"));
191
+
192
+ return newtext;
193
+ }
194
+
195
+ void Init_balance_tags_c(){
196
+ mP2A = rb_define_module("Pidgin2Adium");
197
+ rb_define_module_function(mP2A, "balance_tags_c", balance_tags_c, 1);
198
+ }
@@ -0,0 +1,4 @@
1
+ require 'mkmf'
2
+
3
+ dir_config("balance_tags_c")
4
+ create_makefile("balance_tags_c")
data/lib/pidgin2adium.rb CHANGED
@@ -14,7 +14,7 @@ module Pidgin2Adium
14
14
  ADIUM_LOG_DIR = File.expand_path('~/Library/Application Support/Adium 2.0/Users/Default/Logs/') << '/'
15
15
  # These files/directories show up in Dir.entries()
16
16
  BAD_DIRS = %w{. .. .DS_Store Thumbs.db .system}
17
- VERSION = "2.0.2"
17
+ VERSION = "3.0.0"
18
18
  # For displaying after we finish converting
19
19
  @@oops_messages = []
20
20
  @@error_messages = []
@@ -38,6 +38,7 @@ module Pidgin2Adium
38
38
  module_function :log_msg, :oops, :error
39
39
  #######################
40
40
 
41
+ # Parses the provided log.
41
42
  # Returns a LogFile instance or false if an error occurred.
42
43
  def parse(logfile_path, my_aliases)
43
44
  logfile_path = File.expand_path(logfile_path)
@@ -54,7 +55,8 @@ module Pidgin2Adium
54
55
 
55
56
  return parser.parse()
56
57
  end
57
-
58
+
59
+ # Parses the provided log and writes out the log in Adium format.
58
60
  # Returns the path to the converted log, false if an error occurred, or
59
61
  # Pidgin2Adium::FILE_EXISTS if file already exists AND opts[:overwrite] =
60
62
  # false.
@@ -26,12 +26,12 @@ module Pidgin2Adium
26
26
  # key is for Pidgin, value is for Adium
27
27
  # Just used for <service>.<screenname> in directory structure
28
28
  service_name_map = {'aim' => 'AIM',
29
- 'jabber' =>'jabber',
29
+ 'jabber' =>'Jabber',
30
30
  'gtalk'=> 'GTalk',
31
31
  'icq' => 'ICQ',
32
32
  'qq' => 'QQ',
33
33
  'msn' => 'MSN',
34
- 'yahoo' => 'Yahoo'}
34
+ 'yahoo' => 'Yahoo!'}
35
35
 
36
36
  @service = service_name_map[service.downcase]
37
37
  end
@@ -7,7 +7,7 @@
7
7
  require 'parsedate'
8
8
  require 'time' # for Time.zone_offset
9
9
 
10
- require 'pidgin2adium/balance_tags'
10
+ require 'balance_tags_c'
11
11
  require 'pidgin2adium/log_file'
12
12
 
13
13
  module Pidgin2Adium
@@ -42,12 +42,12 @@ module Pidgin2Adium
42
42
  # Time regexes must be set before pre_parse().
43
43
  # "4/18/2007 11:02:00 AM" => %w{4, 18, 2007, 11, 02, 00, AM}
44
44
  # ONLY used (if at all) in first line of chat ("Conversation with...at...")
45
- @time_regex_first_line = %r{(\d{1,2})/(\d{1,2})/(\d{4}) (\d{1,2}):(\d{2}):(\d{2}) ([AP]M)}
45
+ @time_regex_first_line = %r{^(\d{1,2})/(\d{1,2})/(\d{4}) (\d{1,2}):(\d{2}):(\d{2}) ([AP]M)$}
46
46
  # "2007-04-17 12:33:13" => %w{2007, 04, 17, 12, 33, 13}
47
- @time_regex = /(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/
47
+ @time_regex = /^(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})$/
48
48
  # sometimes a line in a chat doesn't have a full timestamp
49
49
  # "04:22:05 AM" => %w{04 22 05 AM}
50
- @minimal_time_regex = /(\d{1,2}):(\d{2}):(\d{2})( [AP]M)?/
50
+ @minimal_time_regex = /^(\d{1,2}):(\d{2}):(\d{2})( [AP]M)?$/
51
51
 
52
52
  # Whether or not the first line is parseable.
53
53
  @first_line_is_valid = true
@@ -90,10 +90,10 @@ module Pidgin2Adium
90
90
  /(.+) is offering to send file/,
91
91
  /^Transfer of file .+ complete$/,
92
92
  /Error reading|writing|accessing .+: .+/,
93
- /You cancelled the transfer of/,
93
+ /You cancell?ed the transfer of/,
94
94
  /File transfer cancelled/,
95
- /(.+) cancelled the transfer of/,
96
- /(.+) cancelled the file transfer/,
95
+ /(.+?) cancell?ed the transfer of/,
96
+ /(.+?) cancelled the file transfer/,
97
97
  # Direct IM - actual (dis)connect events are their own types
98
98
  /^Attempting to connect to (.+) at .+ for Direct IM\./,
99
99
  /^Asking (.+) to connect to us at .+ for Direct IM\./,
@@ -106,9 +106,6 @@ module Pidgin2Adium
106
106
  /^Conflicting Key Received!$/,
107
107
  /^Error in decryption- asking for resend\.\.\.$/,
108
108
  /^Making new key pair\.\.\.$/,
109
- # file transfer
110
- /You canceled the transfer of/,
111
- /(.+?) canceled the transfer of/,
112
109
  # sending errors
113
110
  /^Last outgoing message not received properly- resetting$/,
114
111
  /Resending\.\.\./,
@@ -178,9 +175,8 @@ module Pidgin2Adium
178
175
  if tz_match and tz_match[1]
179
176
  tz_offset = tz_match[1]
180
177
  else
181
- zone = Time.local(Time.new.year).zone
182
178
  # "-0500" (3d rather than 2d to allow for "+")
183
- tz_offset = sprintf('+%03d00', Time.zone_offset(zone) / 3600)
179
+ tz_offset = sprintf('%+03d00', Time.zone_offset(Time.now.zone) / 3600)
184
180
  end
185
181
  return tz_offset
186
182
  end
@@ -255,7 +251,7 @@ module Pidgin2Adium
255
251
  user_SN = first_line_match[3].downcase.tr(' ', '')
256
252
  partner_SN = first_line_match[1]
257
253
  pidgin_chat_time_start = first_line_match[2]
258
- basic_time_info = case @first_line
254
+ basic_time_info = case pidgin_chat_time_start
259
255
  when @time_regex: [$1.to_i, $2.to_i, $3.to_i]
260
256
  when @time_regex_first_line: [$3.to_i, $1.to_i, $2.to_i]
261
257
  end
@@ -488,18 +484,15 @@ module Pidgin2Adium
488
484
 
489
485
  styleparts = style.split(/; ?/)
490
486
  styleparts.map! do |p|
491
- if p =~ /^color/
492
- # Regarding the bit with the ">", sometimes this happens:
493
- # <span style="color: #000000>today;">today was busy</span>
494
- # Then p = "color: #000000>today"
495
- # Or it can end in ">;", with no text before the semicolon.
496
- # So remove the ">" and anything following it.
497
-
498
- # Use regex instead of string, to account for funky ">" stuff
499
- if p =~ /color: #000000/
487
+ if p[0,5] == 'color'
488
+ if p.include?('color: #000000')
500
489
  next
501
490
  elsif p =~ /(color: #[0-9a-fA-F]{6})(>.*)?/
502
- # Keep the color but remove the bit after it
491
+ # Regarding the bit with the ">", sometimes this happens:
492
+ # <span style="color: #000000>today;">today was busy</span>
493
+ # Then p = "color: #000000>today"
494
+ # Or it can end in ">;", with no text before the semicolon.
495
+ # So keep the color but remove the ">" and anything following it.
503
496
  next($1)
504
497
  end
505
498
  else
@@ -546,7 +539,6 @@ module Pidgin2Adium
546
539
  # Basic message with body text (as opposed to pure status messages, which
547
540
  # have no body).
548
541
  class XMLMessage < Message
549
- include Pidgin2Adium
550
542
  def initialize(sender, time, buddy_alias, body)
551
543
  super(sender, time, buddy_alias)
552
544
  @body = body
@@ -571,7 +563,7 @@ module Pidgin2Adium
571
563
  normalize_body_entities!()
572
564
  # Fix mismatched tags. Yes, it's faster to do it per-message
573
565
  # than all at once.
574
- @body = balance_tags(@body)
566
+ @body = Pidgin2Adium.balance_tags_c(@body)
575
567
  if @buddy_alias[0,3] == '***'
576
568
  # "***<alias>" is what pidgin sets as the alias for a /me action
577
569
  @buddy_alias.slice!(0,3)
data/script/console ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+ # File: script/console
3
+ irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb'
4
+
5
+ libs = " -r irb/completion"
6
+ # Perhaps use a console_lib to store any extra methods I may want available in the cosole
7
+ # libs << " -r #{File.dirname(__FILE__) + '/../lib/console_lib/console_logger.rb'}"
8
+ libs << " -r #{File.dirname(__FILE__) + '/../lib/p2a.rb'}"
9
+ puts "Loading p2a gem"
10
+ exec "#{irb} #{libs} --simple-prompt"
data/script/destroy ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
3
+
4
+ begin
5
+ require 'rubigen'
6
+ rescue LoadError
7
+ require 'rubygems'
8
+ require 'rubigen'
9
+ end
10
+ require 'rubigen/scripts/destroy'
11
+
12
+ ARGV.shift if ['--help', '-h'].include?(ARGV[0])
13
+ RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
14
+ RubiGen::Scripts::Destroy.new.run(ARGV)
data/script/generate ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
3
+
4
+ begin
5
+ require 'rubigen'
6
+ rescue LoadError
7
+ require 'rubygems'
8
+ require 'rubigen'
9
+ end
10
+ require 'rubigen/scripts/generate'
11
+
12
+ ARGV.shift if ['--help', '-h'].include?(ARGV[0])
13
+ RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
14
+ RubiGen::Scripts::Generate.new.run(ARGV)
@@ -0,0 +1,13 @@
1
+ namespace :extconf do
2
+ desc "Compiles the Ruby extension"
3
+ task :compile
4
+ end
5
+
6
+ task :compile => "extconf:compile"
7
+
8
+ task :test => :compile
9
+
10
+ BIN = "*.{bundle,jar,so,obj,pdb,lib,def,exp}"
11
+ $hoe.clean_globs |= ["ext/**/#{BIN}", "lib/**/#{BIN}", 'ext/**/Makefile']
12
+ $hoe.spec.require_paths = Dir['{lib,ext/*}']
13
+ $hoe.spec.extensions = FileList["ext/**/extconf.rb"].to_a
@@ -0,0 +1,43 @@
1
+ namespace :extconf do
2
+ extension = File.basename(__FILE__, '.rake')
3
+
4
+ ext = "ext/#{extension}"
5
+ ext_so = "#{ext}/#{extension}.#{Config::CONFIG['DLEXT']}"
6
+ ext_files = FileList[
7
+ "#{ext}/*.c",
8
+ "#{ext}/*.h",
9
+ "#{ext}/*.rl",
10
+ "#{ext}/extconf.rb",
11
+ "#{ext}/Makefile",
12
+ # "lib"
13
+ ]
14
+
15
+
16
+ task :compile => extension do
17
+ if Dir.glob("**/#{extension}.{o,so,dll}").length == 0
18
+ STDERR.puts "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
19
+ STDERR.puts "Gem actually failed to build. Your system is"
20
+ STDERR.puts "NOT configured properly to build #{GEM_NAME}."
21
+ STDERR.puts "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
22
+ exit(1)
23
+ end
24
+ end
25
+
26
+ desc "Builds just the #{extension} extension"
27
+ task extension.to_sym => ["#{ext}/Makefile", ext_so ]
28
+
29
+ file "#{ext}/Makefile" => ["#{ext}/extconf.rb"] do
30
+ Dir.chdir(ext) do ruby "extconf.rb" end
31
+ end
32
+
33
+ file ext_so => ext_files do
34
+ Dir.chdir(ext) do
35
+ sh(PLATFORM =~ /win32/ ? 'nmake' : 'make') do |ok, res|
36
+ if !ok
37
+ require "fileutils"
38
+ FileUtils.rm Dir.glob('*.{so,o,dll,bundle}')
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,10 @@
1
+ require "test/unit"
2
+
3
+ $:.unshift File.dirname(__FILE__) + "/../ext/balance_tags_c"
4
+ require "balance_tags_c.so"
5
+
6
+ class TestBalanceTagsCExtn < Test::Unit::TestCase
7
+ def test_truth
8
+ assert true
9
+ end
10
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pidgin2adium
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.2
4
+ version: 3.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gabe B-W
@@ -9,9 +9,29 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-12-18 00:00:00 -08:00
12
+ date: 2010-01-31 00:00:00 -05:00
13
13
  default_executable:
14
14
  dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: rubyforge
17
+ type: :development
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 2.0.3
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: gemcutter
27
+ type: :development
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 0.3.0
34
+ version:
15
35
  - !ruby/object:Gem::Dependency
16
36
  name: hoe
17
37
  type: :development
@@ -20,7 +40,7 @@ dependencies:
20
40
  requirements:
21
41
  - - ">="
22
42
  - !ruby/object:Gem::Version
23
- version: 2.4.0
43
+ version: 2.5.0
24
44
  version:
25
45
  description: |-
26
46
  Pidgin2Adium is a fast, easy way to convert Pidgin (formerly gaim) logs to the
@@ -30,23 +50,31 @@ email:
30
50
  - pidgin2adium@brandeis.edu
31
51
  executables:
32
52
  - pidgin2adium
33
- extensions: []
34
-
53
+ extensions:
54
+ - ext/balance_tags_c/extconf.rb
35
55
  extra_rdoc_files:
36
56
  - History.txt
37
57
  - Manifest.txt
38
58
  - README.rdoc
39
59
  files:
60
+ - .autotest
40
61
  - History.txt
41
62
  - Manifest.txt
42
63
  - README.rdoc
43
64
  - Rakefile.rb
44
65
  - bin/pidgin2adium
66
+ - ext/balance_tags_c/balance_tags_c.c
67
+ - ext/balance_tags_c/extconf.rb
45
68
  - lib/pidgin2adium.rb
46
- - lib/pidgin2adium/balance_tags.rb
47
69
  - lib/pidgin2adium/log_converter.rb
48
70
  - lib/pidgin2adium/log_file.rb
49
71
  - lib/pidgin2adium/log_parser.rb
72
+ - script/console
73
+ - script/destroy
74
+ - script/generate
75
+ - tasks/extconf.rake
76
+ - tasks/extconf/balance_tags_c.rake
77
+ - test/test_balance_tags_c_extn.rb
50
78
  has_rdoc: true
51
79
  homepage: http://rubyforge.org/projects/pidgin2adium/
52
80
  licenses: []
@@ -55,10 +83,10 @@ post_install_message:
55
83
  rdoc_options:
56
84
  - --main
57
85
  - README.rdoc
58
- - -T
59
- - hanna
86
+ - -T hanna
60
87
  require_paths:
61
88
  - lib
89
+ - ext/balance_tags_c
62
90
  required_ruby_version: !ruby/object:Gem::Requirement
63
91
  requirements:
64
92
  - - ">="
@@ -78,5 +106,5 @@ rubygems_version: 1.3.5
78
106
  signing_key:
79
107
  specification_version: 3
80
108
  summary: Pidgin2Adium is a fast, easy way to convert Pidgin (formerly gaim) logs to the Adium format
81
- test_files: []
82
-
109
+ test_files:
110
+ - test/test_balance_tags_c_extn.rb
@@ -1,118 +0,0 @@
1
- module Pidgin2Adium
2
- # Balances tags of string using a modified stack. Returns a balanced
3
- # string, but also affects the text passed into it!
4
- # Use text = balance_tags(text).
5
-
6
- # From Wordpress's formatting.php; rewritten in Ruby by Gabe
7
- # Berke-Williams, 2009.
8
- # Author:: Leonard Lin <leonard@acm.org>
9
- # License:: GPL v2.0
10
- # Copyright:: November 4, 2001
11
- def balance_tags( text )
12
- tagstack = []
13
- stacksize = 0
14
- tagqueue = ''
15
- newtext = ''
16
- single_tags = %w{br hr img input meta} # Known single-entity/self-closing tags
17
- #nestable_tags = %w{blockquote div span} # Tags that can be immediately nested within themselves
18
- nestable_tags = %w{blockquote div span font} # Tags that can be immediately nested within themselves
19
- # 1: tagname, with possible leading "/"
20
- # 2: attributes
21
- tag_regex = /<(\/?\w*)\s*([^>]*)>/
22
-
23
- # WP bug fix for comments - in case you REALLY meant to type '< !--'
24
- text.gsub!('< !--', '< !--')
25
-
26
- # WP bug fix for LOVE <3 (and other situations with '<' before a number)
27
- text.gsub!(/<([0-9]{1})/, '&lt;\1')
28
-
29
- while ( pos = (text =~ tag_regex) )
30
- newtext << tagqueue
31
- tag = $1.downcase
32
- attributes = $2
33
- matchlen = $~[0].size
34
-
35
- # clear the shifter
36
- tagqueue = ''
37
- # Pop or Push
38
- if (tag[0,1] == "/") # End Tag
39
- tag.slice!(0,1)
40
- # if too many closing tags
41
- if(stacksize <= 0)
42
- tag = ''
43
- #or close to be safe: tag = '/' << tag
44
- elsif (tagstack[stacksize - 1] == tag) # found closing tag
45
- # if stacktop value == tag close value then pop
46
- tag = '</' << tag << '>' # Close Tag
47
- # Pop
48
- tagstack.pop
49
- stacksize -= 1
50
- else # closing tag not at top, search for it
51
- (stacksize-1).downto(0) do |j|
52
- if (tagstack[j] == tag)
53
- # add tag to tagqueue
54
- ss = stacksize - 1
55
- ss.downto(j) do |k|
56
- tagqueue << '</' << tagstack.pop << '>'
57
- stacksize -= 1
58
- end
59
- break
60
- end
61
- end
62
- tag = ''
63
- end
64
- else
65
- # Begin Tag
66
-
67
- # Tag Cleaning
68
- if( (attributes[-1,1] == '/') || (tag == '') )
69
- # If: self-closing or '', don't do anything.
70
- elsif ( single_tags.include?(tag) )
71
- # ElseIf: it's a known single-entity tag but it doesn't close itself, do so
72
- attributes << '/'
73
- else
74
- # Push the tag onto the stack
75
- # If the top of the stack is the same as the tag we want to push, close previous tag
76
- if ((stacksize > 0) &&
77
- ! nestable_tags.include?(tag) &&
78
- (tagstack[stacksize - 1] == tag))
79
- tagqueue = '</' << tagstack.pop << '>'
80
- stacksize -= 1
81
- end
82
- tagstack.push(tag)
83
- stacksize += 1
84
- end
85
-
86
- # Attributes
87
- if(attributes != '')
88
- attributes = ' ' << attributes
89
- end
90
- tag = '<' << tag << attributes << '>'
91
- #If already queuing a close tag, then put this tag on, too
92
- if (tagqueue)
93
- tagqueue << tag
94
- tag = ''
95
- end
96
- end
97
- newtext << text[0,pos] << tag
98
- text = text[pos+matchlen, text.length - (pos+matchlen)]
99
- end
100
-
101
- # Clear Tag Queue
102
- newtext << tagqueue
103
-
104
- # Add Remaining text
105
- newtext << text
106
-
107
- # Empty Stack
108
- tagstack.reverse_each do |t|
109
- newtext << '</' << t << '>' # Add remaining tags to close
110
- end
111
-
112
- # WP fix for the bug with HTML comments
113
- newtext.gsub!("< !--", "<!--")
114
- newtext.gsub!("< !--", "< !--")
115
-
116
- return newtext
117
- end
118
- end