# Display Latest FreeBSD News At Prompt



## Amzo (Nov 18, 2012)

I'm not sure if this is the right section, but I am trying to get my shell to display the latest FreeBSD news at login.

however, characters are missing from the news, probably due to the way I used sed. (Which I am no good at)

Example:







And the code snippet:


```
if [ "$PS1" ]; then
	# The characters "Â£, Â§" are used as metacharacters. They should not be encountered in a feed...
	echo -e "$(echo $(curl --silent http://www.freebsd.org/news/rss.xml | sed -e ':a;N;$!ba;s/\n/ /g') | \
		sed -e 's/&/\&/g
		s/<\|</</g
		s/>\|>/>/g
		s/<\/a>/Â£/g
		s/href\=\"/Â§/g
		s/<title>/\\n\\n\\n   :: \\e[01;31m/g; s/<\/title>/\\e[00m ::\\n/g
		s/<link>/ [ \\e[01;36m/g; s/<\/link>/\\e[00m ]/g
		s/<description>/\\n\\n\\e[00;37m/g; s/<\/description>/\\e[00m\\n\\n/g
		s/<p\( [^>]*\)\?>\|<br\s*\/\?>/\n/g
		s/<b\( [^>]*\)\?>\|<strong\( [^>]*\)\?>/\\e[01;30m/g; s/<\/b>\|<\/strong>/\\e[00;37m/g
		s/<i\( [^>]*\)\?>\|<em\( [^>]*\)\?>/\\e[41;37m/g; s/<\/i>\|<\/em>/\\e[00;37m/g
		s/<u\( [^>]*\)\?>/\\e[4;37m/g; s/<\/u>/\\e[00;37m/g
		s/<code\( [^>]*\)\?>/\\e[00m/g; s/<\/code>/\\e[00;37m/g
		s/<a[^Â§]*Â§\([^\"]*\)\"[^>]*>\([^Â£]*\)[^Â£]*Â£/\\e[01;31m\2\\e[00;37m \\e[01;34m[\\e[00;37m \\e[04m\1\\e[00;37m\\e[01;34m ]\\e[00;37m/g
		s/<li\( [^>]*\)\?>/\n \\e[01;34m*\\e[00;37m /g
		s/<!\[CDATA\[\|\]\]>//g
		s/\|>\s*<//g
		s/ *<[^>]\+> */ /g
		s/[<>Â£Â§]//g')\n\n";
fi
```


----------



## derekschrock (Nov 18, 2012)

I won't use sed to parse RSS.  If you can handle using python:


```
#!/usr/bin/env python 
import feedparser
import socket 
socket.setdefaulttimeout(5)
feed = feedparser.parse( 'http://www.freebsd.org/news/rss.xml' )
sort_entries = sorted(feed.entries, key=lambda entry: entry["published_parsed"])

for e in sort_entries:
    print '\t::', '\033[91m', e.title.encode('utf8'), '\033[0m', '::\n'
    if 'description' in e: 
        print '  ' + e.description + '\n'
    print '\t[', e.link, ']\n'
```


----------



## Amzo (Nov 18, 2012)

Wow thanks, that is a lot better. I put that snippet into /usr/local/bin/news

and just placed a call to it in my bashrc.

However, I am not familiar with python, but is there a way to limit the amount of latest news it shows? Maybe only the 3 latest news articles?

Tho, using the following and your snippet works a treat. It is much appreciated.


```
if [ "$PS1" ]; then
	/usr/local/bin/news
fi
```


----------



## vermaden (Nov 18, 2012)

Here is mine:

```
echo -e "$( curl --silent http://www.freebsd.org/news/rss.xml \
              | grep -A 99999 '<atom:link' \
              | sed 1d \
              | grep -E "(title|link|description)" \
              | sed -E 's/.*<link>/\\e[4m\\e[34m/g' \
              | sed -e 's/<\/link>/\\e[0m\\n/g' \
              | sed -E 's/.*<title>/\\e[01;31m/g' \
              | sed -e 's/<\/title>/\\e[00m/g' \
              | sed -E 's/.*<description>/\\e[00;37m/g' \
              | sed -e 's/<\/description>/\\e[00m/g' \
          )"
```

... and it looks like that:


----------



## wblock@ (Nov 18, 2012)

The -dump option to www/lynx could be used for this, too.


----------



## expl (Nov 18, 2012)

I'd use fetch() for this since it comes with FreeBSD, not from ports.

Fetch to stdout:
`fetch -q -o - 'http://www.freebsd.org/news/rss.xml'`


----------



## derekschrock (Nov 18, 2012)

This would list the latest three in ascending order 


```
#!/usr/bin/env python 
import feedparser
import socket 
socket.setdefaulttimeout(5)
feed = feedparser.parse( 'http://www.freebsd.org/news/rss.xml' )
sort_entries = sorted(feed.entries[0], key=lambda entry: entry["published_parsed"])

for e in sort_entries:
    print '\t::', '\033[91m', e.title.encode('utf8'), '\033[0m', '::\n'
    if 'description' in e: 
        print '  ' + e.description + '\n'
    print '\t[', e.link, ']\n'
```


----------



## cpm@ (Nov 19, 2012)

Other possibility, using ruby instead python:

```
require 'rss/1.0'
require 'rss/2.0'
require 'open-uri'

source = "http://www.freebsd.org/news/rss.xml"
content=""
open(source) do |s| content = s.read end
rss = RSS::Parser.parse(content,false)

print "RSS title: ", rss.channel.title, "\n"
print "RSS link: ", rss.channel.link, "\n"
print "RSS description: ", rss.channel.description, "\n"
print "RSS publication date: ", rss.channel.date, "\n"
print "Number of RSS items: ", rss.items.size, "\n" 
puts
puts "Item values"
puts
print "title: ", rss.items[0].title, "\n"
print "link: ", rss.items[0].link, "\n"
print "description: ", rss.items[0].description, "\n"
print "date: ", rss.items[0].date, "\n"
puts
print "title: ", rss.items[1].title, "\n"
print "link: ", rss.items[1].link, "\n"
print "description: ", rss.items[1].description, "\n"
print "date: ", rss.items[1].date, "\n"
puts
print "title: ", rss.items[2].title, "\n"
print "link: ", rss.items[2].link, "\n"
print "description: ", rss.items[2].description, "\n"
print "date: ", rss.items[2].date, "\n"
puts
print "title: ", rss.items[3].title, "\n"
print "link: ", rss.items[3].link, "\n"
print "description: ", rss.items[3].description, "\n"
print "date: ", rss.items[3].date, "\n"
puts
print "title: ", rss.items[4].title, "\n"
print "link: ", rss.items[4].link, "\n"
print "description: ", rss.items[4].description, "\n"
print "date: ", rss.items[4].date, "\n"
puts
print "title: ", rss.items[5].title, "\n"
print "link: ", rss.items[5].link, "\n"
print "description: ", rss.items[5].description, "\n"
print "date: ", rss.items[5].date, "\n"
puts
print "title: ", rss.items[6].title, "\n"
print "link: ", rss.items[6].link, "\n"
print "description: ", rss.items[6].description, "\n"
print "date: ", rss.items[6].date, "\n"
puts
print "title: ", rss.items[7].title, "\n"
print "link: ", rss.items[7].link, "\n"
print "description: ", rss.items[7].description, "\n"
print "date: ", rss.items[7].date, "\n"
puts
print "title: ", rss.items[8].title, "\n"
print "link: ", rss.items[8].link, "\n"
print "description: ", rss.items[8].description, "\n"
print "date: ", rss.items[8].date, "\n"
puts
print "title: ", rss.items[9].title, "\n"
print "link: ", rss.items[9].link, "\n"
print "description: ", rss.items[9].description, "\n"
print "date: ", rss.items[9].date, "\n"
```


----------



## expl (Nov 20, 2012)

cpu82 said:
			
		

> Other possibility, using ruby instead python:
> 
> ```
> require 'rss/1.0'
> ...



Might want to apply some iteration before you get trolled (to late).


----------



## cpm@ (Nov 20, 2012)

> Might want to apply some iteration before you get trolled (to late).



I need to document myself more to avoid lack of originality


----------



## chatwizrd (Nov 20, 2012)

Seems cool minus all the goofy colors.


----------



## fonz (Nov 20, 2012)

chatwizrd said:
			
		

> Seems cool minus all the goofy colors.


That's probably a matter of taste, but you can get rid of the colours by removing the escape sequences.


----------



## cpm@ (Nov 20, 2012)

Adding colors is not too bad, is more attractive:

```
require 'rss/1.0'
require 'rss/2.0'
require 'open-uri'
require 'term/ansicolor'
include Term::ANSIColor

source = "http://www.freebsd.org/news/rss.xml"
content=""
open(source) do |s| content = s.read end
rss = RSS::Parser.parse(content,false)

print negative, bold, "RSS title: ", rss.channel.title, reset, "\n"
print negative, bold, "RSS link: ", rss.channel.link, reset, "\n"
print negative, bold, "RSS description: ", rss.channel.description, reset, "\n"
print negative, bold, "RSS publication date: ", rss.channel.date, reset, "\n"
print negative, bold, "Number of RSS items: ", rss.items.size, reset, "\n" 
puts
print yellow, bold, underscore, "Item values", reset, "\n" 
puts
print red, bold, underscore, "title: ", rss.items[0].title, reset, "\n" 
print blue, bold, "link: ", rss.items[0].link, reset, "\n"
print green, bold, "description: ", rss.items[0].description, reset, "\n"
print bold, "date: ", rss.items[0].date, reset, "\n"
```


----------



## jotawski (Nov 20, 2012)

derekschrock said:
			
		

> This would list the latest three in ascending order
> 
> 
> ```
> ...


Many thanks indeed,  I love this and I put this code in my facebook group.


----------



## UNIXgod (Nov 21, 2012)

Here... Notice the heredoc removes the need for multiple print statements and newlines( it can take printf or puts as well) ... more so with ruby you can do enumerated iterations from the inside out which allows you to avoid the index style looping like almost every C derived language:


```
#!/usr/bin/env ruby
# UNIXgod's refactoring of cpu82 FreeBSD rss parser
# depends on term/ansicolor gem... 
# might be easier to localize that at toplevel of script.
require 'rss/1.0'
require 'rss/2.0'
require 'open-uri'
require 'term/ansicolor'
include Term::ANSIColor

source = "http://www.freebsd.org/news/rss.xml"
content= String.new
open(source) { |s| content = s.read }
rss = RSS::Parser.parse(content,false)

#THEMES:
r=reset; b=bold; u=underscore
n=negative; nb=n+b
ybu=yellow+b+u; rbu=red+b+u; blb=blue+b; gb=green+b

puts <<-EOF
#{nb} RSS title:  #{rss.channel.title} #{r}
#{nb} RSS link:  #{rss.channel.link} #{r} 
#{nb} RSS description:  #{rss.channel.description} #{r} 
#{nb} RSS publication date: #{rss.channel.date} #{r} 
#{nb} Number of RSS items: #{rss.items.size} #{r}

#{ybu} Item values #{r} 
EOF

rss.items.each do |i|
  printf <<-EOF
  #{rbu} title: #{i.title} #{r}
  #{blb} link:  #{i.link} #{r}
  #{gb} description:  #{i.description} #{r}
  EOF
end
```


cpu82's original:


			
				cpu82 said:
			
		

> Adding colors is not too bad, is more attractive:
> 
> ```
> require 'rss/1.0'
> ...



Also further exploration of that gem it looks like if you really want to use it you can remove the need to call reset with syntax like: puts "Hello".on_red or printf "World!".cyan and so forth without the need to call reset:

[CMD="2.0.0dev :005 >"]Term::ANSIColor.methods - Module.methods[/CMD]


> => [:coloring?, :coloring=, :attributes, :support?, :clear, :reset, :bold, :dark, :italic, :underline, :underscore, :blink, :rapid_blink, :negative, :concealed, :strikethrough, :black, :red, :green, :yellow, :blue, :magenta, :cyan, :white, n_black, n_red, n_green, n_yellow, n_blue, n_magenta, n_cyan, n_white, :intense_black, :intense_red, :intense_green, :intense_yellow, :intense_blue, :intense_magenta, :intense_cyan, :intense_white, n_intense_black, n_intense_red, n_intense_green, n_intense_yellow, n_intense_blue, n_intense_magenta, n_intense_cyan, n_intense_white, :uncolored]


----------



## cpm@ (Nov 21, 2012)

*UNIXgod*, thanks for the tip. I will take a look.


----------



## jwele (Nov 29, 2012)

Something like this would be perfect for FreeBSD/Arch Linux. Cool work Amzo.


----------



## vermaden (Nov 29, 2012)

@jwele

... but this is for FreeBSD.


----------



## jwele (Nov 30, 2012)

vermaden said:
			
		

> @jwele
> 
> ... but this is for FreeBSD.



And if I put it on my FreeBSD box it would be perfect for it.


----------



## MNIHKLOM (Feb 22, 2013)

derekschrock said:
			
		

> This would list the latest three in ascending order
> 
> 
> ```
> ...


Hi,

I have just discovered today that I got errors that said



> ImportError: No module named feedparser



when running this python script.  I am using python 2.7 as my default python and FreeBSD 9-STABLE is my os.  I have just upgraded py27-feedparser-5.1.3 this morning too.

Apologized me for disturbing but since I am leaning python at this moment so I need to know that what really the cause of error is.

Thanks in advanced for any hints or helps.

With best regards,
MNIHKLOM


----------



## derekschrock (Feb 22, 2013)

You need to install textproc/py-feedparser


----------



## MNIHKLOM (Feb 22, 2013)

derekschrock said:
			
		

> You need to install textproc/py-feedparser



Yes I did since your first post and have upgraded this morning but still got error.

Thank you very much for your prompt response.


With best regards,
MNIHKLOM


----------



## cpm@ (Feb 22, 2013)

@MNIHKLOM

Please, show output:
`# pkg_info -Ix python`


----------



## derekschrock (Feb 22, 2013)

MNIHKLOM said:
			
		

> Yes I did since your first post and have upgraded this morning but still got error.
> 
> Thank you very much for your prompt response.
> 
> ...



What site-package did you install it to?  Seems like you might have 2.6 and 2.7 installed?


----------



## MNIHKLOM (Feb 22, 2013)

derekschrock said:
			
		

> What site-package did you install it to?  Seems like you might have 2.6 and 2.7 installed?



Hi,

To cpu82 and derekschrock, this is all about python I have installed



> [MNIHKLOM] ~% pkg_info -Ix python
> boost-python-libs-1.48.0 Framework for interfacing Python and C++
> python-2.7,2        The "meta-port" for the default version of Python interpret
> python-doc-html-2.7.3 Documentation for the Python programming language
> ...



and my /etc/make.conf content is



> [MNIHKLOM] ~% cat /etc/make.conf
> #
> WITH_CLANG=yes
> WITH_CLANG_IS_CC=yes
> ...



some blender's dependencies required python33 to be installed but I forgot why I installed python32.  I keep python24 since I am using zope211.

Once again many thanks for your times indeed.

With best regards,
MNIHKLOM


----------



## cpm@ (Feb 22, 2013)

In order to site-packages are made available to the PYTHON_DEFAULT_VERSION variable established is required running upgrade-site-packages target in lang/python as explained in /usr/ports/UPDATING (note 20110304): 

If using portupgrade(1):
`# cd /usr/ports/lang/python && make upgrade-site-packages`

If using portmaster(8):
`# cd /usr/ports/lang/python && make upgrade-site-packages -DUSE_PORTMASTER`

After upgrade, you can import feedparser module without problems.


----------



## MNIHKLOM (Feb 23, 2013)

cpu82 said:
			
		

> In order to site-packages are made available to the PYTHON_DEFAULT_VERSION variable established is required running upgrade-site-packages target in lang/python as explained in /usr/ports/UPDATING (note 20110304):
> 
> If using portupgrade(1):
> `# cd /usr/ports/lang/python && make upgrade-site-packages`
> ...


Hi,

I need to record this into my leaning notes.  I think as long as python version is the same as the one in `meta port`, one need not to explicitly specify PYTHON_DEFAULT_VERSION  in /etc/make.conf but then what to do with python32 or python33 once they are installed later, will they overwrite /usr/local/bin/python

I appreciate all helps and hints and all of your valuable times to the forum and to me too.

With best regards,
MNIHKLOM


----------



## cpm@ (Feb 23, 2013)

Well, as the porters-handbook says literally:


> The Ports Collection supports parallel installation of multiple Python versions. Ports should make sure to use a correct python interpreter, according to the user-settable PYTHON_VERSION variable. Most prominently, this means replacing the path to python executable in scripts with the value of PYTHON_CMD variable.



Try to set PYTHON_VERSION variable to install textproc/py-feedparser as following:
`# cd /usr/ports/textproc/py-feedparser && env PYTHON_VERSION=python2.7 make clean install`

So add PYTHON_VERSION=python2.7 to /etc/make.conf to make setting permanent.


----------



## MNIHKLOM (Feb 23, 2013)

cpu82 said:
			
		

> Well, as the porters-handbook says literally:
> 
> 
> Try to set PYTHON_VERSION variable to install textproc/py-feedparser as following:
> ...


Hi,

I do not touch porters-handbook before, only /usr/ports/UPDATING, /usr/src/UPDATING, /usr/doc/en_US.ISO8859-1/books/handbook/book.html but not often.  This is rather new indeed.

I experimented by reinstalling python32 and found that /usr/local/bin/python is actually python 3.2, not the default one as specify in /etc/make.conf.  The yield is that I have to force reinstalled meta-port for python in order for version 2.7 to be the default one.

I add python setting in /etc/make.conf already now.

All helps and hints and your times given to me through the forums are appreciated.

With best regards,
MNIHKLOM


----------



## cpm@ (Feb 23, 2013)

MNIHKLOM said:
			
		

> The yield is that I have to force reinstalled meta-port for python in order for version 2.7 to be the default one.



It's correct :e

Or doing dirty trick:

```
# mv /usr/local/bin/python python.old
# ln -s /usr/local/bin/python2.7 /usr/local/bin/python
```

Note that has to be redone after every update of the default python. So to recover the "old" symlink, undo the first step.


----------

