Advertisement
cgrunwald

Auto Detect Language.py

Oct 3rd, 2011
318
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 19.42 KB | None | 0 0
  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])
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement