Ecco le nuove macro per il wiki di Ubuntu-it

Insieme a Leo abbiamo terminato lo sviluppo di un paio di macro per il wiki italiano di Ubuntu.

La prima di queste è la macro [[Indice]], che va a sostituire [[TableOfContents]], fornita di base con MoinMoin. La sintassi della macro di default è molto semplice e prevede un solo parametro facoltativo, ovvero la profondità delle sezioni elencate nell’indice. Ecco un esempio:

[[TableOfContents(2)]]

Il risultato è simile al seguente (lo screen si rifà alla pagina Sicurezza/AppArmor):

Se si sostituisce tale macro con questa

[[Indice(depth=2)]]

Il risultato sarà molto più accattivante:

Oltre al parametro depth ve ne sono altri due, align e style: il primo è utile per specificare il posizionamento della tabella (unico valore non accettato è center), il secondo consente invece di adattare lo stile dell’indice a quello di un determinato portale.

Altro discorso per la macro [[VersioniSupportate]]: prima del nostro intervento per inserire la tabella delle versioni in una pagina bisognava utilizzare la macro [[Include]] con una sintassi simile alla seguente, facendo attenzione a inserire una riga per ogni versione:

[[Include(StrumentiWiki/Versioni)]]
[[Include(StrumentiWiki/Hardy)]]
[[Include(StrumentiWiki/Gutsy)]]
[[Include(StrumentiWiki/Feisty)]]
[[Include(StrumentiWiki/Versioni2)]]

Il risultato era rappresentato dall’inclusione, nella pagina corrente, di una tabellina contenente le versioni specificate fra la prima e l’ultima riga. Ora, con la macro [[VersioniSupportate]], tutto è più semplice: basta include, fra i parametri della macro, l’elenco dei nomi in codice delle versioni supportate, come nel seguente esempio:

[[VersioniSupportate(hardy gutsy feisty)]]

Ecco una dimostrazione grafica:

Poichè l’accesso ai sorgenti delle macro non è libero, ho pensato di pubblicare qui tutto il codice modificato insieme con Leo.

Ecco il file Indice.py:

# -*- coding: iso-8859-1 -*-
"""
    MoinMoin - TableOfContents Macro

    Optional integer argument: maximal depth of listing.

    @copyright: 2000, 2001, 2002 by Jürgen Hermann <jh@web.de>
    @license: GNU GPL, see COPYING for details.
"""

import re, sha
from MoinMoin import config, wikiutil

#Dependencies = ["page"]
Dependencies = ["time"] # works around MoinMoinBugs/TableOfContentsLacksLinks

# from macro Include (keep in sync!)
_arg_heading = r'(?P<heading>,)\s*(|(?P<hquote>[\'"])(?P<htext>.+?)(?P=hquote))'
_arg_level = r',\s*(?P<level>\d*)'
_arg_from = r'(,\s*from=(?P<fquote>[\'"])(?P<from>.+?)(?P=fquote))?'
_arg_to = r'(,\s*to=(?P<tquote>[\'"])(?P<to>.+?)(?P=tquote))?'
_arg_sort = r'(,\s*sort=(?P<sort>(ascending|descending)))?'
_arg_items = r'(,\s*items=(?P<items>\d+))?'
_arg_skipitems = r'(,\s*skipitems=(?P<skipitems>\d+))?'
_arg_titlesonly = r'(,\s*(?P<titlesonly>titlesonly))?'
_arg_editlink = r'(,\s*(?P<editlink>editlink))?'
_args_re_pattern = r'^(?P<name>[^,]+)(%s(%s)?%s%s%s%s%s%s%s)?$' % (
    _arg_heading, _arg_level, _arg_from, _arg_to, _arg_sort, _arg_items,
    _arg_skipitems, _arg_titlesonly, _arg_editlink)

# from Include, too, but with extra htext group around header text
_title_re = r"^(?P<heading>(?P<hmarker>=+)\s(?P<htext>.*)\s(?P=hmarker))$"

class TableOfContents:
    """
    TOC Macro wraps all global variables without disturbing threads
    """

    def __init__(self, macro, args):
        self.macro = macro
        self._ = self.macro.request.getText
        
        self.inc_re = re.compile(r"^\[\[Include\((.*)\)\]\]")
        self.arg_re = re.compile(_args_re_pattern)
        self.head_re = re.compile(_title_re) # single lines only
        self.pre_re = re.compile(r'\{\{\{.+?\}\}\}', re.S)
        
        self.result = []
        self.baseindent = 0
        self.indent = 0
        self.lineno = 0
        self.titles = {}
	
        self.include_macro = None
        
        self.align_list = ['left', 'right']
        self.style_list = ['Server', 'InternetRete', 'AmministrazioneSistema', 'Multimedia', 'Sicurezza', 'Programmazione', 'Giochi', 'Hardware', 'AmbienteGrafico', 'Emulatori', 'Grafica', 'Radioamatori', 'Ufficio', 'Architettura64Bit', 'Installazione']

        try:
            self.mindepth = int(macro.request.getPragma('section-numbers', 1))
        except (ValueError, TypeError):
            self.mindepth = 1
            
        (self.maxdepth, self.align, self.style) = self.__readParams(args)
        
    def __args_to_dict(self, args):
    	args_dict = dict()
    	if(args!=None):
    		args_list = args.split()
    		for argument in args_list:
    			if '=' in argument:
    				temp = argument.split('=')
    				args_dict[temp[0]] = temp[1]
#    		else: # altrimenti lancia un'eccezione
#				raise Exception('ExceptionArguments: l\'argomento "%s" non e\' valido. Utilizzare [[Indice(depth=INTERO align=left|right)]]'%  argument )
    	return args_dict

    def __readParams(self, args):
    	argsDict = self.__args_to_dict(args)
	maxdepth = 99	# maxdepth default value
	align = 'right' # align default value
	style = '' # style default value
	if argsDict != {}: # se il dizionario non è vuoto
		if argsDict.has_key('depth'): # se è stata impostata una profondità...
			try:
				maxdepth = max(int(argsDict['depth']), 1) # ...settala
			except (ValueError, TypeError, KeyError):
				raise Exception('ExceptionArguments: l\'argomento %s non e\' valido.'%  depth )
		if argsDict.has_key('align'):
			if argsDict['align'] in self.align_list: # se è stato impostato un allineamento valido...
				align = argsDict['align'] # ...settalo
			else:
				raise Exception('ExceptionArguments: l\'argomento %s non e\' valido.'%  argsDict['align'] )
		if argsDict.has_key('style'): # se lo style è personalizzato
			if argsDict['style'] in self.style_list: # controlla che sia valido
				style = '-%s' % argsDict['style'] # se lo è, imposta lo style
			else: # altrimenti lancia un'eccezione
				raise Exception('ExceptionArguments: l\'argomento %s non e\' valido.'%  argsDict['style'] )
	return (maxdepth, align, style) # restituisci il risultato

    def IncludeMacro(self, *args, **kwargs):
        if self.include_macro is None:
            self.include_macro = wikiutil.importPlugin(self.macro.request.cfg,
                                                       'macro', "Include")
        return self.pre_re.sub('',apply(self.include_macro, args, kwargs)).split('\n')

    def run(self):
        _ = self._
	# Just a toc styled 
	style = self.style	
	# Creating header for toc by div structure
	self.result.append('<div class="toc%s" style="float:%s;">' % (style, self.align))
	self.result.append(self.macro.formatter.div(1, css_class=("toc-top-sx%s" % style)))
	self.result.append(self.macro.formatter.div(0))
	self.result.append(self.macro.formatter.div(1, css_class="toc-top-dx%s" % style))
	self.result.append(self.macro.formatter.div(0))
	self.result.append(self.macro.formatter.div(1))
	self.result.append(self.macro.formatter.div(1, css_class="toc-core%s" % style))
	self.result.append('<strong>Indice</strong>')

	# Instead of "Indice", these lines open a <p>, print "Contenuti" and close </p>
	self.result.append(self.macro.formatter.paragraph(1, css_class="toc-core-heading%s" % style))
        #self.result.append(self.macro.formatter.escapedText(_('Contents')))
        self.result.append(self.macro.formatter.paragraph(0))

        self.process_lines(self.pre_re.sub('',self.macro.parser.raw).split('\n'),
                           self.macro.formatter.page.page_name)
        # Close pending lists
        for i in range(self.baseindent, self.indent):
            self.result.append(self.macro.formatter.listitem(0))
            self.result.append(self.macro.formatter.number_list(0))
 

	# Closing toc-core div
        self.result.append(self.macro.formatter.div(0))
        self.result.append(self.macro.formatter.div(0))

	# Creting footer for toc by div structure
	self.result.append(self.macro.formatter.div(1, css_class="toc-bottom-sx%s" % style))
	self.result.append(self.macro.formatter.div(0))
	self.result.append(self.macro.formatter.div(1, css_class="toc-bottom-dx%s" % style))
	self.result.append(self.macro.formatter.div(0))

	# Closing toc div
	self.result.append(self.macro.formatter.div(0))
	
        return ''.join(self.result)

    def process_lines(self, lines, pagename):
        for line in lines:
            # Filter out the headings
            self.lineno = self.lineno + 1
            match = self.inc_re.match(line)
            if match:
                # this is an [[Include()]] line.
                # now parse the included page and do the work on it.

                ## get heading and level from Include() line.
                tmp = self.arg_re.match(match.group(1))
                if tmp and tmp.group("name"):
                    inc_pagename = tmp.group("name")
                else:
                    # no pagename?  ignore it
                    continue
                if tmp.group("heading") and tmp.group("hquote"):
                    if tmp.group("htext"):
                        heading = tmp.group("htext")
                    else:
                        heading = inc_pagename
                    if tmp.group("level"):
                        level = int(tmp.group("level"))
                    else:
                        level = 1
                    inc_page_lines = ["%s %s %s" %("=" * level, heading, "=" * level)]
                else:
                    inc_page_lines = []

                inc_page_lines = inc_page_lines + self.IncludeMacro(self.macro, match.group(1), called_by_toc=1)
                
                self.process_lines(inc_page_lines, inc_pagename)
            else:
                self.parse_line(line, pagename)

    def parse_line(self, line, pagename):
        # FIXME this also finds "headlines" in {{{ code sections }}}:
        match = self.head_re.match(line)
        if not match: return
        title_text = match.group('htext').strip()
        pntt = pagename + title_text
        self.titles.setdefault(pntt, 0)
        self.titles[pntt] += 1

        # Get new indent level
        newindent = len(match.group('hmarker'))
        if newindent > self.maxdepth: return
        if newindent < self.mindepth: return
        if not self.indent:
            self.baseindent = newindent - 1
            self.indent = self.baseindent

        # Close lists
        for i in range(0,self.indent-newindent):
            self.result.append(self.macro.formatter.listitem(0))
            self.result.append(self.macro.formatter.number_list(0))

        # Open Lists
        for i in range(0,newindent-self.indent):
            self.result.append(self.macro.formatter.number_list(1))
            self.result.append(self.macro.formatter.listitem(1))

        # Add the heading
        unique_id = ''
        if self.titles[pntt] > 1:
            unique_id = '-%d' % (self.titles[pntt],)

        # close last listitem if same level
        if self.indent == newindent:
            self.result.append(self.macro.formatter.listitem(0))
            
        if self.indent >= newindent:
            self.result.append(self.macro.formatter.listitem(1))
        self.result.append(self.macro.formatter.anchorlink(1,
            "head-" + sha.new(pntt.encode(config.charset)).hexdigest() + unique_id) +
                           self.macro.formatter.text(title_text) +
                           self.macro.formatter.anchorlink(0))

        # Set new indent level
        self.indent = newindent

def execute(macro, args):
    toc=TableOfContents(macro,args)
    return toc.run()

Infine, il file VersioniSupportate.py, contenente il sorgente della macro [[VersioniSupportate]]:

# -*- coding: iso-8859-1 -*-

from MoinMoin import config, wikiutil

def execute(self, args):

	if args == '':
      		raise Exception('ExceptionArguments: inserire il nome di almeno un rilascio di Ubuntu nella macro VersioniSupportate.')

	pageRelease = { 'dapper': "DapperNoteDiRilascio", 'feisty': "7.04tour", 'gutsy': "GutsyNoteDiRilascio", 'hardy': 'HardyNoteDiRilascio'}

	numRelease = { 'dapper': " 6.06", 'feisty': " 7.04", 'gutsy': ' 7.10', 'hardy': ' 8.04' }

	nameRelease = { 'warty': 'deprecated', 'hoary': 'deprecated', 'breezy': 'deprecated', 'edgy': 'deprecated', 'dapper': "Dapper Drake", 'feisty': "Feisty Fawn", 'gutsy': 'Gutsy Gibbon', 'hardy': 'Hardy Heron' }


	self.result = []
	# Creating header 
	self.result.append(self.formatter.div(1, css_class="supported-releases"))
	self.result.append(self.formatter.div(1, css_class="toc-top-sx"))
	self.result.append(self.formatter.div(0))
	self.result.append(self.formatter.div(1, css_class="toc-top-dx"))
	self.result.append(self.formatter.div(0))
	self.result.append(self.formatter.div(1, css_class="supported-releases-core"))

	# Preparing to cycle
	self.result.append('<p class="supported-releases-heading">Versioni supportate:</p>')
	# Cycling args
	for arg in args.split():
		# If it's a typing mistake
		if arg not in nameRelease: ## HiHiHi 😀 😀 😀 EasterEgg writen with AlessioTreglia help 
			raise Exception('ExceptionRelease: le prestazioni sessuali di MefistoRQ nei confronti di MiloCasagrande non sono state convincenti per avere il rilascio di "%s".'%  arg )
			pass
		# If it's deprecated
		if nameRelease[arg] == 'deprecated':
			pass
		else:	
			self.result.append('Ubuntu %s <a href="/%s">%s</a><br />' % (numRelease[arg], pageRelease[arg], nameRelease[arg]))


	
	# Closing div supported-release-core
        self.result.append(self.formatter.div(0))
	
	# Creating footer  
	self.result.append(self.formatter.div(1, css_class="toc-bottom-sx"))
	self.result.append(self.formatter.div(0))
	self.result.append(self.formatter.div(1, css_class="toc-bottom-dx"))
	self.result.append(self.formatter.div(0))
	
	self.result.append(self.formatter.div(0))

	return ''.join(self.result) 

Facebook Twitter Linkedin Plusone Pinterest Email

3 pensieri su “Ecco le nuove macro per il wiki di Ubuntu-it

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *