Opened 7 years ago

Closed 2 months ago

# [patch] Slight integration with TagsPlugin and alphabetic sort

Reported by: Owned by: Nelso G. Jost Ryan J Ollos normal TracKeywordsPlugin normal TagsPlugin 0.12

### Description

I made ​​a small patch to the plugin also enter keywords in the "Tag Under" field (for the ones who uses TagsPlugin).

To use this in the wiki edit page, make sure to include the follow tag in the file <trac_egg>/trac/wiki/templates/wiki_edit.html:

<xi:include href="keywords.html" />

• You can put this right before </body>.

This patch also includes the alphabetic sort enhancement.

These improvements do not restrain the use of the plugin from those who DO NOT use TagsPlugin, so I ask the maintainer to decide whether to accept or not those changes.

### Changed 7 years ago by Nelso G. Jost

Apply tested only in Trac 0.11 version of the plugin

### comment:1 Changed 7 years ago by Adrian Fritz

Owner: changed from thomasvs to Ryan J Ollos

Hi Ryan, this patch was made against [9285].

### comment:2 follow-up:  13 Changed 7 years ago by Ryan J Ollos

Status: new → assigned

Hi Adrian, thanks for the patch. I'll get it applied today.

### comment:3 Changed 7 years ago by Adrian Fritz

Nice.

Tip: up-date TO-DO file removing "sort keywords alphabetically, since iterating over the section doesn't respect the order from the config"

### comment:4 Changed 7 years ago by Adrian Fritz

BTW: patch was submitted by Nelso (I'm just guiding him)

### Changed 7 years ago by Nelso G. Jost

Patch against [9285]

### comment:5 Changed 7 years ago by Nelso G. Jost

The new patch available comes with a new approach for config keywords: from a external text file, which must be set in TracIni [keywords] section under file parameter. The way to config keywords in that file remains the same: name = description.

Keywords now are treated in a case-sensitive way (use of CamelCase can really help to makes tags more concises). This was not possible before, since TracIni keys names aren't meant to be case-sensitive.

This changes also incorporate independently the features of the previous one.

### comment:6 in reply to:  description Changed 5 years ago by Steffen Hoffmann

To use this in the wiki edit page, make sure to include the follow tag in the file <trac_egg>/trac/wiki/templates/wiki_edit.html:

<xi:include href="keywords.html" />


You could do this without requiring tedious hand-patching by implementing the ITemplateStreamFilter interface.

### comment:7 Changed 5 years ago by Ryan J Ollos

I'm supposedly maintaining this, but I'm not using it, so I've set the needsadoption tag. Let's fix this up and leave it in a nice state before I go ;)

### comment:8 Changed 5 years ago by Ryan J Ollos

Content moved from main page:

1. Update the ticket template page to include this plugin page section ("Add keywords").
• You can do this by including the following line somewhere in the keywords.html file:
<xi:include href="keywords.html" />

• Suggested place: right before </body> tag.
• Where to locate files @ Trac 0.12:
• <trac_egg>/trac/ticket/templates/ticket.html
• <trac_egg>/trac/wiki/templates/wiki_edit.html (For a slight integration with TagsPlugin, see #8799)
• Trac 0.10 ticket.cs file:
...
</fieldset><?cs /if ?>;

<?cs include "keywords.cs" ?>

<?cs if:ticket.actions.accept || ticket.actions.reopen ||
ticket.actions.resolve || ticket.actions.reassign ?>
...


### comment:9 Changed 5 years ago by Steffen Hoffmann

Suggested ITemplateStreamFilter usage (untested code, but general concept is well-known):

from genshi.core import Markup
from trac.web.api import ITemplateStreamFilter

...

implements(ITemplateStreamFilter)

def filter_stream(self, req, method, filename, stream, data):
if filename == 'ticket.html':
ticket = data.get('ticket')
if self.keywords and ticket and ticket.exists and \
'TICKET_CHGPROP' in req.perm(ticket.resource):
insert = Markup('<xi:include href="keywords.html" />')
filter = Transformer('div[@id="content"]')
stream |= filter.after(insert)
elif filename == 'wiki_view.html':

...

return stream



### comment:10 Changed 5 years ago by Ryan J Ollos

I'm having trouble with:

insert = Markup('<xi:include href="keywords.html" />')


It is just displayed as plain text. If I change to:

insert = HTML('<xi:include href="keywords.html" />')


then viewing the source and clicking on keywords.html results in a NOT FOUND.

If we can figure out how to inject an include into a markup stream and have it to render, I think that would be a very valuable thing to have in the toolset.

### comment:11 Changed 5 years ago by Ryan J Ollos

Here's how it looks on Trac 1.0dev:

### comment:12 Changed 5 years ago by Ryan J Ollos

(In [11771]) Refs #8799: Eliminated need for manual installation step and editing of Trac source code by rendering template and adding it to the stream in ITemplateStreamFilter.filter_stream.

### comment:13 in reply to:  2 Changed 5 years ago by Ryan J Ollos

Hi Adrian, thanks for the patch. I'll get it applied today.

Wow, I'm late on this one!

### comment:14 Changed 5 years ago by Ryan J Ollos

Here's how the wiki page looks on Trac 1.0dev:

### comment:15 Changed 5 years ago by Ryan J Ollos

(In [11772]) Refs #8799:

• Keywords are now shown on the wiki_edit page.
• Keywords are sorted before display.

### comment:16 follow-up:  18 Changed 5 years ago by Ryan J Ollos

At present, the keywords are always shown on the wiki_edit page, even if the TagsPlugin is not installed. They are also shown in what is probably not an optimal location; better would be under the Tags input element.

The trouble is, the Tags input element is also added to the Genshi stream, and there is no guarantee it will have been added when filter_stream is called for the TracKeywordsPlugin. Is there another way we can determine whether the TagsPlugin is installed?

### comment:17 follow-up:  33 Changed 5 years ago by Ryan J Ollos

This plugin is very similar to the LoomingCloudsPlugin. The two could probably be merged together.

### comment:18 in reply to:  16 ; follow-up:  19 Changed 5 years ago by Steffen Hoffmann

At present, the keywords are always shown on the wiki_edit page, even if the TagsPlugin is not installed.

Do you think this is a problem? Keywords in tickets are a standard property, just that TagsPlugin extends and generalizes the concept of tagged resources to more/all Trac realms.

They are also shown in what is probably not an optimal location; better would be under the Tags input element.

The trouble is, the Tags input element is also added to the Genshi stream, and there is no guarantee it will have been added when filter_stream is called for the TracKeywordsPlugin. Is there another way we can determine whether the TagsPlugin is installed?

Really? No, I don't think so. If not due to effects of BlackMagicTicketTweaksPlugin, DynamicFieldsPlugin or SimpleTicketPlugin there should always be a keywords field. But a better position - near (below?) the keywords input field is a reasonable request. As you probably understand by now, this is just a matter of creating a simple but precisely matching XPATH expression for the appropriate position in the template.

### comment:19 in reply to:  18 ; follow-up:  20 Changed 5 years ago by Ryan J Ollos

Do you think this is a problem? Keywords in tickets are a standard property, just that TagsPlugin extends and generalizes the concept of tagged resources to more/all Trac realms.

Well, the undesirable thing as I see it is that, in the case that TagsPlugin is not installed, a keywords fieldset will still be added to the wiki_edit page, but it serve no purpose since there isn't a tags input element to populate.

Really? No, I don't think so. If not due to effects of BlackMagicTicketTweaksPlugin, DynamicFieldsPlugin or SimpleTicketPlugin there should always be a keywords field. But a better position - near (below?) the keywords input field is a reasonable request.

I'm referring to the wiki_edit page again here. I was making the assumption that the reason I couldn't filter for the tags input element was because it hadn't been added to the stream yet, but I suppose I could have been making some other error.

### comment:20 in reply to:  19 ; follow-up:  21 Changed 5 years ago by Steffen Hoffmann

Well, the undesirable thing as I see it is that, in the case that TagsPlugin is not installed, a keywords fieldset will still be added to the wiki_edit page, but it serve no purpose since there isn't a tags input element to populate.

Ah, I see now. Right, we'll need to check, if TagsPlugin's wiki module is enabled. This might be next to trivial. Should I look at this and propose a patch?

I'm referring to the wiki_edit page again here. I was making the assumption that the reason I couldn't filter for the tags input element was because it hadn't been added to the stream yet, but I suppose I could have been making some other error.

True again. Indeed I remember clearly, that TagsPlugin is inserting the keywords field dynamically to the wiki edit page. Should be resolved as mentioned above.

### comment:21 in reply to:  20 Changed 5 years ago by anonymous

Right, we'll need to check, if TagsPlugin's wiki module is enabled. This might be next to trivial. Should I look at this and propose a patch?

A patch would be great. Off-hand, I'm not sure how to approach this.

### comment:22 Changed 5 years ago by Ryan J Ollos

(In [11788]) Refs #9872, #8799: Fixed defect introduced in [11771]: keywords would not be parsed from the keywords section in trac.ini. Thanks to asix for testing and reporting this.

### comment:23 follow-up:  24 Changed 5 years ago by Steffen Hoffmann

So I try:

    def __init__(self):
# Compatibility code for ComponentManager.is_enabled
# (available since Trac 0.12)
def _is_enabled(env, cls):
"""Return whether the given component class is enabled.

For Trac 0.11 the missing algorithm is included as fallback.
"""
try:
return env.is_enabled(cls)
except AttributeError:
if cls not in env.enabled:
env.enabled[cls] = env.is_component_enabled(cls)
return env.enabled[cls]
# Test availability of TagsPlugin and specifically it's wiki page
# tagging support.
try:
from tractags.wiki import WikiTagInterface
wikikw_enabled = _is_enabled(self.env, WikiTagInterface)
except ImportError:
wikikw_enabled = False

...

def filter_stream(self, req, method, filename, stream, data):
if filename == 'ticket.html':

...

elif self.wikikw_enabled and filename == 'wiki_edit.html':

...



The is_enabled method I've borrowed from AccountManagerPlugin, so this is largely known to work.

### comment:24 in reply to:  23 Changed 5 years ago by Ryan J Ollos

The is_enabled method I've borrowed from AccountManagerPlugin, so this is largely known to work.

Looks good, thanks! I have your code integrated working locally, and I'll do a bit more testing and check it in tomorrow.

### comment:25 follow-up:  28 Changed 5 years ago by Ryan J Ollos

The code sample works great with a minor change:

if cls not in env.enabled


=>

if cls not in self.env.enabled


It looks like that is an error in the AccountManager code.

### comment:26 Changed 5 years ago by Ryan J Ollos

(In [11804]) Refs #8799: Only add the keywords to the wiki_edit page if the TagsPlugin is enabled.

Tested with Trac 0.11 and Trac 1.0dev-r11158. Thanks to hasienda for contributing this code.

### comment:27 Changed 5 years ago by Ryan J Ollos

I think the goals of this ticket have been accomplished. Code review and testing feedback is appreciated. Thanks!

### comment:28 in reply to:  25 ; follow-up:  29 Changed 5 years ago by Steffen Hoffmann

The code sample works great with a minor change:

![...]

It looks like that is an error in the AccountManager code.

Well, the original code forms a function, while you changed that into a class method. This is fine, because this way you eliminate the env argument. But at least you can't compare the conditions any longer, both are valid in their code context: Inside the function env refers to the 1st argument, while self.env for your class method is an attribute inherited from trac.core.Component class.

My initial design might be broken because I attempted to create a (class independed) function inside of a class method. Maybe it would've worked, if I had written def _is_enabled(self, env, cls): and consequently wikikw_enabled = self._is_enabled( later on. Nevermind, your code looks good and simple, so keep it.

### comment:29 in reply to:  28 Changed 5 years ago by Ryan J Ollos

Well, the original code forms a function, while you changed that into a class method...

Ah, right. It was late and I had forgotten that I had converted it to a class method the night before. I'll look more closely next time before suggesting your code is broken ;)

My initial design might be broken because I attempted to create a (class independed) function inside of a class method. Maybe it would've worked, if I had written def _is_enabled(self, env, cls): and consequently wikikw_enabled = self._is_enabled( later on. Nevermind, your code looks good and simple, so keep it.

I've read a lot of arguments, especially in the writings by the C++ gurus, that say member functions should be kept to a minimum, and make it a non-member if it doesn't have to modify class properties. With Trac, I tend to make the function a method whenever it needs env, but I can see the value in having this be a function in your util module, for the case of a larger project like your AccountMananger.

### comment:30 follow-up:  31 Changed 5 years ago by Adrian Fritz

Tested TracKeywordsPlugin with:

• simple keywords
• composed keywords (CamelCase, '/' )
• non-ascii characters (ç, ü, á, è, é, ...)

Environment:

Results:

• In general working good
• Keywords shown alphabetically ordered;
• Inserts / removes keywords correctly;
• Tips shown accordingly;
• Side effect / non expected: has lowered case for all keywords:
• Some may consider this expected or desirable (I´ve already saw some pro arguments);
• I expect NO keyword be modified.

### comment:31 in reply to:  30 Changed 5 years ago by Ryan J Ollos

• Side effect / non expected: has lowered case for all keywords:
• Some may consider this expected or desirable (I´ve already saw some pro arguments);
• I expect NO keyword be modified.

Thanks for testing and reporting. I'll have time to look into this later in the week.

### comment:32 Changed 4 years ago by Ryan J Ollos

Status: assigned → new

### comment:33 in reply to:  17 Changed 4 years ago by Steffen Hoffmann

This plugin is very similar to the LoomingCloudsPlugin. The two could probably be merged together.

This was the last tip I needed. Now I recognize, that apart from TagsPlugin we have even three more hacks that work in the area of tagging Trac resources. Are there even more? Anyway, looks like candidates for bundling and merging functionality.

Last edited 4 years ago by Steffen Hoffmann (previous) (diff)

### comment:34 Changed 2 months ago by Ryan J Ollos

Resolution: → fixed new → closed

### Modify Ticket

Change Properties