import sublime, sublime_plugin, re

class CodeConverter(object):
    def __init__(self, s):
        self.s = s

    def result(self):
        self.multilines_to_one_line()
        self.replace_nsstring()
        self.convert_square_brackets_expression()
        self.remove_semicolon_at_the_end()
        self.remove_autorelease()
        self.remove_type_declaration()
        return self.s

    # Helpers
    def convert_args(self, matchobj):
        # Consider args with colon followed by spaces
        following_args = re.sub(r'([^:]+)(\s+)', r'\1,', matchobj.group(2))
        # Clear extra spaces
        following_args = re.sub(r'\s+', '', following_args)
        return "%s(%s)" % (matchobj.group(1), following_args)

    def ruby_style_code(self, matchobj):
        msg = re.sub(r'([^:]+)\:\s*(.+)', self.convert_args, matchobj.group(2))
        return "%s.%s" % (matchobj.group(1), msg)

    # Conversions
    def multilines_to_one_line(self):
        # Remove trailing white space first. Refs: TrimTrailingWhiteSpace
        self.s = re.sub(r'[\t ]+$', '', self.s)
        self.s = re.sub(re.compile(r'([^;\s])$\n\s*', re.MULTILINE), r'\1 ', self.s)
        return self

    def replace_nsstring(self):
        self.s = re.sub(r'@("(?:[^\\"]|\\.)*")', r'\1', self.s)
        return self

    def convert_square_brackets_expression(self):
        max_attempt = 10 # Avoid infinite loops
        attempt_count = 0
        square_pattern = re.compile(r'\[([^\[\]]+?)\s+([^\[\]]+?)\]')
        while True:
            attempt_count += 1
            m = re.search(square_pattern, self.s)
            if attempt_count > max_attempt :
                break
            elif m :
                self.s = re.sub(square_pattern, self.ruby_style_code, self.s)
            else :
                break
        return self

    def remove_semicolon_at_the_end(self):
        self.s = re.sub(r';', '', self.s)
        return self

    def remove_autorelease(self):
        self.s = re.sub(r'\.autorelease$', '', self.s)
        return self

    def remove_type_declaration(self):
        self.s = re.sub(r'^(\s*)[a-zA-Z_0-9]+\s*\*\s*([^=]+)=', r'\1\2=', self.s)
        return self

class ObjcToRubyMotionCommand(sublime_plugin.TextCommand):
    def run(self, edit):
        for region in self.view.sel():
            if region.empty():
                line = self.view.line(region)
                self.replace_objc(edit, line)
            else:
                self.replace_objc(edit, region)

    def replace_objc(self, edit, region):
        # Get the selected text
        s = self.view.substr(region)

        # Replace the selection with transformed text
        self.view.replace(edit, region, CodeConverter(s).result())

@@ -1995,17 +1995,16 @@
 orelease
-$
 ', '', s
@@ -2094,16 +2094,27 @@
  re.sub(
+re.compile(
 r'%5E(%5Cs*)
@@ -2144,16 +2144,31 @@
 %5E=%5D+)=',
+ re.MULTILINE),
  r'%5C1%5C2=

Fix some issues with multilines conversion