Want more features on Pastebin? Sign Up, it's FREE!
Guest

Auto Detect Language.py

By: cgrunwald on Oct 3rd, 2011  |  syntax: Python  |  size: 19.42 KB  |  views: 160  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. #!python.exe
  2. import pickle, re
  3. from os import path
  4.  
  5. __author__ = 'Charles Grunwald (Juntalis) <cgrunwald@gmail.com>'
  6.  
  7. def __setup_configobj__(deps, info):
  8.         """ Setup configobj either in the lib folder or the local folder """
  9.         from os import unlink, mkdir
  10.         import shutil
  11.        
  12.         # Download and unzip
  13.         tmpfile = deps.download(info['url'], info['filename'])
  14.         tmpfolder = path.splitext(tmpfile)[0]
  15.         deps.unzip(tmpfile, tmpfolder)
  16.         unlink(tmpfile)
  17.        
  18.         modfolder = path.join(tmpfolder, 'configobj-4.7.2')
  19.         modpath = [path.join(modfolder, 'configobj.py'), path.join(modfolder, 'validate.py')]
  20.        
  21.         (modpath, modconfigobj) = deps.install(modpath, 'configobj')
  22.         shutil.rmtree(tmpfolder, True)
  23.         return (modconfigobj, modpath)
  24.  
  25. """ Our dependencies """
  26. __dependencies__ = {
  27.         'configobj':
  28.                 (__setup_configobj__, {
  29.                         'filename' : 'configobj.zip',
  30.                         'url' : 'http://www.voidspace.org.uk/downloads/configobj-4.7.2.zip'
  31.                 })
  32. }
  33.  
  34. class ScriptDeps:
  35.         """ Simple class to install any script dependencies we don't have at startup. """
  36.         __modules__ = {}
  37.        
  38.         def __init__(self, dependencies):
  39.                 deps = dependencies
  40.                 for dep in deps.keys():
  41.                         (setup, info) = deps[dep]
  42.                         self.__modules__[dep] = setup(self, info)
  43.  
  44.         def get(self, name):
  45.                 if self.__modules__.has_key(name):
  46.                         return self.__modules__[name]
  47.                 return None
  48.  
  49.         def unzip(self, filename, dir):
  50.                 """ Extract zip file: filename to folder: dir. """
  51.                 import zipfile, os
  52.                 from cStringIO import StringIO
  53.                 zf = zipfile.ZipFile( filename )
  54.                 namelist = zf.namelist()
  55.                 dirlist = filter( lambda x: x.endswith( '/' ), namelist )
  56.                 filelist = filter( lambda x: not x.endswith( '/' ), namelist )
  57.                 # make base
  58.                 pushd = os.getcwd()
  59.                 if not path.isdir( dir ):
  60.                         os.mkdir( dir )
  61.                 os.chdir( dir )
  62.                 # create directory structure
  63.                 dirlist.sort()
  64.                 for dirs in dirlist:
  65.                         dirs = dirs.split( '/' )
  66.                         prefix = ''
  67.                         for dir in dirs:
  68.                                 dirname = path.join( prefix, dir )
  69.                                 if dir and not path.isdir( dirname ):
  70.                                         os.mkdir( dirname )
  71.                                 prefix = dirname
  72.                 # extract files
  73.                 for fn in filelist:
  74.                         try:
  75.                                 out = open( fn, 'wb' )
  76.                                 buffer = StringIO( zf.read( fn ))
  77.                                 buflen = 2 ** 20
  78.                                 datum = buffer.read( buflen )
  79.                                 while datum:
  80.                                         out.write( datum )
  81.                                         datum = buffer.read( buflen )
  82.                                 out.close()
  83.                         except:
  84.                                 import sys
  85.                                 sys.stderr.write('Error while unzipping %s..\n' % filename)
  86.                 os.chdir( pushd )
  87.        
  88.         def download(self, url, filename):
  89.                 """ Download dependencies specified by dictionary __dependencies__"""
  90.                 from urllib import urlretrieve as download
  91.                 from tempfile import gettempdir as tempdir
  92.  
  93.                 # Iterate through dependencies, downloading and moving.
  94.                 result = path.join(tempdir(), filename)
  95.                 download(url, result)
  96.                 return result
  97.        
  98.         def _install_global(self, modpath, modname):
  99.                 # install to the lib folder under Notepad++'s plugin directory.
  100.                 import shutil
  101.                 libdir = path.join(notepad.getNppDir(), 'plugins', 'PythonScript', 'lib')
  102.                 modconfigobj = None
  103.                 try:
  104.                         # install to pythonscript lib folder.
  105.                         for modfile in modpath:
  106.                                 shutil.move(modfile, libdir)
  107.                 except:
  108.                         (modpath, modconfigobj) = self._install_user(modpath, modname)
  109.                 else:
  110.                         modconfigobj = __import__(modname)
  111.                         modpath = path.join(libdir, '%s.py' % modname)
  112.                 return (modpath, modconfigobj)
  113.        
  114.         def _install_user(self, modpath, modname):
  115.                 # install to User's AppData PythonScript/lib
  116.                 import shutil
  117.                 libdir = path.join(path.abspath(path.dirname(path.dirname(__file__))), 'lib')
  118.                 if not path.exists(libdir) or not path.isdir(libdir):
  119.                         mkdir(libdir)
  120.                 for modfile in modpath:
  121.                         shutil.move(modfile, libdir)
  122.                 modconfigobj = __import__(modname)
  123.                 modpath = path.join(libdir, '%s.py' % modname)
  124.                 return (modpath, modconfigobj)
  125.        
  126.         def _install_stub(self, libdir):
  127.                 initfile = path.join(libdir, '__init__.py')
  128.                 if not path.exists(initfile):
  129.                         f = open(initfile,'w')
  130.                         f.write('# Stub')
  131.                         f.close()
  132.                 return initfile
  133.        
  134.         def install(self, modpath, modname, install_global=False):
  135.                 if install_global:
  136.                         return self._install_global(modpath, modname)
  137.                 return self._install_user(modpath, modname)
  138.  
  139. class SimpleCache(dict):
  140.         """
  141.         Simple local cache.
  142.         It saves local data in singleton dictionary with convenient interface
  143.        
  144.         Downloaded from http://code.activestate.com/recipes/577492-simple-local-cache-and-cache-decorator/
  145.        
  146.         Author: Andrey Nikishaev
  147.         License: GPL
  148.         Copyright 2010, http://creotiv.in.ua
  149.         """
  150.        
  151.         def __new__(cls,*args):
  152.                 if not hasattr(cls,'_instance'):
  153.                         cls._instance = dict.__new__(cls)
  154.                 else:
  155.                         raise Exception('SimpleCache already initialized')
  156.                 return cls._instance
  157.        
  158.         @classmethod
  159.         def getInstance(cls):
  160.                 if not hasattr(cls,'_instance'):
  161.                         cls._instance = dict.__new__(cls)
  162.                 return cls._instance
  163.  
  164.         def get(self,name,default=None):
  165.                 """Multilevel get function.
  166.                 Code:          
  167.                 Config().get('opt.opt_level2.key','default_value')
  168.                 """
  169.                 if not name:
  170.                         return default
  171.                 levels = name.split('.')
  172.                 data = self                    
  173.                 for level in levels:
  174.                         try:                   
  175.                                 data = data[level]
  176.                         except:
  177.                                 return default
  178.  
  179.                 return data
  180.        
  181.         def set(self,name,value):
  182.                 """Multilevel set function
  183.                 Code:          
  184.                 Config().set('opt.opt_level2.key','default_value')
  185.                 """
  186.                 levels = name.split('.')
  187.                 arr = self             
  188.                 for name in levels[:-1]:
  189.                         if not arr.has_key(name):                
  190.                                 arr[name] = {}  
  191.                         arr = arr[name]
  192.                 arr[levels[-1]] = value
  193.                
  194.         def getset(self,name,value):
  195.                 """Get cache, if not exists set it and return set value
  196.                 Code:          
  197.                 Config().getset('opt.opt_level2.key','default_value')
  198.                 """
  199.                 g = self.get(name)
  200.                 if not g:
  201.                         g = value
  202.                         self.set(name,g)
  203.                 return g
  204.  
  205. def scache(func):
  206.         def wrapper(*args, **kwargs):
  207.                 cache = SimpleCache.getInstance()
  208.                 fn = "scache." + func.__module__ + func.__class__.__name__ + \
  209.                          func.__name__ + str(args) + str(kwargs)               
  210.                 val = cache.get(fn)
  211.                 if not val:
  212.                         res = func(*args, **kwargs)
  213.                         cache.set(fn,res)
  214.                         return res
  215.                 return val
  216.         return wrapper
  217.  
  218.  
  219. # Try to import configobj module. If we cant, download it and set it up.
  220. try:
  221.         import configobj
  222.         has_configobj = True
  223. except ImportError:
  224.         notepad.messageBox('Could not find module "configobj". Downloading and setting it up now..', 'Dependencies')
  225.         deps = ScriptDeps(__dependencies__)
  226.         (configobj, configobj_path) = deps.get('configobj')
  227.         has_configobj = configobj is not None
  228.         if has_configobj:
  229.                 notepad.messageBox('Module "configobj" setup successfully. You can find it at:\n\n%s' % configobj_path, 'Setup Successful')
  230.         else:
  231.                 notepad.messageBox('Error: Could not import configobj.\nDownload at: http://www.voidspace.org.uk/python/configobj.html', 'Import Error')
  232.                 exit()
  233.  
  234.  
  235. class LanguageAutoDetector:
  236.         """ Main class """
  237.         __log = None
  238.         __config = None
  239.         __config_path = None
  240.         __cache = None
  241.         __detections = [
  242.                 'filename',
  243.                 'partial_filename',
  244.                 'xml',
  245.                 'shebang',
  246.                 'try_shebang',
  247.                 'contains_string'
  248.                 #'regex'
  249.         ]
  250.         __cache_ignore = {
  251.                 'contains_string' : None,
  252.                 'try_shebang' : 'shebang',
  253.                 'partial_filename' : 'filename',
  254.                 'regex' : None
  255.         }
  256.        
  257.         def __init__(self, config_file=None):
  258.                 config = self.__load_config(config_file)
  259.                 if config['cache']['enabled']:
  260.                         self.__load_cache()
  261.                 #self.__log = logger.FileLogger()
  262.                
  263.  
  264.         def __new__(cls,*args):
  265.                 if not hasattr(cls,'_instance'):
  266.                         cls._instance = dict.__init__(cls, args)
  267.                 else:
  268.                         raise Exception('LanguageAutoDetector already initialized')
  269.                 return cls._instance
  270.        
  271.         @classmethod
  272.         def getInstance(cls):
  273.                 if not hasattr(cls,'_instance'):
  274.                         cls._instance = dict.__new__(cls)
  275.                 return cls._instance
  276.  
  277.         @scache
  278.         def config(self, key=None, default=None):
  279.                 if self.__config is None:
  280.                         config = self.__load_config()
  281.                 else:
  282.                         config = self.__config
  283.                
  284.                 if key is None:
  285.                         return config
  286.                
  287.                 return self.__getdict(config, key, default)
  288.  
  289.         @scache
  290.         def cache(self, key=None, default=None):
  291.                 if self.__cache is None:
  292.                         cache = self.__load_cache()
  293.                 else:
  294.                         cache = self.__cache
  295.                
  296.                 if key is None:
  297.                         return cache
  298.                
  299.                 return self.__getdict(cache, key, default)
  300.        
  301.         def set_lang(self, result, bufferID):
  302.                 ret = False
  303.                 lang = self.__test_language(result)
  304.                 if lang is None:
  305.                         if self.config('errors.invalid_lang'):
  306.                                 notepad.messageBox('Error: Specified language %s invalid.' % result, 'Config Error')
  307.                 else:
  308.                         notepad.setLangType(lang, bufferID)
  309.                         ret = True
  310.                 return ret
  311.        
  312.         def detect(self, args):
  313.                 detections = self.config('detections.order')
  314.                 bufferID = args['bufferID']
  315.                 args['filename'] = path.basename(notepad.getBufferFilename(bufferID))
  316.                 notepad.activateBufferID(bufferID)
  317.                 for detection in detections:
  318.                         func = getattr(self, 'detection_%s' % detection.lower())
  319.                         result = func(args)
  320.                         console.write('Detection %s: %s\n' % (detection.lower(),result))
  321.                         if result is not None:
  322.                                 if self.set_lang(result, bufferID):
  323.                                         break
  324.  
  325.         # filename
  326.         # partial_filename
  327.         # xml
  328.         # shebang
  329.         # try_shebang
  330.         # contains_string
  331.        
  332.         def detection_filename(self, args):
  333.                 filename = args['filename']
  334.                 config = self.config('detections.filename')
  335.                 for lang in config.keys():
  336.                         if filename in config[lang]:
  337.                                 return lang
  338.                 return None
  339.        
  340.         @scache
  341.         def detection_partial_filename(self, args):
  342.                 filename = args['filename']
  343.                 config = self.config('detections.partial_filename')
  344.                 for lang in config.keys():
  345.                         for pattern in config[lang]:
  346.                                 rgx = re.compile("^%s$" % pattern, re.IGNORECASE)
  347.                                 if rgx.match(filename):
  348.                                         # TODO: Cache here filename -> lang
  349.                                         return lang
  350.                 return None
  351.        
  352.         def detection_xml(self, args):
  353.                 # Check for xml stuff.
  354.                 xml_config = self.config('detections.xml')
  355.                 xml_filename = args['filename']
  356.                 self.xml_lang = None
  357.                 def check(contents, lineNumber, totalLines):
  358.                         val = contents.strip().lower()
  359.                         if len(val) == 0:
  360.                                 return 1
  361.                         else:
  362.                                 for pattern in xml_config:
  363.                                         pattern = pattern.lower()
  364.                                         if val.startswith(pattern):
  365.                                                 self.xml_lang = 'xml'
  366.                                                 ext = path.splitext(xml_filename)[1]
  367.                                                 if len(ext) > 0:
  368.                                                         xml_cache = { ext : 'xml' } # TODO: Cache here
  369.                         return totalLines - lineNumber
  370.                 editor.forEachLine(check)
  371.                 return self.xml_lang
  372.        
  373.         def detection_shebang(self, args):
  374.                 shebang = self.__getshebang()
  375.                 if shebang is None:
  376.                         return None
  377.                 config = self.config('detections.shebang')
  378.                 for lang in config.keys():
  379.                         for pattern in config[lang]:
  380.                                 rgx = re.compile(r"^#!((?:/[^\s]+/env(?:\.[a-z]+)? |/[^\s]+/|[A-Z]:[^\s]*\\|[A-Z]:[^\s]*\\env\.[a-z]+ ?)?%s[\d.-_]*(?:\.[0-9a-z-_.])*)\b" % pattern, re.IGNORECASE)
  381.                                 if rgx.search(shebang):
  382.                                         # TODO: Cache here shebang -> lang
  383.                                         return lang
  384.                 return None
  385.                                
  386.         def detection_try_shebang(self, args):
  387.                 shebang = self.__getshebang()
  388.                 if shebang is None:
  389.                         return None
  390.                 rgx = re.compile(r"^#!(?:/[^\s]+/env(?:\.[a-z]+)? |/[^\s]+/|[A-Z]:[^\s]*\\|[A-Z]:[^\s]*\\env\.[a-z]+ ?)?([^\s]+)[\d.-_]*(?:\.[0-9a-z-_.])*\b", re.IGNORECASE)
  391.                 match = rgx.search(shebang)
  392.                 if match:
  393.                         result = match.group(1)
  394.                         lang = self.__test_language(result)
  395.                         if lang is None:
  396.                                 return None
  397.                         return result
  398.                 return None
  399.        
  400.         def detection_contains_string(self, args):
  401.                 text = editor.getText()
  402.                 config = self.config('detections.contains_string')
  403.                 for lang in config.keys():
  404.                         for pattern in config[lang]:
  405.                                 rgx = re.compile("%s" % pattern, re.IGNORECASE | re.MULTILINE)
  406.                                 if rgx.search(text):
  407.                                         # TODO: Cache here shebang -> lang
  408.                                         return lang
  409.                 return None
  410.  
  411.         def detection_regex(self, args):
  412.                 pass
  413.        
  414.         def __getshebang(self):
  415.                 line = editor.getLine(0)
  416.                 if len(line) <= 2:
  417.                         return None
  418.                 if line[0:2] == '#!':
  419.                         return line
  420.                 return None
  421.        
  422.         def __getdict(self, dict, name, default=None):
  423.                 """Multilevel get function.
  424.                 Code:          
  425.                 Config().get('opt.opt_level2.key','default_value')
  426.                 """
  427.                 if not name:
  428.                         return default
  429.                 levels = name.split('.')
  430.                 data = dict
  431.                 for level in levels:
  432.                         try:                   
  433.                                 data = data[level]
  434.                         except:
  435.                                 return default
  436.                 return data
  437.        
  438.         def __load_config(self, cfg=None):
  439.                 """ Load configuration for script. If it doesn't exist, write the default
  440.                         configuration to file. """
  441.                
  442.                 # Figure out config path.
  443.                 if cfg is None:
  444.                         cfg = path.join(notepad.getPluginConfigDir(), 'py_autolang.cfg')
  445.                 self.__config_path = cfg
  446.                 if path.exists(cfg):
  447.                         self.__config = configobj.ConfigObj(cfg)
  448.                 else:
  449.                         self.__config = self.__default_config()
  450.                         self.__save_config()
  451.                 return self.__config
  452.        
  453.         def __default_config(self, cfg=None):
  454.                 """ Default configuration for script. """
  455.                
  456.                 # Figure out config path.
  457.                 if cfg is None and self.__config_path is None:
  458.                         cfg = path.join(notepad.getPluginConfigDir(), 'py_autolang.cfg')
  459.                 elif cfg is None and self.__config_path is not None:
  460.                         cfg = self.__config_path
  461.                
  462.                 config = configobj.ConfigObj()
  463.                 config.filename = cfg
  464.                
  465.                 # Main config
  466.                 config['script'] = {}
  467.                 config['script']['enabled'] = True
  468.                 config['script']['autoload'] = True
  469.                
  470.                 # Errors
  471.                 config['errors'] = {}
  472.                 config['errors']['invalid_lang'] = True # Message box on invalid lexer specified.
  473.                 config['errors']['invalid_lexer'] = True # Message box on invalid lang specified.
  474.                
  475.                 # Script cache
  476.                 config['cache'] = {}
  477.                 config['cache']['enabled'] = True
  478.                 cache_folder = path.abspath(path.join(path.dirname(cfg), 'cache'))
  479.                 valid_folder = False
  480.                 while not valid_folder:
  481.                         if path.exists(cache_folder):
  482.                                 if not path.isdir(cache_folder):
  483.                                         import string, random
  484.                                         cache_folder += '-' + ''.join(random.choice(string.ascii_uppercase + string.digits) for x in range(3))
  485.                                 else:
  486.                                         valid_folder = True
  487.                         else:
  488.                                 from os import mkdir
  489.                                 mkdir(cache_folder)
  490.                 config['cache']['folder'] = cache_folder
  491.                
  492.                 # Logging
  493.                 config['logging'] = {}
  494.                 config['logging']['console'] = False
  495.                 config['logging']['console_auto_open'] = False
  496.                 config['logging']['file'] = False
  497.                
  498.                 # Loading event
  499.                 config['file_load_event'] = {}
  500.                 config['file_load_event']['no_extension'] = True
  501.                 config['file_load_event']['default_lexer'] = True
  502.                 config['file_load_event']['always'] = False
  503.                
  504.                
  505.                 """
  506.                         Detection methods order - This tells what order to use detection methods.
  507.                         So if filename is executed before shebang, and filename matches a detection,
  508.                         the shebang line wont be run. To disable a detection method, set to 0. If
  509.                         any two methods have the same number, an error will be thrown.
  510.                        
  511.                         Possible detections:
  512.                                 shebang
  513.                                 try_shebang
  514.                                 xml
  515.                                 filename
  516.                                 partial_filename
  517.                                 contains_string
  518.                                 regex - Not yet implemented
  519.                 """
  520.                 order = ['filename', 'partial_filename', 'xml', 'shebang', 'try_shebang', 'contains_string']
  521.  
  522.                 # Default Detections
  523.                 ## Shebangs
  524.                 ## These all match the follow regex pattern:
  525.                 ### r"^#!(?:/[^\s]+/env(?:\.[a-z]+) |/[^\s]+/|[A-Z]:[^\s]*\\|[A-Z]:[^\s]*\\env\.[a-z]+ ?)?%s[\d.-_]*(?:\.[0-9a-z-_.])*\b" % key
  526.                 shebang = {
  527.                                                
  528.                         # Shell
  529.                         ## Bash/Korn Shell/C Shell/Z Shell/etc
  530.                         'bash' : ['(?:[czk]|ba)?sh'],
  531.                        
  532.                         # Python
  533.                         ## CPython - http://python.org/
  534.                         ## Cross Twine Linker (xtpython) - http://crosstwine.com/linker/python.html
  535.                         ## Unpython Python to C compiler (unpython) - http://code.google.com/p/unpython/
  536.                         ## IPython (ipython) - http://ipython.org/
  537.                         ## PyPy - http://pypy.org/
  538.                         ## Iron Python - http://ironpython.net/
  539.                         ## Mozilla Embedded Python Console - http://www.thomas-schilz.de/MozPython/
  540.                         ## TinyPy - http://www.tinypy.org/
  541.                         ## Snipy - Personal project, you can remove if you want.
  542.                         ## Enthought SciPy distribution - http://www.enthought.com/
  543.                         ## Jython (jython) - http://www.jython.org/
  544.                         ## Cython (Optimizing Python to C Compiler) - http://cython.org/
  545.                         ## Typhon (typhon) - https://github.com/vic/typhon
  546.                         ## Mython (mython) - http://mython.org/
  547.                        
  548.                         # Languages Close Enough to Python """
  549.                         ## Nimrod  - http://force7.de/nimrod/download.html
  550.                         ## Serpent - http://sourceforge.net/projects/serpent/
  551.                         ## Boo - http://boo.codehaus.org/
  552.                        
  553.                         'python' : [
  554.                                 '(?:xt|un|i)?pythonw?',
  555.                                 '(?:py|i|moz|tiny|sni)pyw?(?:-c)?',
  556.                                 'epdw?',
  557.                                 '[jctm]ythonw?',
  558.                                 '(?:nimrod|ser?pent)',
  559.                                 'boo(?:c|i|ish)?'
  560.                         ],
  561.  
  562.                         # Perl
  563.                         ## Perl - http://www.perl.org/
  564.                         ## Parrot - http://parrot.org/
  565.                         ### Hm, this one might be hard. Leaving parrot as perl for now
  566.                         'perl' : [ 'w?perl', 'parrot' ],
  567.                        
  568.                         # Ruby
  569.                         ## Ruby - http://www.ruby-lang.org/en/
  570.                         ## Iron Ruby (ir, etc) - http://ironruby.net/
  571.                         ## JRuby - http://jruby.org/
  572.                         ## Ruby on Rails - http://rubyonrails.org/
  573.                         'ruby' : [
  574.                                 '[ji]?[ie]r[wbi]{0,2}?(?:_swing)?',
  575.                                 '[ej]?ruby[wc]?',
  576.                                 'rake'
  577.                         ],
  578.  
  579.                         # Javascript
  580.                         ## Node.Js - http://nodejs.org/
  581.                         ## Narwhal - https://github.com/tlrobinson/narwhal
  582.                         ## JSDB - http://www.jsdb.org/
  583.                         ## Ringo Javascript - http://ringojs.org/
  584.                         ## GlueScript - http://gluescript.sourceforge.net/
  585.                         ## Rhino - http://www.mozilla.org/rhino/
  586.                         'javascript' : [
  587.                                 '(?:node|npm)',
  588.                                 '(?:narwhal|tusk)',
  589.                                 '(?:jsdb|ringo|gluew?)',
  590.                                 '(?:rhino|js)'
  591.                         ],
  592.                        
  593.                         # PHP
  594.                         'php' : [
  595.                                 '(?:i?php(?:-cgi|-cli|-win)?|pharc?)'
  596.                         ]
  597.  
  598.                 }
  599.                
  600.                 filename = {
  601.                         'bash' : ['configure'],
  602.                         'makefile' : ['Makefile']
  603.                 }
  604.                
  605.                 partial_filename = {
  606.                         'makefile' : ['Makefile\..+']
  607.                 }
  608.                
  609.                 contains_string = {
  610.                         'bash' : ['^mk_add_options', '^ac_add_options']
  611.                 }
  612.                
  613.                 config['detections'] = {
  614.                         'order' : order,
  615.                         'filename' : filename,
  616.                         'partial_filename' : partial_filename,
  617.                         'xml' : ['<?xml ', '<!DOCTYPE'],
  618.                         'shebang' : shebang,
  619.                         'contains_string' : contains_string
  620.                 }
  621.                
  622.                 return config
  623.        
  624.         def __save_config(self):
  625.                 self.__config.write()
  626.        
  627.         def __load_cache(self):
  628.                 config = self.config()
  629.                 folder = config['cache']['folder']
  630.                
  631.                 cache = {}
  632.                 for detection in config['detections']['order']:
  633.                         if detection in self.__cache_ignore:
  634.                                 if self.__cache_ignore[detection] is not None:
  635.                                         detection = self.__cache_ignore[detection]
  636.                                         if cache.has_key(detection):
  637.                                                 continue
  638.                                 else:
  639.                                         continue
  640.                         f = path.join(folder, detection)
  641.                         if path.exists(f) and path.isfile(f):
  642.                                 input = open(f, 'rb')
  643.                                 cache[detection] = {
  644.                                         'changed' : False,
  645.                                         'value' : pickle.load(input)
  646.                                 }
  647.                                 input.close()
  648.                         else:
  649.                                 cache[detection] = {
  650.                                         'changed' : False,
  651.                                         'value' : None
  652.                                 }
  653.                 self.__cache = cache
  654.                 return self.__cache
  655.        
  656.         def __save_cache(self):
  657.                 config = self.config()
  658.                 folder = config['cache']['folder']
  659.                 saved = []
  660.                 for detection in config['detections']['order']:
  661.                         if detection in self.__cache_ignore:
  662.                                 if self.__cache_ignore[detection] is not None:
  663.                                         detection = self.__cache_ignore[detection]
  664.                                         if detection in saved:
  665.                                                 continue
  666.                                 else:
  667.                                         continue
  668.                         f = path.join(folder, detection)
  669.                         cache = self.cache(detection)
  670.                         if cache['changed'] and cache['value'] is not None:
  671.                                 output = open(f, 'wb')
  672.                                 pickle.dump(cache['value'], output)
  673.                                 output.close()
  674.                                 self.__cache[detection]['changed'] = False
  675.                         saved.append(detection)
  676.        
  677.         def __test_lexer(self, lexer):
  678.                 result = True
  679.                 old_lexer = editor.getLexerLanguage()
  680.                 editor.setLexerLanguage(lexer)
  681.                 if editor.getLexerLanguage() == 'null':
  682.                         result = False
  683.                 editor.setLexerLanguage(old_lexer)
  684.                 return result
  685.  
  686.         def __test_language(self, lang):
  687.                 import Npp
  688.                 lang = lang.upper()
  689.                 result = None
  690.                 try:
  691.                         result = getattr(Npp.LANGTYPE, lang)
  692.                 except AttributeError:
  693.                         result = None
  694.                 return result
  695.  
  696. detector = LanguageAutoDetector()
  697. notepad.clearCallbacks([NOTIFICATION.FILEOPENED])
  698. notepad.callback(detector.detect, [NOTIFICATION.FILEOPENED])
clone this paste RAW Paste Data