home *** CD-ROM | disk | FTP | other *** search
/ PC Welt 2006 November (DVD) / PCWELT_11_2006.ISO / casper / filesystem.squashfs / usr / lib / gedit-2 / plugins / modelines.py < prev    next >
Encoding:
Python Source  |  2006-08-27  |  8.6 KB  |  295 lines

  1. # -*- coding: utf-8 -*-
  2. # modelines.py - Emacs, Kate and Vim-style modelines support for gedit.
  3. #
  4. # Copyright (C) 2005 - Steve Fr├⌐cinaux
  5. #
  6. # This program is free software; you can redistribute it and/or modify
  7. # it under the terms of the GNU General Public License as published by
  8. # the Free Software Foundation; either version 2, or (at your option)
  9. # any later version.
  10. # This program is distributed in the hope that it will be useful,
  11. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. # GNU General Public License for more details.
  14. #
  15. # You should have received a copy of the GNU General Public License
  16. # along with this program; if not, write to the Free Software
  17. # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  18.  
  19. import gedit
  20. import re
  21. import gtk
  22. import gconf
  23.  
  24. class ModelinePlugin(gedit.Plugin):
  25.     def __init__(self):
  26.         gedit.Plugin.__init__(self)
  27.  
  28.     def connect_handlers(self, view):
  29.         doc = view.get_buffer()
  30.         loaded_id = doc.connect("loaded", apply_modeline, view)
  31.         saved_id  = doc.connect("saved", apply_modeline, view)
  32.         doc.set_data("ModelinePluginHandlerIds", (loaded_id, saved_id))
  33.     
  34.     def disconnect_handlers(self, view):
  35.         doc = view.get_buffer()
  36.         loaded_id, saved_id = doc.get_data("ModelinePluginHandlerIds")
  37.         doc.disconnect(loaded_id)
  38.         doc.disconnect(saved_id)
  39.         doc.set_data("ModelinePluginHandlerIds", None)
  40.     
  41.     def activate(self, window):
  42.         for view in window.get_views(): 
  43.             self.connect_handlers(view)
  44.             apply_modeline(view.get_buffer(), None, view)
  45.             
  46.         tab_added_id = window.connect("tab_added",
  47.                                       lambda w, t: self.connect_handlers(t.get_view()))
  48.         window.set_data("ModelinePluginHandlerId", tab_added_id)
  49.     
  50.     def deactivate(self, window):
  51.         tab_added_id = window.get_data("ModelinePluginHandlerId")
  52.         window.disconnect(tab_added_id)
  53.         window.set_data("ModelinePluginHandlerId", None)
  54.         
  55.         for view in window.get_views():
  56.             self.disconnect_handlers(view)
  57.  
  58. def apply_modeline(doc, error, view):
  59.     if error is None:
  60.         options = get_modeline_options(doc)
  61.         apply_options(options, view)
  62.  
  63. def get_modeline_options(doc):
  64.     options = dict()
  65.  
  66.     # Search the two first lines for emacs- or vim-style modelines
  67.     start = doc.get_start_iter()
  68.     for i in (1, 2):
  69.         end = start.copy()
  70.         if not end.forward_to_line_end():
  71.             return options
  72.         modeline = doc.get_text(start, end, False)
  73.         options.update(parse_modeline_kate(modeline))
  74.         options.update(parse_modeline_vim(modeline))
  75.         options.update(parse_modeline_emacs(modeline))
  76.         start = end
  77.  
  78.     # Vim can read modeline on the 3rd line
  79.     end = start.copy()
  80.     if not end.forward_to_line_end():
  81.         return options
  82.     modeline = doc.get_text(start, end, False)
  83.     options.update(parse_modeline_kate(modeline))
  84.     options.update(parse_modeline_vim(modeline))
  85.     start = end
  86.  
  87.     # Kate reads modelines on the 10 first lines
  88.     for i in (4, 5, 6, 7, 8, 9, 10):
  89.         end = start.copy()
  90.         if not end.forward_to_line_end():
  91.             break
  92.         modeline = doc.get_text(start, end, False)
  93.         options.update(parse_modeline_kate(modeline))
  94.         start = end
  95.  
  96.     # Search the three last lines for vim- and kate-style modelines
  97.     start = doc.get_end_iter()
  98.     start.backward_lines(2)    
  99.     for i in (1, 2, 3):
  100.         end = start.copy()
  101.         if not end.forward_to_line_end():
  102.             return options
  103.         modeline = doc.get_text(start, end, False)
  104.         options.update(parse_modeline_kate(modeline))
  105.         options.update(parse_modeline_vim(modeline))
  106.         start = end
  107.  
  108.     # Kate reads modelines on the 10 last lines
  109.     start.backward_lines(9)    
  110.     for i in (4, 5, 6, 7, 8, 9, 10):
  111.         end = start.copy()
  112.         if not end.forward_to_line_end():
  113.             return options
  114.         modeline = doc.get_text(start, end, False)
  115.         options.update(parse_modeline_kate(modeline))
  116.         start = end
  117.     
  118.     return options
  119.  
  120. def parse_modeline_vim(line):
  121.     # First form modeline
  122.     # [text]{white}{vi:|vim:|ex:}[white]{options}
  123.     #
  124.     # Second form
  125.     # [text]{white}{vi:|vim:|ex:}[white]se[t] {options}:[text]
  126.  
  127.     # Find the modeline
  128.     for i in ('ex:', 'vi:', 'vim:'):
  129.         start = line.find(i)
  130.         if start != -1:    
  131.             start = start + len(i)
  132.             break
  133.     else:
  134.         return {}
  135.     
  136.     if line[start : start + 2] == "se":
  137.         end = line.find(":", start + 3)
  138.         if end == -1:
  139.             return {}
  140.         elif line[start + 2] == 't':
  141.             line = line[start + 4 : end]
  142.         else:
  143.             line = line[start + 3 : end]
  144.     else:
  145.         line = line[start :]
  146.     
  147.     # Get every individual directives
  148.     directives = [x for x in re.split(r'[: ]', line) if x != '']
  149.     options = dict();
  150.     
  151.     for directive in directives:
  152.         # Reformat the directive
  153.         if (directive.find("=") != -1):
  154.             name, value = directive.split("=")
  155.         elif directive[0:2] == "no":
  156.             value = False
  157.             name = directive[2:]
  158.         else:
  159.             value = True
  160.             name = directive
  161.         
  162.         # Set the options according to the directive
  163.         if name == "et" or name == "expandtab":
  164.             options["use-tabs"] = not value
  165.         elif name == "ts" or name == "tabstop":
  166.             options["tabs-width"] = int(value)
  167.         elif name == "wrap":
  168.             options["wrapping"] = value
  169.         elif name == "textwidth":
  170.             options["margin"] = int(value)
  171.     return options
  172.  
  173. def parse_modeline_emacs(line):
  174.     # cf. http://www.delorie.com/gnu/docs/emacs/emacs_486.html
  175.     # Extract the modeline from the given line
  176.     start = line.find("-*-")
  177.     if start == -1:
  178.         return {}
  179.     else:
  180.         start = start + 3
  181.     end = line.find("-*-", start)
  182.     if end == -1:
  183.         return {}
  184.     
  185.     # Get every individual directives
  186.     directives = [x for x in [i.strip() for i in line[start : end].split(";")] if x != '']
  187.     options = dict()
  188.     
  189.     for directive in directives:
  190.         name, value = ([i.strip() for i in directive.split(":", 1)] + [None])[0:2]
  191.         if name == "tab-width":
  192.             options["tabs-width"] = int(value)
  193.         elif name == "indent-tabs-mode":
  194.             options["use-tabs"] = value != "nil"
  195.         elif name == "autowrap":
  196.             options["wrapping"] = value != "nil"
  197.     return options
  198.  
  199. def parse_modeline_kate(line):
  200.     # cf. http://wiki.kate-editor.org/index.php/Modelines
  201.  
  202.     # Extract the modeline from the given line
  203.     start = line.find("kate:")
  204.     if start == -1:
  205.         return {}
  206.     else:
  207.         start = start + 5
  208.     end = line.rfind(";")
  209.     if end == -1:
  210.         return {}
  211.     
  212.     # Get every individual directives
  213.     directives = [x for x in [i.strip() for i in line[start : end].split(";")] if x != '']
  214.     options = dict()
  215.     
  216.     for directive in directives:
  217.         name, value = ([i.strip() for i in directive.split(None, 1)] + [None])[0:2]
  218.         if name == "tab-width" or name == "indent-width":
  219.             options["tabs-width"] = int(value)
  220.         elif name == "space-indent":
  221.             options["use-tabs"] = value not in ("on", "true", "1")
  222.         elif name == "word-wrap":
  223.             options["wrapping"] = value in ("on", "true", "1")
  224.         elif name == "word-wrap-column":
  225.             options["margin"] = int(value)
  226.     return options
  227.  
  228. def apply_options(options, view):
  229.     old_options = view.get_data("ModelineOptions")
  230.  
  231.     if not old_options:
  232.         old_options = {}
  233.     if not options:
  234.         options = {}
  235.  
  236.     if options.has_key("tabs-width"):
  237.         view.set_tabs_width(options["tabs-width"])
  238.     elif old_options.has_key("tabs-width"):
  239.         view.set_tabs_width(gconf_get_int("/apps/gedit-2/preferences/editor/tabs/tabs_size", 8))
  240.     
  241.     if options.has_key("use-tabs"):
  242.         view.set_insert_spaces_instead_of_tabs(not options["use-tabs"])
  243.     elif old_options.has_key("use-tabs"):
  244.         view.set_insert_spaces_instead_of_tabs(gconf_get_bool("/apps/gedit-2/preferences/editor/tabs/insert_spaces", False))
  245.  
  246.     if options.has_key("wrapping"):
  247.         if options["wrapping"]:
  248.             view.set_wrap_mode(gtk.WRAP_WORD)
  249.         else:
  250.             view.set_wrap_mode(gtk.WRAP_NONE)
  251.     elif old_options.has_key("wrapping"):
  252.         wrap_mode = gconf_get_str("/apps/gedit-2/preferences/editor/wrap_mode/wrap_mode", "GTK_WRAP_WORD")
  253.         if wrap_mode == "GTK_WRAP_WORD":
  254.             view.set_wrap_mode(gtk.WRAP_WORD)
  255.         else:
  256.             view.set_wrap_mode(gtk.WRAP_NONE)        
  257.  
  258.     if options.has_key("margin"):
  259.         if options["margin"] > 0:
  260.             view.set_margin(long(options["margin"]))
  261.             view.set_show_margin(True)
  262.         else:
  263.             view.set_show_margin(False)
  264.     elif old_options.has_key("margin"):
  265.         view.set_margin(long(gconf_get_int("/apps/gedit-2/preferences/editor/right_margin/right_margin_position", 80)))
  266.         view.set_show_margin(gconf_get_bool("/apps/gedit-2/preferences/editor/right_margin/display_right_margin", False))
  267.  
  268.     view.set_data("ModelineOptions", options)
  269.  
  270. gconf_client = gconf.client_get_default()
  271. def gconf_get_bool(key, default = False):
  272.     val = gconf_client.get(key)
  273.     if val is not None and val.type == gconf.VALUE_BOOL:
  274.         return val.get_bool()
  275.     else:
  276.         return default
  277.  
  278. def gconf_get_str(key, default = ""):
  279.     val = gconf_client.get(key)
  280.     if val is not None and val.type == gconf.VALUE_STRING:
  281.         return val.get_string()
  282.     else:
  283.         return default
  284.  
  285. def gconf_get_int(key, default = 0):
  286.     val = gconf_client.get(key)
  287.     if val is not None and val.type == gconf.VALUE_INT:
  288.         return val.get_int()
  289.     else:
  290.         return default
  291.  
  292. # ex:ts=8:noet:
  293. # kate: word-wrap-column 120;
  294.