import json
from collections import OrderedDict
from .command import Command
from .settings import FormatterSettings


class Formatter():
    def __init__(self, name, command='', args=''):
        self.__name = name
        self.__command = command.split(' ') if command else []
        self.__args = args.split(' ') if args else []
        self.__settings = FormatterSettings(name.lower())

    @property
    def name(self):
        return self.__name

    @property
    def sources(self):
        return self.__settings.sources

    @property
    def options(self):
        return self.__settings.options

    @property
    def format_on_save(self):
        return self.__settings.format_on_save

    @format_on_save.setter
    def format_on_save(self, value):
        self.__settings.format_on_save = value

    def format(self, input):
        command = self.__command
        options = self.options
        args = self.__args
        return Command(command + options + args).run(input)


class JsonFormatter(Formatter):
    def __init__(self):
        super().__init__(name='JSON')

    def format(self, input):
        try:
            data = json.loads(input, object_pairs_hook=OrderedDict)
            return json.dumps(data, indent=4), None
        except ValueError:
            return None, 'Invalid JSON'

import json
from collections import OrderedDict
from .command import Command
from .settings import FormatterSettings


class Formatter():
    def __init__(self, name, command=None, args=None, formatter=None):
        self.__name = name
        self.__format = formatter
        self.__settings = FormatterSettings(name.lower())

        if not formatter:
            command = command.split(' ') if command else []
            options = self.__settings.options
            args = args.split(' ') if args else []
            shell_command = Command(command + options + args)

            def external_format(input):
                return shell_command.run(input)

            self.__format = external_format

    @property
    def name(self):
        return self.__name

    @property
    def sources(self):
        return self.__settings.sources

    @property
    def format_on_save(self):
        return self.__settings.format_on_save

    @format_on_save.setter
    def format_on_save(self, value):
        self.__settings.format_on_save = value

    def format(self, input):
        return self.__format(input)


class JsonFormatter(Formatter):
    def __init__(self):
        def format_json(input):
            try:
                data = json.loads(input, object_pairs_hook=OrderedDict)
                return json.dumps(data, indent=4), None
            except ValueError:
                return None, 'Invalid JSON'

        super().__init__(name='JSON', formatter=format_json)

Allow format function to be provided to Formatter constructor
Allow format function to be provided to Formatter constructor

  import json
  from collections import OrderedDict
  from .command import Command
  from .settings import FormatterSettings
  
  
  class Formatter():
-     def __init__(self, name, command='', args=''):
+     def __init__(self, name, command=None, args=None, formatter=None):
          self.__name = name
+         self.__format = formatter
-         self.__command = command.split(' ') if command else []
-         self.__args = args.split(' ') if args else []
          self.__settings = FormatterSettings(name.lower())
+ 
+         if not formatter:
+             command = command.split(' ') if command else []
+             options = self.__settings.options
+             args = args.split(' ') if args else []
+             shell_command = Command(command + options + args)
+ 
+             def external_format(input):
+                 return shell_command.run(input)
+ 
+             self.__format = external_format
  
      @property
      def name(self):
          return self.__name
  
      @property
      def sources(self):
          return self.__settings.sources
  
      @property
-     def options(self):
-         return self.__settings.options
- 
-     @property
      def format_on_save(self):
          return self.__settings.format_on_save
  
      @format_on_save.setter
      def format_on_save(self, value):
          self.__settings.format_on_save = value
  
      def format(self, input):
+         return self.__format(input)
-         command = self.__command
-         options = self.options
-         args = self.__args
-         return Command(command + options + args).run(input)
  
  
  class JsonFormatter(Formatter):
      def __init__(self):
-         super().__init__(name='JSON')
+         def format_json(input):
+             try:
+                 data = json.loads(input, object_pairs_hook=OrderedDict)
+                 return json.dumps(data, indent=4), None
+             except ValueError:
+                 return None, 'Invalid JSON'
  
+         super().__init__(name='JSON', formatter=format_json)
-     def format(self, input):
-         try:
-             data = json.loads(input, object_pairs_hook=OrderedDict)
-             return json.dumps(data, indent=4), None
-         except ValueError:
-             return None, 'Invalid JSON'
  
Allow format function to be provided to Formatter constructor
## Code Before:
import json
from collections import OrderedDict
from .command import Command
from .settings import FormatterSettings


class Formatter():
    def __init__(self, name, command='', args=''):
        self.__name = name
        self.__command = command.split(' ') if command else []
        self.__args = args.split(' ') if args else []
        self.__settings = FormatterSettings(name.lower())

    @property
    def name(self):
        return self.__name

    @property
    def sources(self):
        return self.__settings.sources

    @property
    def options(self):
        return self.__settings.options

    @property
    def format_on_save(self):
        return self.__settings.format_on_save

    @format_on_save.setter
    def format_on_save(self, value):
        self.__settings.format_on_save = value

    def format(self, input):
        command = self.__command
        options = self.options
        args = self.__args
        return Command(command + options + args).run(input)


class JsonFormatter(Formatter):
    def __init__(self):
        super().__init__(name='JSON')

    def format(self, input):
        try:
            data = json.loads(input, object_pairs_hook=OrderedDict)
            return json.dumps(data, indent=4), None
        except ValueError:
            return None, 'Invalid JSON'

## Instruction:
Allow format function to be provided to Formatter constructor
## Code After:
import json
from collections import OrderedDict
from .command import Command
from .settings import FormatterSettings


class Formatter():
    def __init__(self, name, command=None, args=None, formatter=None):
        self.__name = name
        self.__format = formatter
        self.__settings = FormatterSettings(name.lower())

        if not formatter:
            command = command.split(' ') if command else []
            options = self.__settings.options
            args = args.split(' ') if args else []
            shell_command = Command(command + options + args)

            def external_format(input):
                return shell_command.run(input)

            self.__format = external_format

    @property
    def name(self):
        return self.__name

    @property
    def sources(self):
        return self.__settings.sources

    @property
    def format_on_save(self):
        return self.__settings.format_on_save

    @format_on_save.setter
    def format_on_save(self, value):
        self.__settings.format_on_save = value

    def format(self, input):
        return self.__format(input)


class JsonFormatter(Formatter):
    def __init__(self):
        def format_json(input):
            try:
                data = json.loads(input, object_pairs_hook=OrderedDict)
                return json.dumps(data, indent=4), None
            except ValueError:
                return None, 'Invalid JSON'

        super().__init__(name='JSON', formatter=format_json)
