Features Download

From: Youness Alaoui <kakaroto <at> kakaroto.homelinux.net>
Subject: Re: aMSN2 ncurses (Re: Branches needed? (Was Re: net top-cw))
Newsgroups: gmane.network.instant-messaging.amsn.devel
Date: Tuesday 17th March 2009 20:20:01 UTC (over 9 years ago)
On Tue, Mar 17, 2009 at 06:12:56PM +0000, Stéphane Bisinger wrote:
> 2009/3/17 Youness Alaoui :
> >
> > Great! Nice to see you work so fast! I just tried it out and it does
> > already! although.. the contact list didn't appear.. butI know you
> > know that :)
> It's just that I love python, I find it so easy to get going with
no who doesn't? :p

> >  by the way.. I just realized you are kjir from IRC... sorry about my
> > previous reply to you.. I asked about logging in amsn2 and I thought
> > meant 'chat logs', not debug logs, hehe...
> Don't worry about that, I know that you get asked a lot of silly
> questions and it's not always easy to recognize legitimate ones ;)
thanks for your comprehension ;)
> > actually, the logging mechanism is something that comes from pymsn,
look at
> > the code that sets the logger, I'm sure there are many more options
that you
> > can do with it..
> > for now, amsn itself doesn't have any logging mechanism.. if the one
> > pymsn uses is a standard python lib, then we could use that too!
> The reason I asked about that is that with the ncurses interface print
> statements interfere with the program display, so I have to redirect
> output to a file. Also I learned a long time ago that a good logging
> mechanism is an invaluable tool when it comes to debugging... Maybe
> it's more true for web development, but it's always helpful. Anyway
> I'll give it some thought, maybe I can come up with a nice system to
> do logging.

hehe, right, I didn't think of debug + ncurses.. you're
right, so anyways, it's easy to fix.. look here :
that's the logging mechanism of python and that's what pymsn
If you look at amsn2/core/amsn.py, you'll see :
        if self._options.debug:
            import logging

You could just add filename="/path/to/log" in that call to
That logging mechanism seems good, so I think using it for
amsn2 also would be a good idea.
And no, a good logging mechanism is always very important,
for web development or not! :)

> > Very interesting point here! I didn't think of the hotkeys yet! I
wonder if
> > we should stick with amsn1's hotkeys (not a lot I must say) or just
> > from scratch... I wonder also if we should have a common hotkey list or
> > every front end could implement its own... I really don't know yet..
> Well some hotkeys should follow some standars, like ctrl+w to close a
> tab, so that we apply the rule of least surprise

yes, sure, we already have some hotkeys defined for aMSN and
we'd probably want to keep them so people who are used to
them can keep using them.. search the wiki for 'hotkeys'

> > but
> > quickly off the top of my hat I'd say:
> > amsn would provide a 'HotKeyView' with hotkeys for all actions, and the
> > would have to use them ... like a list of KeyBindingView and Action
> > being a callback to call, and KeyBindingView already exists in
> > amsn2/core/views/keybindingview.py
> > Those would be configurable with an option like 'vim hotkeys/emacs
> > hotkeys/custom' so a user could override and customize each hotkey, and
> > nothing would have to be done by the UI... keeping our "dumb UI"
> > you just get the hotkeys for every window opened, you hook the key
> > to call that specific action... (since the core sets the bindings on
> > window, we would have the callback contain all the necessary arguments
> > already.. like "view_history $email".. if the core detects that the
> > switched to another tab, he would just change the action associated
with a
> > binding and call the SetHotkeys again on the window, with the other
> > email as argument, etc... )
> This could be a good idea, although I am not so convinced about the
> mechanism to pass the correct arguments. Maybe all callback functions
> must accept a single argument which holds a "context" object where you
> can find the info relative to the selected tab (i.e. the user's
> e-mail), so that functions that need it (i.e. nudge the user) use that
> object, functions that don't just ignore it.
> The thing is some hotkeys will need to perform actions on the UI
> itself (i.e. enable/disable bold, hide user pic), but we could solve
> that by creating those methods in the base classes and setting them as
> the callback function.

Humm.. well, I don't know much about python, but in tcl, a
callback is just a string, so you can put your callback as
"function $arg1 $arg2" for example... but I think python
allows something like that too.. 
callback (*args) 
or callback (**kargs)
I know i've seen this before.. you can have a tuple for your
args, or a dictionary with var_name:value... since anyways,
python passes arguments as tuples or dictionaries...
and doing *arg or **args would expand the tuple/dictionary
into an argument list..
I'd have to look into it, but I think it's doable.
Anyways, this way you can pass any number of arguments to
any callback you want. otherwise, using a context structure
would work too in case i'm totally wrong here..
about the UI actions, that's no problem, everything goes
through the core and the core would just call the
appropriate UI method anyways.

> > This would allow all front ends to have the same key bindings, so we
> > actually finally ue amsn wouldn't the need to use the mouse at all (use
> > ncurses key bindings on the gtk/qt/efl front end for example, hehe).
> > would allow users to customize their stuff..
> I have some doubts about the vim style keybindings in a graphical UI,
> you'd need to find a way to have at least two modes (insert mode and
> command mode) and make it understandable to the user in which state he
> is. It not impossible, though, Vimperator is an example of such an
> application.

you're perfectly right about that... for ncurses it's easy,
but for another type of UI, not that much... also if we
implement that, it would have to go in the core, not in the
UI (in order to keep the same behavior everywhere on every
front end, and to keep the front ends 'dumb')...
however, I'm afraid it would add too much overhead to notify
the core of every keystroke and then let the core tell the
UI whether to add that key or to do something else... and it would
maybe (probably) complicate a lot how the UIs would work
(they'd have to override the text/entry widget's default
behavior for that).
I would probably vote for just doing an emacs style hotkeys,
but I'm guessing that you're a vi user and you want it to be
vi style.. anyways, we'll discuss this further when the time
comes! But I'm sure we can manage something...

> > The front end could however provide the core with a 'PreferredHotkeys"
> > each action, in case some front ends have some kind of preference
> > switch tabs with ctrl-up/ctrl-down on qt4/kde because it's the same as
> > konqueror or whatever, but ctrl-up/ctrl-down might be the default gnome
> > binding to switch from previous/next virtual desktop... (just examples,
> > don't use kde or gnome so don't know the real shortcuts)). If the user
> > customized the shortcut, then the core would store the front end's
> > preference as the default one.
> Yes this is a good idea, as above this would apply the rule of least
surprise ;)
> > hehe, thanks! :) yes, i'm very proud of the design! :)
> > You can start looking at these two threads if you want to understand
> > design :
> > http://thread.gmane.org/gmane.network.instant-messaging.amsn.devel/9502
> > http://thread.gmane.org/gmane.network.instant-messaging.amsn.devel/9497
> > It's a bit old so some stuff might have changed but I think the general
> > is there.. I should probably start a wiki page on the design and keep
it up
> > to date as we move along... also keep the API well documented!
> > You can comment on the design whenever you want.. especially if it's to
> > how incredibly good it is.. :D :)  :p
> I read the messages and now I understand what views are (well sort of
> ;) ). There are two issues that come to my mind right now: with
> ncurses you can't display images, but you'll probably want to display
> the corresponding text for the smileys and the contact list should
> always display just the nickname because with ncurses you have less
> control over the spacing, so it's better with shorter names. I don't
> know the details about the implementation of these aspects (yet) so
> maybe these issues don't really exist, I'll have to check... Does this
> design allow for a "disable smileys" toggle? Because I don't know
> about you, but I sometimes have to fight hard with smileys to
> understand what it is written because often people map smileys to
> small words that may be embedded in other words. Ok I'll explain it
> with an example: let's say you map the word "ace" with an image of an
> ace of spades, then when you write word as "space", "grace", "mace",
> "face", etc you see some letters and the smiley without understanding
> what the word actually is. I know, this is a silly mapping, but it's
> not so uncommon, at least among my contacs :O
> What I like about this design is that it is very flexible and I can
> see an easy solution about any issue that arises :D This is very
> valuable!

ok cool.. well, let me explain quickly what a 'view' is...
basically, it's what the user should 'view'... in my
opinion, the UI doesn't need to know what the nickname or
personal message of a contact is, or if he's online, away,
offline, or blocked, has an alarm on him, a custom nickname,
The UI doesn't need to know that a group has X contacts
online and Y offline.. it just needs to know what to show..
All that information will be 'parsed' by the human's brain
so why are people bothering giving all that huge
responsability to the UI for it to know every little detail
about the contact and then transform the contact into
something visible on screen.. the Views are a way to
abstract that, you don't tell the UI to render this contact
with this status and this nickname, etc.. you tell it to
render a 'string' and that string represents a contact...
once the string is rendered correctly, then the user will
see the string and he will know exactly what's the nickname,
status, etc... the UI didn't need to know all that info..
This allows the UI to be very dumb too.. and the main reason
is to avoid bugs like : "I set a custom nickname on a user
but it doesn't show it on the QT front end, but works with
gtk, why ?"
imagine we have 10 options that interfere with how a contact
is to be rendered.. like "show psm below the nick/next to
it" if we add that option at some point in the future, then
we'd need to update ALL the front ends.. and with the same
if/else code.. why not just put it in the core directly! the
UI doesn't need to know about that option, he just gets a
string :)
That's basically what a 'View' is... with regards to
contacts.. but I'm putting views everywhere now in amsn2, a
view is simply the core telling the UI *what* to show.. what
the user should 'view'... and ultimately, the UI should be
able to do everything but never, ever use a single line of :
config.getOption(whatever) or something like that... because
all options are taken care of in the core..

Another example I often use, is that for the contact list,
the design makes it so simple that you can fit all the use
cases in only three functions.. contactlistUpdated,
groupUpdated and contactUpdated...
At first, you get contactListUpdated with a ContactListView
containing a sorted list of groups which themselves contain
a sorted list of contacts.. there, your contact list is
populated, it's sorted, etc...
The status of a group is defined by the 'icon/color'
combination used in its view, so the UI doesn't even need to
know if a group is expanded or collapsed.. it just shows the
icon and puts the text in the right color and then the user
will know if it's expanded or collapsed.. and it will also
have an empty list of contacts.. of course, why would the UI
care about the 'hidden' contacts, it doesn't show them so it
doesn't need to know about them.
If a user changes his nickname or status, you get
contactUpdated so you can update the user's StringView.. if
that nick/state change made him change position in the
contact list (you sort by status or you start
alphabetically, etc..) then you also call groupUpdated and
then the UI would compare the sorted list of the groupView
with its current state and reorder the contacts...
If the last online person goes offline from a group and the
option "hide empty groups" is enabled, then
contactlistUpdated, the group is removed from the list and
the UI would remove the group.
These simple 3 functions are enough to replace :
contact : nickname changed, personal message changed, some
custom setting changes, status changed, blocked, unblocked,
added, removed, copied to group, moved to group, removed
from group, sort by status, sort alphabetically, etc...
group : renamed, added, deleted, contact changed state (to
keep count of X/Y online contacts), sorting changed, show
online/offline, or show groups, or hide offline contacts,
contactlist, change sorting, add/remove group, etc..

Also, the example I like to give is that with this design,
you could even have an option on a user "always show this
contact" and you could collapse a group but the contact
stays visible..
The drawback is that when a user clicks on a group, the UI
should tell the core about it and let the core decide if it
should collapse, expand or not.. (maybe a setting double
click to collapse/expand, or, a group with 'never collapse',
or the above example of 'always show this contact').
So as long as the UI tells the core "i have this event on
this group, what should i do", then anything can happen..
and all that, of course, still without having a single
decision-making line of code in the UI... and without doing
any config.getOption() or anything like that.

damn it, I couldn't make my explanation 'short'.. sorry!
Anyways, I hope that it helped you better understand the
design I'm looking for!

anyways, about the smileys, I thought about that (don't
remember if it's implemented or not). It would be the same
as the 'alt' attribute of an  in html.. basically the
StringView to represent the contact/text/whatever would have
the list [text hello, smiley image123 :), text world]
in other words a ImageElement of a StringView could easily
have the text the smiley represents... This is definitely
needed also for other front ends because when you want to
copy/paste stuff, and you copy text containing a smiley, the
copied text should actually contain the text trigger, not
just a space (like WLM does).
Anyways, about the disable smileys, of course the design
allows it..  since the UI doesn't have any idea what a
smiley is (do we really want to implement smiley parsing in
every front end?), the core takes care of that, it will
parse the smileys in the nicknames/text sent/received, etc..
and it will build the StringView that the front end has to
show.. for ncurses, you'd just use the text trigger and
ignore the images.. and if you want to disable it, then the
option is added in the core, and the core doesn't substitute
smileys and it will just work in every front end without
having to update any one of them (that's the purpose of my
design :))
And by the way about that silly smileys thing that you were
talking about, yes, it's very common, that's why you can
override that in aMSN.. just go to the properties page of
your contact and in the settings tab, you can enable the
option "ignore custom smileys from this contact". This way
you still get custom smileys, but you can disable them just
for those annoying contacts who don't know how to use
again.. the current amsn2 design would allow such a feature
to be added without any changes to the UIs... since they
never need to do the infamous config.getOption() :)

Thanks! :)

> -- 
> Stéphane

Apps built with the Adobe(R) Flex(R) framework and Flex Builder(TM) are
powering Web 2.0 with engaging, cross-platform capabilities. Quickly and
easily build your RIAs with Flex Builder, the Eclipse(TM)based development
software that enables intelligent coding and step-through debugging.
Download the free 60 day trial. http://p.sf.net/sfu/www-adobe-com
CD: 12ms