Permalink
Browse files

Andreas Krennmair:

	updated documentation
	implemented "ignore-article" command to ignore certain articles using the filter language
	introduced a memory leak with this FilterParser/matcher objects...
  • Loading branch information...
akrennmair committed Jun 1, 2007
1 parent 3abe90e commit 4c1d272f4f3430d05b08e05835b51590ce5cec70
Showing with 76 additions and 10 deletions.
  1. +6 −1 doc/newsbeuter.txt
  2. +1 −2 filter/FilterParser.cpp
  3. +2 −2 filter/FilterParser.h
  4. +1 −0 include/controller.h
  5. +1 −0 include/matcher.h
  6. +12 −1 include/rss.h
  7. +3 −1 src/controller.cpp
  8. +1 −1 src/itemlist_formaction.cpp
  9. +4 −0 src/matcher.cpp
  10. +45 −2 src/rss.cpp
View
@@ -368,7 +368,12 @@ The possibilities for combining such queries is endless, sky (actually:
the available memory) is the limit.
To filter your feeds, press "F" in the feed list, enter your filter expression,
-and press enter. To clear the filter, press Ctrl-F.
+and press enter. To clear the filter, press Ctrl-F. To filter the articles in the article list,
+press "F", enter your expression, and press enter. Clearing the filter works the same as before.
+Be aware that only certain attributes work in both dialogs. The table below lists all available
+attributes and their context, i.e. an attribute that belongs to a feed can only be matched
+in the feed list, while an attribute that belongs to an article can only be matched in the
+article list.
.Available Comparison Operators
[frame="all", grid="all", format="dsv"]
View
@@ -5,7 +5,7 @@
FilterParser::FilterParser() : root(0), curpos(0), next_must_descend_right(false) { }
FilterParser::~FilterParser() {
- cleanup();
+ // cleanup();
}
void FilterParser::add_logop(int op) {
@@ -120,4 +120,3 @@ expression::expression(int o) : op(o), l(NULL), r(NULL), parent(NULL), regex(NUL
expression::~expression() {
delete regex;
}
-
View
@@ -6,11 +6,11 @@
#include <regex.h>
-enum { LOGOP_AND = 1, LOGOP_OR, MATCHOP_EQ, MATCHOP_NE, MATCHOP_RXEQ, MATCHOP_RXNE, MATCHOP_LT, MATCHOP_GT, MATCHOP_LE, MATCHOP_GE, MATCHOP_CONTAINS, MATCHOP_CONTAINSNOT };
+enum { LOGOP_INVALID = 0, LOGOP_AND = 1, LOGOP_OR, MATCHOP_EQ, MATCHOP_NE, MATCHOP_RXEQ, MATCHOP_RXNE, MATCHOP_LT, MATCHOP_GT, MATCHOP_LE, MATCHOP_GE, MATCHOP_CONTAINS, MATCHOP_CONTAINSNOT };
struct expression {
expression(const std::string& n, const std::string& lit, int o);
- expression(int o);
+ expression(int o = LOGOP_INVALID);
~expression();
std::string name;
View
@@ -57,6 +57,7 @@ namespace newsbeuter {
std::string queue_file;
bool refresh_on_start;
configcontainer * cfg;
+ rss_ignores ign;
mutex * reload_mutex;
};
View
@@ -16,6 +16,7 @@ namespace newsbeuter {
class matcher {
public:
matcher();
+ matcher(const std::string& expr);
bool parse(const std::string& expr);
bool matches(matchable* item);
private:
View
@@ -128,9 +128,11 @@ namespace newsbeuter {
cache * ch;
};
+ class rss_ignores;
+
class rss_parser {
public:
- rss_parser(const char * uri, cache * c, configcontainer *);
+ rss_parser(const char * uri, cache * c, configcontainer *, rss_ignores * ii);
~rss_parser();
rss_feed parse();
static time_t parse_date(const std::string& datestr);
@@ -139,6 +141,15 @@ namespace newsbeuter {
cache * ch;
configcontainer *cfgcont;
mrss_t * mrss;
+ rss_ignores * ign;
+ };
+
+ class rss_ignores : public config_action_handler {
+ public:
+ virtual action_handler_status handle_action(const std::string& action, const std::vector<std::string>& params);
+ bool matches(rss_item* item);
+ private:
+ std::vector<std::pair<std::string, matcher> > ignores;
};
}
View
@@ -208,6 +208,8 @@ void controller::run(int argc, char * argv[]) {
cfgparser.register_handler("bind-key",&keys);
cfgparser.register_handler("unbind-key",&keys);
+ cfgparser.register_handler("ignore-article",&ign);
+
try {
cfgparser.parse("/etc/" PROGRAM_NAME "/config");
cfgparser.parse(config_file);
@@ -344,7 +346,7 @@ void controller::reload(unsigned int pos, unsigned int max) {
v->set_status(msgbuf);
GetLogger().log(LOG_DEBUG, "controller::reload: after setting status");
- rss_parser parser(feed.rssurl().c_str(), rsscache, cfg);
+ rss_parser parser(feed.rssurl().c_str(), rsscache, cfg, &ign);
GetLogger().log(LOG_DEBUG, "controller::reload: created parser");
try {
feed = parser.parse();
@@ -8,7 +8,7 @@
namespace newsbeuter {
itemlist_formaction::itemlist_formaction(view * vv, std::string formstr)
- : formaction(vv,formstr), feed(0), apply_filter(false), update_visible_items(false) {
+ : formaction(vv,formstr), feed(0), apply_filter(false), update_visible_items(true) {
}
itemlist_formaction::~itemlist_formaction() { }
View
@@ -15,6 +15,10 @@ matchable::~matchable() { }
matcher::matcher() { }
+matcher::matcher(const std::string& expr) {
+ parse(expr);
+}
+
bool matcher::parse(const std::string& expr) {
struct timeval tv1, tv2;
gettimeofday(&tv1, NULL);
View
@@ -16,7 +16,8 @@
using namespace newsbeuter;
-rss_parser::rss_parser(const char * uri, cache * c, configcontainer * cfg) : my_uri(uri), ch(c), cfgcont(cfg), mrss(0) { }
+rss_parser::rss_parser(const char * uri, cache * c, configcontainer * cfg, rss_ignores * ii)
+ : my_uri(uri), ch(c), cfgcont(cfg), mrss(0), ign(ii) { }
rss_parser::~rss_parser() { }
@@ -108,6 +109,8 @@ rss_feed rss_parser::parse() {
x.set_author(utils::convert_text(item->author, "utf-8", encoding));
}
+ x.set_feedurl(feed.rssurl());
+
mrss_tag_t * content;
if (mrss_search_tag(item, "encoded", "http://purl.org/rss/1.0/modules/content/", &content) == MRSS_OK && content) {
@@ -179,14 +182,22 @@ rss_feed rss_parser::parse() {
GetLogger().log(LOG_DEBUG, "rss_parser::parse: item title = `%s' link = `%s' pubDate = `%s' (%d) description = `%s'",
x.title().c_str(), x.link().c_str(), x.pubDate().c_str(), x.pubDate_timestamp(), x.description().c_str());
- feed.items().push_back(x);
+
+ // only add item to feed if it isn't on the ignore list or if there is no ignore list
+ if (!ign || !ign->matches(&x)) {
+ feed.items().push_back(x);
+ GetLogger().log(LOG_INFO, "rss_parser::parse: added article title = `%s' link = `%s' ign = %p", x.title().c_str(), x.link().c_str(), ign);
+ } else {
+ GetLogger().log(LOG_INFO, "rss_parser::parse: ignored article title = `%s' link = `%s'", x.title().c_str(), x.link().c_str());
+ }
}
mrss_free(mrss);
return feed;
}
+
// rss_item setters
void rss_item::set_title(const std::string& t) {
@@ -446,3 +457,35 @@ std::string rss_feed::get_attribute(const std::string& attribname) {
}
return "";
}
+
+action_handler_status rss_ignores::handle_action(const std::string& action, const std::vector<std::string>& params) {
+ if (action == "ignore-article") {
+ if (params.size() >= 2) {
+ std::string ignore_rssurl = params[0];
+ std::string ignore_expr = params[1];
+ matcher m;
+ if (m.parse(ignore_expr)) {
+ ignores.push_back(std::pair<std::string,matcher>(ignore_rssurl, matcher(ignore_expr)));
+ return AHS_OK;
+ } else {
+ return AHS_INVALID_PARAMS;
+ }
+ } else {
+ return AHS_TOO_FEW_PARAMS;
+ }
+ }
+ return AHS_INVALID_COMMAND;
+}
+
+bool rss_ignores::matches(rss_item* item) {
+ for (std::vector<std::pair<std::string, matcher> >::iterator it=ignores.begin();it!=ignores.end();++it) {
+ GetLogger().log(LOG_DEBUG, "rss_ignores::matches: it->first = `%s' item->feedurl = `%s'", it->first.c_str(), item->feedurl().c_str());
+ if (it->first == "*" || item->feedurl() == it->first) {
+ if (it->second.matches(item)) {
+ GetLogger().log(LOG_DEBUG, "rss_ignores::matches: found match");
+ return true;
+ }
+ }
+ }
+ return false;
+}

0 comments on commit 4c1d272

Please sign in to comment.