Case Insensitive Moin

Feb 14, 2006

I wanted case-insensitive filenames in MoinMoin, so I wrote this hack to do so. It causes a marginal increase in CPU usage as it lists directories when it doesn't find a page, but I think it is worth it.

To do this requires changes to MoinMoin's "Page.py" class.

WARNING - make backups first! While this worked for me, it might damage your wiki! These changes are tested on MoinMoin Version 1.5.2, and no other version.

Steps for MoinMoin 1.5.2

Diff file

For those who like diffs, here is a diff file for these changes to Page.py. The changes are described below.

Edits

  1. Open Page.py in your favorite text editor. Find the following section of code:

Toggle line numbers
   1     def reset(self):
           2         """ Reset page state """
           3         page_name = self.page_name
           4         # page_name quoted for file system usage, needs to be reset to
           5         # None when pagename changes
           6 
           7         qpagename = wikiutil.quoteWikinameFS(page_name)
           8         self.page_name_fs = qpagename
           9 
          10         # the normal and the underlay path used for this page
        

1. Add lines 8-13 as shown below after "qpagename = wikiutil...".

Toggle line numbers
   1     def reset(self):
           2         """ Reset page state """
           3         page_name = self.page_name
           4         # page_name quoted for file system usage, needs to be reset to
           5         # None when pagename changes
           6 
           7         qpagename = wikiutil.quoteWikinameFS(page_name)
           8         insensitive = self.get_fs_name_ignoring_case(qpagename)
           9         if insensitive != qpagename:
          10             qpagename = insensitive
          11             # set page name with proper cases and spaces
          12             self.page_name = wikiutil.unquoteWikiname(qpagename)
          13 
          14         self.page_name_fs = qpagename
          15 
          16         # the normal and the underlay path used for this page
        

2. Next, scroll to the end of the "reset" method, and add the following method:

Toggle line numbers
   1     def get_fs_name_ignoring_case(self, page_name):
           2         """
           3         get the case sensitive path to "pagedir",
           4         ignoring pagedir's case.
           5         @param page_name: the page name to parse
           6         @return: str page_name with proper case
           7         """
           8         datadirs = [ self.cfg.data_dir, self.cfg.data_underlay_dir ]
           9 
          10         # quit early if the page exists as given
          11         for datadir in datadirs:
          12             if not datadir == None:
          13                 if os.path.exists(os.path.join(datadir, "pages", page_name)):
          14                     return page_name
          15 
          16         for datadir in datadirs:
          17             if not datadir == None:
          18                 for page in os.listdir( os.path.join( datadir, "pages" ) ):
          19                     if page.lower() == page_name.lower():
          20                         return page
          21         return page_name
        

3. You're done! Case-insensitive pagenames for the masses.

For Wiki Farms

If your wiki lives in a wikifarm like mine does, where other wikis don't necessarily want case-insensitivity, you can make the wiki case insensitive only if a configuration directive is there, as shown here. Add a "try... except" block to the method in step 2 above, as shown here:

Toggle line numbers
   1     def get_fs_name_ignoring_case(self, page_name):
           2         """
           3         get the case sensitive path to "pagedir",
           4         ignoring pagedir's case.
           5         @param page_name: the page name to parse
           6         @return: str page_name with proper case
           7         """
           8         try:
           9             if not self.cfg.case_insensitive_pagenames:
          10                 return page_name
          11         except AttributeError:
          12             return page_name
          13 
          14         datadirs = [ self.cfg.data_dir, self.cfg.data_underlay_dir ]
          15 
          16         # quit early if the page exists as given
          17         for datadir in datadirs:
          18             if not datadir == None:
          19                 if os.path.exists(os.path.join(datadir, "pages", page_name)):
          20                     return page_name
          21 
          22         for datadir in datadirs:
          23             if not datadir == None:
          24                 for page in os.listdir( os.path.join( datadir, "pages" ) ):
          25                     if page.lower() == page_name.lower():
          26                         return page
          27         return page_name
        

Now, to enable case insensitivity, add the following option to your wiki's configuration script:

Toggle line numbers
   1         case_insensitive_pagenames = 1
        

Other MoinMoin Extensions