Attachment 'xmlhelper.py'
Download 1 # -*- coding: utf8 -*-
2 # XML Helper for GEdit
3 #
4 # Copyright (c) 2007 Matej Cepl <matej@ceplovi.cz>
5 #
6 # Permission is hereby granted, free of charge, to any person obtaining
7 # a copy of this software and associated documentation files (the
8 # "Software"), to deal in the Software without restriction, including
9 # without limitation the rights to use, copy, modify, merge, publish,
10 # distribute, sublicense, and/or sell copies of the Software, and to
11 # permit persons to whom the Software is furnished to do so, subject to
12 # the following conditions:
13 #
14 # The above copyright notice and this permission notice shall be
15 # included in all copies or substantial portions of the Software.
16 #
17 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
21 # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22 # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23 # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
25 import gedit
26 import gtk
27 import re,sys
28 import enum
29
30 end_tag_str = """
31 <ui>
32 <menubar name="MenuBar">
33 <menu name="EditMenu" action="Edit">
34 <placeholder name="EditOps_6">
35 <menuitem name="LastTag" action="LastTag"/>
36 <menuitem name="EndTag" action="EndTag"/>
37 </placeholder>
38 </menu>
39 </menubar>
40 </ui>
41 """
42
43 debug = False
44
45 def prDebug(string):
46 if debug:
47 print >>sys.stderr,string
48
49 class XMLHelper(gedit.Plugin):
50 def __init__(self):
51 gedit.Plugin.__init__(self)
52 self.elementEndness=enum.Enum("end","start","single")
53
54 def __get_tag(self,iter):
55 if not(iter.forward_char()):
56 raise RuntimeError, "we are in trouble"
57 searchRet=iter.forward_search(">",gtk.TEXT_SEARCH_TEXT_ONLY)
58 if searchRet:
59 begEnd,endEnd=searchRet
60 retStr = iter.get_text(begEnd)
61 if (retStr[-1]=="/") or (retStr[:3]=="!--"):
62 hasEndTag = self.elementEndness.single
63 retStr = retStr.rstrip("/")
64 elif retStr[0] == "/":
65 hasEndTag = self.elementEndness.end
66 retStr = retStr.lstrip("/")
67 else:
68 hasEndTag = self.elementEndness.start
69 # cut element's parameters
70 retStr = retStr.split(" ")[0]
71 prDebug("tag found is %s and the value of hasEndTag is %s" % (retStr,hasEndTag))
72 return retStr,hasEndTag
73 else:
74 raise IOError, "Never ending tag at line %d" % (iter.get_line()+1)
75
76 def findLastEndableTag(self,position):
77 tagStack = []
78 res = position.backward_search("<", gtk.TEXT_SEARCH_TEXT_ONLY)
79 while res:
80 start_match,end_match=res
81 tag,isEndTag=self.__get_tag(start_match)
82 if isEndTag==self.elementEndness.end:
83 tagStack.append(tag)
84 prDebug("Push tag '%s'" % tag)
85 elif isEndTag==self.elementEndness.single:
86 prDebug("Ignoring single tag '%s'" % tag)
87 elif len(tagStack) != 0: # stack not empty
88 poppedTag=tagStack.pop()
89 prDebug("Popped tag '%s'" % poppedTag)
90 if poppedTag != tag:
91 raise IOError,"mismatching tags.\nFound %s and expecting %s." % \
92 (tag,poppedTag)
93 else: # stack is empty and this is not end tag == we found it
94 prDebug("We found tag '%s'" % tag)
95 return tag
96 start_match.backward_char()
97 res = start_match.backward_search("<",gtk.TEXT_SEARCH_TEXT_ONLY)
98
99 # not totally sure what following means, but doesn't look right to me
100 if len(tagStack) != 0:
101 raise IOError, "whatever"
102 if not(res): # There is no open tag in the current buffer
103 return None
104
105 def end_tag(self, action, window):
106 buffer = window.get_active_view().get_buffer()
107 inp_mark=buffer.get_iter_at_mark(buffer.get_insert())
108 tagname=self.findLastEndableTag(inp_mark)
109 if tagname:
110 buffer.insert(inp_mark,'</%s>' % tagname)
111
112 def previous_tag(self,action,window):
113 buffer = window.get_active_view().get_buffer()
114 inp_mark = buffer.get_iter_at_mark(buffer.get_insert())
115 res = inp_mark.backward_search("<", gtk.TEXT_SEARCH_TEXT_ONLY)
116 if res:
117 start_match,end_match = res
118 tag,isEndTag = self.__get_tag(start_match)
119 if isEndTag == self.elementEndness.end:
120 buffer.insert(inp_mark,'<%s>' % tag)
121
122 def activate(self, window):
123 actions = [
124 ('EndTag', None, 'End Tag', None, "End Tag", self.end_tag),
125 ('LastTag', None, 'Last Tag', None, "Last Tag", self.previous_tag),
126 ]
127
128 # store per window data in the window object
129 windowdata = dict()
130 window.set_data("XMLHelperWindowDataKey", windowdata)
131 windowdata["action_group"] = gtk.ActionGroup("GeditXMLHelperActions")
132 windowdata["action_group"].add_actions(actions, window)
133 manager = window.get_ui_manager()
134 manager.insert_action_group(windowdata["action_group"], -1)
135 windowdata["ui_id"] = manager.add_ui_from_string(end_tag_str)
136
137 window.set_data("XMLHelperInfo", windowdata)
138
139 def deactivate(self, window):
140 windowdata = window.get_data("XMLHelperWindowDataKey")
141 manager = window.get_ui_manager()
142 manager.remove_ui(windowdata["ui_id"])
143 manager.remove_action_group(windowdata["action_group"])
144
145 def update_ui(self, window):
146 view = window.get_active_view()
147 windowdata = window.get_data("XMLHelperWindowDataKey")
148 windowdata["action_group"].set_sensitive(bool(view and view.get_editable()))
Attached Files
To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.You are not allowed to attach a file to this page.