merge missing changeset from default into plugin, so both branches are up to date
This commit is contained in:
commit
deea31d9b7
4 changed files with 252 additions and 37 deletions
158
data/poezio.1
158
data/poezio.1
|
@ -1,9 +1,9 @@
|
||||||
.\" Copyright 2010 Le Coz Florent
|
.\" Copyright 2010 Le Coz Florent
|
||||||
.\" This man page is distributed under the GPLv3 license.
|
.\" This man page is distributed under the GPLv3 license.
|
||||||
.\" See COPYING file
|
.\" See COPYING file
|
||||||
.TH "Poezio" "1" "August 1, 2010" "Poezio dev team" ""
|
.TH "Poezio" "1" "September 26, 2011" "Poezio dev team" ""
|
||||||
.SH "NAME"
|
.SH "NAME"
|
||||||
Poezio \- a ncurses jabber client
|
Poezio \- a ncurses jabber client written in python3
|
||||||
.SH "SYNOPSIS"
|
.SH "SYNOPSIS"
|
||||||
.B poezio [\-f \fICONFIG_FILE\fR] [\-d \fIDEBUG_FILE\fR] [\-h]
|
.B poezio [\-f \fICONFIG_FILE\fR] [\-d \fIDEBUG_FILE\fR] [\-h]
|
||||||
.SH "DESCRIPTION"
|
.SH "DESCRIPTION"
|
||||||
|
@ -20,10 +20,164 @@ Log debug from both poezio and SleekXMPP in \fIDEBUG_FILE\fR. Debug contains inc
|
||||||
.TP
|
.TP
|
||||||
\fB\-h\fR
|
\fB\-h\fR
|
||||||
Display an help message
|
Display an help message
|
||||||
|
|
||||||
|
.SH "TABS"
|
||||||
|
A \fItab\fR, in Poezio, is the base structure of the interface. A tab may contains one or more \fIwindows\fR, and can be of different types:
|
||||||
|
.RS
|
||||||
|
.TP 6
|
||||||
|
.I Roster \fRtab
|
||||||
|
It contains a list of your contacts on the left, as well as an info window on the right.
|
||||||
|
.TP
|
||||||
|
.I MUC \fRtab
|
||||||
|
MUC stands for "Multi-User Chat".
|
||||||
|
.TP
|
||||||
|
.I Conversation \fRtab
|
||||||
|
It is used for one-to-one communication, usually when using a real Jabber account.
|
||||||
|
.TP
|
||||||
|
.I Private \fRtab
|
||||||
|
It is used to privately communicate with someone in a MUC.
|
||||||
|
|
||||||
|
.SH "KEY BINDINGS"
|
||||||
|
While most of the keyboard shortcuts are common to all types of tabs, some of them are tab-specific.
|
||||||
|
.SS Text edition
|
||||||
|
These shortcuts work in any kind of tab; most of them are identical to emacs' ones.
|
||||||
|
.RS
|
||||||
|
.TP 8
|
||||||
|
.B Ctrl+A
|
||||||
|
Move the cursor to the begining of the line.
|
||||||
|
.TP
|
||||||
|
.B Ctrl+E
|
||||||
|
Move the cursor to the end of the line.
|
||||||
|
.TP
|
||||||
|
.B Ctrl+W
|
||||||
|
Delete the word before the cursor.
|
||||||
|
.TP
|
||||||
|
.B Ctrl+K
|
||||||
|
Delete the text from the cursor to the end of the line and save it in the clipboard.
|
||||||
|
.TP
|
||||||
|
.B Ctrl+U
|
||||||
|
Delete the text from the beginning of the line to the cursor and save it in the clipboard.
|
||||||
|
.TP
|
||||||
|
.B Ctrl+Y
|
||||||
|
Insert the text in the clipboard after the cursor.
|
||||||
|
.TP
|
||||||
|
.B Ctrl+D
|
||||||
|
Delete the char after the cursor (same as the Suppr key)
|
||||||
|
|
||||||
|
.SS Navigation keybindings
|
||||||
|
.RS
|
||||||
|
.TP 8
|
||||||
|
.B F5, Ctrl+N
|
||||||
|
Go to the previous tab.
|
||||||
|
.TP
|
||||||
|
.B F6, Ctrl+P
|
||||||
|
Go to the next tab.
|
||||||
|
.TP
|
||||||
|
.B Alt+<number>
|
||||||
|
Go to the specified tab (from 0 to 9)
|
||||||
|
.TP
|
||||||
|
.B Alt+J <two-digits-number>
|
||||||
|
Go to the specified tab (from 00 to 99)
|
||||||
|
.TP
|
||||||
|
.B Alt+Z
|
||||||
|
Go to the last visited tab.
|
||||||
|
.TP
|
||||||
|
.B Alt+E
|
||||||
|
Go to the next important tab (private message, highlight, simple message)
|
||||||
|
.TP
|
||||||
|
.B F7
|
||||||
|
Decrease the information window size.
|
||||||
|
.TP
|
||||||
|
.B F8
|
||||||
|
Increase the information window size.
|
||||||
|
.TP
|
||||||
|
.B Alt+R
|
||||||
|
Go to the roster.
|
||||||
|
.TP
|
||||||
|
.B Ctrl+L
|
||||||
|
Redraw the screen.
|
||||||
|
.TP
|
||||||
|
.B Up, Down
|
||||||
|
Browse the history of the last messages or commands you've entered.
|
||||||
|
|
||||||
|
.SS Roster keybindings
|
||||||
|
.RS
|
||||||
|
.TP 8
|
||||||
|
.B o
|
||||||
|
Hide or show the offline contacts.
|
||||||
|
.TP
|
||||||
|
.B s
|
||||||
|
Search through your contact list.
|
||||||
|
.TP
|
||||||
|
.B Ctrl+G
|
||||||
|
Cancel a search.
|
||||||
|
|
||||||
|
.SS MUC-specific keybindings
|
||||||
|
.RS
|
||||||
|
.TP 8
|
||||||
|
.B Alt+V
|
||||||
|
Move the line separator at the bottom of the text window.
|
||||||
|
.TP
|
||||||
|
.B Tab
|
||||||
|
Complete the nickname that you're typing. If nothing has been entered, insert the nickname of the last user who spoke.
|
||||||
|
.TP
|
||||||
|
.B Alt+/
|
||||||
|
Complete the word that you're typing, based on the list of the recently said words in the conversation.
|
||||||
|
|
||||||
|
.SH "COMMANDS"
|
||||||
|
Most commands support tab completion, both for their names and for their arguments. You can use the \fI/help\fR command to list all available commands, and \fI/help <command>\fR for a complete description of <command>.
|
||||||
|
|
||||||
|
The following is a basic description of the most widely used commands; you should refer to \fI/help\fR inside poezio for more documentation. \fI<foo>\fR denotes a obligatory argument, while \fI[bar]\fR is an optional argument (without argument, the \fI/remove\fR command, for example, acts on the currently selected contact)
|
||||||
|
.SS Roster commands
|
||||||
|
.RS
|
||||||
|
.TP 5
|
||||||
|
.B /add <jid>
|
||||||
|
Add a JID to your roster.
|
||||||
|
.TP
|
||||||
|
.B /remove [jid]
|
||||||
|
Remove a contact from your roster.
|
||||||
|
.TP
|
||||||
|
.B /accept [jid]
|
||||||
|
Accept a JID that wants to subscribe to your presence.
|
||||||
|
.TP
|
||||||
|
.B /deny [jid]
|
||||||
|
The opposite of \fI/accept\fR.
|
||||||
|
|
||||||
|
.SS MUC-specific commands
|
||||||
|
.RS
|
||||||
|
.TP 5
|
||||||
|
.B /recolor
|
||||||
|
Change the color of the nicknames in the conversation. Useful when a few people are talking and their random color happen to be the same: using this command will let you differentiate them more easily.
|
||||||
|
.TP
|
||||||
|
.B /kick <user>
|
||||||
|
Kick the specified user from the room.
|
||||||
|
.TP
|
||||||
|
.B /show <status> [message]
|
||||||
|
Change your status, and status message, in the current room. You can use “avail”, “busy”, “away” and “xa” as your status, followed by an optional message.
|
||||||
|
.TP
|
||||||
|
.B /ignore <user>
|
||||||
|
Ignore the specified user.
|
||||||
|
.TP
|
||||||
|
.B /topic [topic text]
|
||||||
|
View or change the topic of the room.
|
||||||
|
.TP
|
||||||
|
.B /query <user>
|
||||||
|
Talk privately with the specified participant.
|
||||||
|
.TP
|
||||||
|
.B /part
|
||||||
|
Leave the current room.
|
||||||
|
|
||||||
.SH "BUGS"
|
.SH "BUGS"
|
||||||
Sure.
|
Sure.
|
||||||
|
|
||||||
|
.SH "KNOWN ISSUES"
|
||||||
|
If you're using a terminal multiplexer such as \fIscreen\fR or \fItmux\fR, it may be setting $TERM to "screen", which breaks 256-color support. Consider setting your $TERM to something like "screen-256color".
|
||||||
|
|
||||||
.SH "FEEDBACK"
|
.SH "FEEDBACK"
|
||||||
You are encouraged to report bugs or feature requests on http://dev.louiz.org/project/poezio.
|
You are encouraged to report bugs or feature requests on http://dev.louiz.org/project/poezio.
|
||||||
You can also find us on the Jabber chatroom poezio@kikoo.louiz.org
|
You can also find us on the Jabber chatroom poezio@kikoo.louiz.org
|
||||||
|
|
||||||
.SH "AUTHORS"
|
.SH "AUTHORS"
|
||||||
Written by Florent Le Coz <louiz@louiz.org>
|
Written by Florent Le Coz <louiz@louiz.org>
|
||||||
|
|
||||||
|
Later completed by Baptiste Jonglez <baptiste--poezio@jonglez.org>
|
||||||
|
|
|
@ -128,7 +128,6 @@ class Core(object):
|
||||||
'connect': (self.command_reconnect, _('Usage: /connect\nConnect: disconnect from the remote server if you are currently connected and then connect to it again'), None),
|
'connect': (self.command_reconnect, _('Usage: /connect\nConnect: disconnect from the remote server if you are currently connected and then connect to it again'), None),
|
||||||
'server_cycle': (self.command_server_cycle, _('Usage: /server_cycle [domain] [message]\nServer Cycle: disconnect and reconnects in all the rooms in domain.'), None),
|
'server_cycle': (self.command_server_cycle, _('Usage: /server_cycle [domain] [message]\nServer Cycle: disconnect and reconnects in all the rooms in domain.'), None),
|
||||||
'bind': (self.command_bind, _('Usage: /bind <key> <equ>\nBind: bind a key to an other key or to a “command”. For example "/bind ^H KEY_UP" makes Control + h do the same same than the Up key.'), None),
|
'bind': (self.command_bind, _('Usage: /bind <key> <equ>\nBind: bind a key to an other key or to a “command”. For example "/bind ^H KEY_UP" makes Control + h do the same same than the Up key.'), None),
|
||||||
'pubsub': (self.command_pubsub, _('Usage: /pubsub <domain>\nPubsub: Open a pubsub browser on the given domain'), None),
|
|
||||||
'load': (self.command_load, _('Usage: /load <plugin>\nLoad: Load the specified plugin'), self.plugin_manager.completion_load),
|
'load': (self.command_load, _('Usage: /load <plugin>\nLoad: Load the specified plugin'), self.plugin_manager.completion_load),
|
||||||
'unload': (self.command_unload, _('Usage: /unload <plugin>\nUnload: Unload the specified plugin'), self.plugin_manager.completion_unload),
|
'unload': (self.command_unload, _('Usage: /unload <plugin>\nUnload: Unload the specified plugin'), self.plugin_manager.completion_unload),
|
||||||
}
|
}
|
||||||
|
@ -1308,7 +1307,7 @@ class Core(object):
|
||||||
t = self.current_tab()
|
t = self.current_tab()
|
||||||
if not isinstance(t, tabs.MucTab) and not isinstance(t, tabs.PrivateTab):
|
if not isinstance(t, tabs.MucTab) and not isinstance(t, tabs.PrivateTab):
|
||||||
return
|
return
|
||||||
room = t.get_name()
|
room = JID(t.get_name()).bare
|
||||||
nick = t.get_room().own_nick
|
nick = t.get_room().own_nick
|
||||||
else:
|
else:
|
||||||
info = JID(args[0])
|
info = JID(args[0])
|
||||||
|
|
|
@ -16,6 +16,7 @@ import curses
|
||||||
from windows import g_lock
|
from windows import g_lock
|
||||||
import windows
|
import windows
|
||||||
from tabs import Tab
|
from tabs import Tab
|
||||||
|
from theming import to_curses_attr, get_theme
|
||||||
|
|
||||||
class DataFormsTab(Tab):
|
class DataFormsTab(Tab):
|
||||||
"""
|
"""
|
||||||
|
@ -85,7 +86,7 @@ class FieldInput(object):
|
||||||
"""
|
"""
|
||||||
def __init__(self, field):
|
def __init__(self, field):
|
||||||
self._field = field
|
self._field = field
|
||||||
self.color = 14
|
self.color = (14, -1)
|
||||||
|
|
||||||
def set_color(self, color):
|
def set_color(self, color):
|
||||||
self.color = color
|
self.color = color
|
||||||
|
@ -113,6 +114,27 @@ class FieldInput(object):
|
||||||
"""
|
"""
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
|
class ColoredLabel(windows.Win):
|
||||||
|
def __init__(self, text):
|
||||||
|
self.text = text
|
||||||
|
self.color = get_theme().COLOR_NORMAL_TEXT
|
||||||
|
windows.Win.__init__(self)
|
||||||
|
|
||||||
|
def resize(self, height, width, y, x):
|
||||||
|
self._resize(height, width, y, x)
|
||||||
|
|
||||||
|
def set_color(self, color):
|
||||||
|
self.color = color
|
||||||
|
self.refresh()
|
||||||
|
|
||||||
|
def refresh(self):
|
||||||
|
with g_lock:
|
||||||
|
self._win.attron(to_curses_attr(self.color))
|
||||||
|
self.addstr(0, 0, self.text)
|
||||||
|
self._win.attroff(to_curses_attr(self.color))
|
||||||
|
self._refresh()
|
||||||
|
|
||||||
|
|
||||||
class DummyInput(FieldInput, windows.Win):
|
class DummyInput(FieldInput, windows.Win):
|
||||||
"""
|
"""
|
||||||
Used for fields that do not require any input ('fixed')
|
Used for fields that do not require any input ('fixed')
|
||||||
|
@ -165,7 +187,7 @@ class BooleanWin(FieldInput, windows.Win):
|
||||||
|
|
||||||
def refresh(self):
|
def refresh(self):
|
||||||
with g_lock:
|
with g_lock:
|
||||||
self._win.attron(curses.color_pair(self.color))
|
self._win.attron(to_curses_attr(self.color))
|
||||||
self.addnstr(0, 0, ' '*(8), self.width)
|
self.addnstr(0, 0, ' '*(8), self.width)
|
||||||
self.addstr(0, 2, "%s"%self.value)
|
self.addstr(0, 2, "%s"%self.value)
|
||||||
self.addstr(0, 8, '→')
|
self.addstr(0, 8, '→')
|
||||||
|
@ -174,7 +196,7 @@ class BooleanWin(FieldInput, windows.Win):
|
||||||
self.addstr(0, 8, '')
|
self.addstr(0, 8, '')
|
||||||
else:
|
else:
|
||||||
self.addstr(0, 0, '')
|
self.addstr(0, 0, '')
|
||||||
self._win.attroff(curses.color_pair(self.color))
|
self._win.attroff(to_curses_attr(self.color))
|
||||||
self._refresh()
|
self._refresh()
|
||||||
|
|
||||||
def reply(self):
|
def reply(self):
|
||||||
|
@ -229,7 +251,7 @@ class TextMultiWin(FieldInput, windows.Win):
|
||||||
def refresh(self):
|
def refresh(self):
|
||||||
if not self.edition_input:
|
if not self.edition_input:
|
||||||
with g_lock:
|
with g_lock:
|
||||||
self._win.attron(curses.color_pair(self.color))
|
self._win.attron(to_curses_attr(self.color))
|
||||||
self.addnstr(0, 0, ' '*self.width, self.width)
|
self.addnstr(0, 0, ' '*self.width, self.width)
|
||||||
option = self.options[self.val_pos]
|
option = self.options[self.val_pos]
|
||||||
self.addstr(0, self.width//2-len(option)//2, option)
|
self.addstr(0, self.width//2-len(option)//2, option)
|
||||||
|
@ -237,7 +259,7 @@ class TextMultiWin(FieldInput, windows.Win):
|
||||||
self.addstr(0, 0, '←')
|
self.addstr(0, 0, '←')
|
||||||
if self.val_pos < len(self.options)-1:
|
if self.val_pos < len(self.options)-1:
|
||||||
self.addstr(0, self.width-1, '→')
|
self.addstr(0, self.width-1, '→')
|
||||||
self._win.attroff(curses.color_pair(self.color))
|
self._win.attroff(to_curses_attr(self.color))
|
||||||
self._refresh()
|
self._refresh()
|
||||||
else:
|
else:
|
||||||
self.edition_input.refresh()
|
self.edition_input.refresh()
|
||||||
|
@ -281,7 +303,7 @@ class ListMultiWin(FieldInput, windows.Win):
|
||||||
|
|
||||||
def refresh(self):
|
def refresh(self):
|
||||||
with g_lock:
|
with g_lock:
|
||||||
self._win.attron(curses.color_pair(self.color))
|
self._win.attron(to_curses_attr(self.color))
|
||||||
self.addnstr(0, 0, ' '*self.width, self.width)
|
self.addnstr(0, 0, ' '*self.width, self.width)
|
||||||
if self.val_pos > 0:
|
if self.val_pos > 0:
|
||||||
self.addstr(0, 0, '←')
|
self.addstr(0, 0, '←')
|
||||||
|
@ -290,7 +312,7 @@ class ListMultiWin(FieldInput, windows.Win):
|
||||||
option = self.options[self.val_pos]
|
option = self.options[self.val_pos]
|
||||||
self.addstr(0, self.width//2-len(option)//2, option[0]['label'])
|
self.addstr(0, self.width//2-len(option)//2, option[0]['label'])
|
||||||
self.addstr(0, 2, '✔' if option[1] else '☐')
|
self.addstr(0, 2, '✔' if option[1] else '☐')
|
||||||
self._win.attroff(curses.color_pair(self.color))
|
self._win.attroff(to_curses_attr(self.color))
|
||||||
self._refresh()
|
self._refresh()
|
||||||
|
|
||||||
def reply(self):
|
def reply(self):
|
||||||
|
@ -327,7 +349,7 @@ class ListSingleWin(FieldInput, windows.Win):
|
||||||
|
|
||||||
def refresh(self):
|
def refresh(self):
|
||||||
with g_lock:
|
with g_lock:
|
||||||
self._win.attron(curses.color_pair(self.color))
|
self._win.attron(to_curses_attr(self.color))
|
||||||
self.addnstr(0, 0, ' '*self.width, self.width)
|
self.addnstr(0, 0, ' '*self.width, self.width)
|
||||||
if self.val_pos > 0:
|
if self.val_pos > 0:
|
||||||
self.addstr(0, 0, '←')
|
self.addstr(0, 0, '←')
|
||||||
|
@ -335,7 +357,7 @@ class ListSingleWin(FieldInput, windows.Win):
|
||||||
self.addstr(0, self.width-1, '→')
|
self.addstr(0, self.width-1, '→')
|
||||||
option = self.options[self.val_pos]['label']
|
option = self.options[self.val_pos]['label']
|
||||||
self.addstr(0, self.width//2-len(option)//2, option)
|
self.addstr(0, self.width//2-len(option)//2, option)
|
||||||
self._win.attroff(curses.color_pair(self.color))
|
self._win.attroff(to_curses_attr(self.color))
|
||||||
self._refresh()
|
self._refresh()
|
||||||
|
|
||||||
def reply(self):
|
def reply(self):
|
||||||
|
@ -353,7 +375,7 @@ class TextSingleWin(FieldInput, windows.Input):
|
||||||
self.text = field.getValue() if isinstance(field.getValue(), str)\
|
self.text = field.getValue() if isinstance(field.getValue(), str)\
|
||||||
else ""
|
else ""
|
||||||
self.pos = len(self.text)
|
self.pos = len(self.text)
|
||||||
self.color = 14
|
self.color = (14, -1)
|
||||||
|
|
||||||
def reply(self):
|
def reply(self):
|
||||||
self._field['label'] = ''
|
self._field['label'] = ''
|
||||||
|
@ -370,15 +392,15 @@ class TextPrivateWin(TextSingleWin):
|
||||||
with g_lock:
|
with g_lock:
|
||||||
self._win.erase()
|
self._win.erase()
|
||||||
if self.color:
|
if self.color:
|
||||||
self._win.attron(curses.color_pair(self.color))
|
self._win.attron(to_curses_attr(self.color))
|
||||||
self.addstr('*'*len(self.text[self.line_pos:self.line_pos+self.width-1]))
|
self.addstr('*'*len(self.text[self.line_pos:self.line_pos+self.width-1]))
|
||||||
if self.color:
|
if self.color:
|
||||||
(y, x) = self._win.getyx()
|
(y, x) = self._win.getyx()
|
||||||
size = self.width-x
|
size = self.width-x
|
||||||
self.addnstr(' '*size, size, curses.color_pair(self.color))
|
self.addnstr(' '*size, size, to_curses_attr(self.color))
|
||||||
self.addstr(0, self.pos, '')
|
self.addstr(0, self.pos, '')
|
||||||
if self.color:
|
if self.color:
|
||||||
self._win.attroff(curses.color_pair(self.color))
|
self._win.attroff(to_curses_attr(self.color))
|
||||||
self._refresh()
|
self._refresh()
|
||||||
|
|
||||||
def get_help_message(self):
|
def get_help_message(self):
|
||||||
|
@ -447,8 +469,8 @@ class FormWin(object):
|
||||||
return
|
return
|
||||||
if self.current_input == len(self.inputs) - 1 or self.current_input >= self.height-1:
|
if self.current_input == len(self.inputs) - 1 or self.current_input >= self.height-1:
|
||||||
return
|
return
|
||||||
self.inputs[self.current_input]['label'].set_color(14)
|
self.inputs[self.current_input]['input'].set_color(get_theme().COLOR_NORMAL_TEXT)
|
||||||
self.inputs[self.current_input]['input'].set_color(14)
|
self.inputs[self.current_input]['label'].set_color(get_theme().COLOR_NORMAL_TEXT)
|
||||||
self.current_input += 1
|
self.current_input += 1
|
||||||
jump = 0
|
jump = 0
|
||||||
while self.current_input+jump != len(self.inputs) - 1 and self.inputs[self.current_input+jump]['input'].is_dummy():
|
while self.current_input+jump != len(self.inputs) - 1 and self.inputs[self.current_input+jump]['input'].is_dummy():
|
||||||
|
@ -456,16 +478,16 @@ class FormWin(object):
|
||||||
if self.inputs[self.current_input+jump]['input'].is_dummy():
|
if self.inputs[self.current_input+jump]['input'].is_dummy():
|
||||||
return
|
return
|
||||||
self.current_input += jump
|
self.current_input += jump
|
||||||
self.inputs[self.current_input]['label'].set_color(13)
|
self.inputs[self.current_input]['input'].set_color(get_theme().COLOR_SELECTED_ROW)
|
||||||
self.inputs[self.current_input]['input'].set_color(13)
|
self.inputs[self.current_input]['label'].set_color(get_theme().COLOR_SELECTED_ROW)
|
||||||
|
|
||||||
def go_to_previous_input(self):
|
def go_to_previous_input(self):
|
||||||
if not self.inputs:
|
if not self.inputs:
|
||||||
return
|
return
|
||||||
if self.current_input == 0:
|
if self.current_input == 0:
|
||||||
return
|
return
|
||||||
self.inputs[self.current_input]['label'].set_color(14)
|
self.inputs[self.current_input]['input'].set_color(get_theme().COLOR_NORMAL_TEXT)
|
||||||
self.inputs[self.current_input]['input'].set_color(14)
|
self.inputs[self.current_input]['label'].set_color(get_theme().COLOR_NORMAL_TEXT)
|
||||||
self.current_input -= 1
|
self.current_input -= 1
|
||||||
jump = 0
|
jump = 0
|
||||||
while self.current_input-jump > 0 and self.inputs[self.current_input+jump]['input'].is_dummy():
|
while self.current_input-jump > 0 and self.inputs[self.current_input+jump]['input'].is_dummy():
|
||||||
|
@ -473,8 +495,8 @@ class FormWin(object):
|
||||||
if self.inputs[self.current_input+jump]['input'].is_dummy():
|
if self.inputs[self.current_input+jump]['input'].is_dummy():
|
||||||
return
|
return
|
||||||
self.current_input -= jump
|
self.current_input -= jump
|
||||||
self.inputs[self.current_input]['label'].set_color(13)
|
self.inputs[self.current_input]['input'].set_color(get_theme().COLOR_SELECTED_ROW)
|
||||||
self.inputs[self.current_input]['input'].set_color(13)
|
self.inputs[self.current_input]['label'].set_color(get_theme().COLOR_SELECTED_ROW)
|
||||||
|
|
||||||
def on_input(self, key):
|
def on_input(self, key):
|
||||||
if not self.inputs:
|
if not self.inputs:
|
||||||
|
@ -502,10 +524,11 @@ class FormWin(object):
|
||||||
break
|
break
|
||||||
inp['label'].refresh()
|
inp['label'].refresh()
|
||||||
inp['input'].refresh()
|
inp['input'].refresh()
|
||||||
|
inp['label'].refresh()
|
||||||
if self.current_input < self.height-1:
|
if self.current_input < self.height-1:
|
||||||
self.inputs[self.current_input]['input'].set_color(13)
|
self.inputs[self.current_input]['input'].set_color(get_theme().COLOR_SELECTED_ROW)
|
||||||
self.inputs[self.current_input]['input'].refresh()
|
self.inputs[self.current_input]['input'].refresh()
|
||||||
self.inputs[self.current_input]['label'].set_color(13)
|
self.inputs[self.current_input]['label'].set_color(get_theme().COLOR_SELECTED_ROW)
|
||||||
self.inputs[self.current_input]['label'].refresh()
|
self.inputs[self.current_input]['label'].refresh()
|
||||||
|
|
||||||
def refresh_current_input(self):
|
def refresh_current_input(self):
|
||||||
|
|
49
src/tabs.py
49
src/tabs.py
|
@ -681,6 +681,7 @@ class MucTab(ChatTab):
|
||||||
"""
|
"""
|
||||||
if not self.visible:
|
if not self.visible:
|
||||||
return
|
return
|
||||||
|
self.need_resize = False
|
||||||
text_width = (self.width//10)*9
|
text_width = (self.width//10)*9
|
||||||
self.topic_win.resize(1, self.width, 0, 0)
|
self.topic_win.resize(1, self.width, 0, 0)
|
||||||
self.v_separator.resize(self.height-3, 1, 1, 9*(self.width//10))
|
self.v_separator.resize(self.height-3, 1, 1, 9*(self.width//10))
|
||||||
|
@ -799,6 +800,7 @@ class MucTab(ChatTab):
|
||||||
room.users.append(new_user)
|
room.users.append(new_user)
|
||||||
if from_nick == room.own_nick:
|
if from_nick == room.own_nick:
|
||||||
room.joined = True
|
room.joined = True
|
||||||
|
if self.core.current_tab() == self and self.core.status.show not in ('xa', 'away'):
|
||||||
self.send_chat_state('active')
|
self.send_chat_state('active')
|
||||||
new_user.color = get_theme().COLOR_OWN_NICK
|
new_user.color = get_theme().COLOR_OWN_NICK
|
||||||
room.add_message(_("\x195}Your nickname is \x193}%s") % (from_nick))
|
room.add_message(_("\x195}Your nickname is \x193}%s") % (from_nick))
|
||||||
|
@ -999,10 +1001,12 @@ class PrivateTab(ChatTab):
|
||||||
# keys
|
# keys
|
||||||
self.key_func['^I'] = self.completion
|
self.key_func['^I'] = self.completion
|
||||||
# commands
|
# commands
|
||||||
#self.commands['info'] = (self.command_info, _('Usage: /info\nInfo: Display some information about the user in the MUC: '), None)
|
self.commands['info'] = (self.command_info, _('Usage: /info\nInfo: Display some information about the user in the MUC: '), None)
|
||||||
self.commands['unquery'] = (self.command_unquery, _("Usage: /unquery\nUnquery: close the tab"), None)
|
self.commands['unquery'] = (self.command_unquery, _("Usage: /unquery\nUnquery: close the tab"), None)
|
||||||
self.commands['part'] = (self.command_unquery, _("Usage: /part\nPart: close the tab"), None)
|
self.commands['part'] = (self.command_unquery, _("Usage: /part\nPart: close the tab"), None)
|
||||||
|
self.commands['version'] = (self.command_version, _('Usage: /version\nVersion: get the software version of the current interlocutor (usually its XMPP client and Operating System)'), None)
|
||||||
self.resize()
|
self.resize()
|
||||||
|
self.parent_muc = self.core.get_tab_by_name(JID(room.name).bare, MucTab)
|
||||||
self.on = True
|
self.on = True
|
||||||
|
|
||||||
def completion(self):
|
def completion(self):
|
||||||
|
@ -1019,7 +1023,8 @@ class PrivateTab(ChatTab):
|
||||||
msg['body'] = xhtml.clean_text(line)
|
msg['body'] = xhtml.clean_text(line)
|
||||||
msg['xhtml_im'] = xhtml.poezio_colors_to_html(line)
|
msg['xhtml_im'] = xhtml.poezio_colors_to_html(line)
|
||||||
if config.get('send_chat_states', 'true') == 'true' and self.remote_wants_chatstates is not False:
|
if config.get('send_chat_states', 'true') == 'true' and self.remote_wants_chatstates is not False:
|
||||||
msg['chat_state'] = 'active'
|
needed = 'inactive' if self.core.status.show in ('xa', 'away') else 'active'
|
||||||
|
msg['chat_state'] = needed
|
||||||
msg.send()
|
msg.send()
|
||||||
self.core.add_message_to_text_buffer(self.get_room(), line, None, self.core.own_nick or self.get_room().own_nick)
|
self.core.add_message_to_text_buffer(self.get_room(), line, None, self.core.own_nick or self.get_room().own_nick)
|
||||||
logger.log_message(JID(self.get_name()).bare, self.core.own_nick, line)
|
logger.log_message(JID(self.get_name()).bare, self.core.own_nick, line)
|
||||||
|
@ -1033,9 +1038,35 @@ class PrivateTab(ChatTab):
|
||||||
"""
|
"""
|
||||||
self.core.close_tab()
|
self.core.close_tab()
|
||||||
|
|
||||||
|
def command_version(self, arg):
|
||||||
|
"""
|
||||||
|
/version
|
||||||
|
"""
|
||||||
|
def callback(res):
|
||||||
|
if not res:
|
||||||
|
return self.core.information('Could not get the software version from %s' % (jid,), 'Warning')
|
||||||
|
version = '%s is running %s version %s on %s' % (jid,
|
||||||
|
res.get('name') or _('an unknown software'),
|
||||||
|
res.get('version') or _('unknown'),
|
||||||
|
res.get('os') or _('on an unknown platform'))
|
||||||
|
self.core.information(version, 'Info')
|
||||||
|
jid = self.get_room().name
|
||||||
|
self.core.xmpp.plugin['xep_0092'].get_version(jid, callback=callback)
|
||||||
|
|
||||||
|
def command_info(self, arg):
|
||||||
|
"""
|
||||||
|
/info
|
||||||
|
"""
|
||||||
|
if arg:
|
||||||
|
self.parent_muc.command_info(arg)
|
||||||
|
else:
|
||||||
|
user = JID(self.get_room().name).resource
|
||||||
|
self.parent_muc.command_info(user)
|
||||||
|
|
||||||
def resize(self):
|
def resize(self):
|
||||||
if self.core.information_win_size >= self.height-3 or not self.visible:
|
if self.core.information_win_size >= self.height-3 or not self.visible:
|
||||||
return
|
return
|
||||||
|
self.need_resize = False
|
||||||
self.text_win.resize(self.height-3-self.core.information_win_size, self.width, 0, 0)
|
self.text_win.resize(self.height-3-self.core.information_win_size, self.width, 0, 0)
|
||||||
self.text_win.rebuild_everything(self._room)
|
self.text_win.rebuild_everything(self._room)
|
||||||
self.info_header.resize(1, self.width, self.height-3-self.core.information_win_size, 0)
|
self.info_header.resize(1, self.width, self.height-3-self.core.information_win_size, 0)
|
||||||
|
@ -1124,11 +1155,12 @@ class PrivateTab(ChatTab):
|
||||||
"""
|
"""
|
||||||
The user left the associated MUC
|
The user left the associated MUC
|
||||||
"""
|
"""
|
||||||
|
self.deactivate()
|
||||||
if not status_message:
|
if not status_message:
|
||||||
self.get_room().add_message(_('\x191}%(spec)s \x193}%(nick)s\x195} has left the room') % {'nick':from_nick.replace('"', '\\"'), 'spec':get_theme().CHAR_QUIT.replace('"', '\\"')})
|
self.get_room().add_message(_('\x191}%(spec)s \x193}%(nick)s\x195} has left the room') % {'nick':from_nick.replace('"', '\\"'), 'spec':get_theme().CHAR_QUIT.replace('"', '\\"')})
|
||||||
else:
|
else:
|
||||||
self.get_room().add_message(_('\x191}%(spec)s \x193}%(nick)s\x195} has left the room (%(status)s)"') % {'nick':from_nick.replace('"', '\\"'), 'spec':get_theme().CHAR_QUIT, 'status': status_message.replace('"', '\\"')})
|
self.get_room().add_message(_('\x191}%(spec)s \x193}%(nick)s\x195} has left the room (%(status)s)"') % {'nick':from_nick.replace('"', '\\"'), 'spec':get_theme().CHAR_QUIT, 'status': status_message.replace('"', '\\"')})
|
||||||
self.deactivate()
|
if self.core.current_tab() is self:
|
||||||
self.refresh()
|
self.refresh()
|
||||||
self.core.doupdate()
|
self.core.doupdate()
|
||||||
|
|
||||||
|
@ -1136,11 +1168,13 @@ class PrivateTab(ChatTab):
|
||||||
"""
|
"""
|
||||||
The user (or at least someone with the same nick) came back in the MUC
|
The user (or at least someone with the same nick) came back in the MUC
|
||||||
"""
|
"""
|
||||||
self.get_room().add_message('\x194}%(spec)s \x193}%(nick)s\x195} joined the room' % {'nick':nick, 'spec':get_theme().CHAR_JOIN})
|
|
||||||
self.activate()
|
self.activate()
|
||||||
|
self.get_room().add_message('\x194}%(spec)s \x193}%(nick)s\x195} joined the room' % {'nick':nick, 'spec':get_theme().CHAR_JOIN})
|
||||||
|
if self.core.current_tab() is self:
|
||||||
self.refresh()
|
self.refresh()
|
||||||
self.core.doupdate()
|
self.core.doupdate()
|
||||||
|
|
||||||
|
|
||||||
def activate(self):
|
def activate(self):
|
||||||
self.on = True
|
self.on = True
|
||||||
|
|
||||||
|
@ -1185,6 +1219,7 @@ class RosterInfoTab(Tab):
|
||||||
def resize(self):
|
def resize(self):
|
||||||
if not self.visible:
|
if not self.visible:
|
||||||
return
|
return
|
||||||
|
self.need_resize = False
|
||||||
roster_width = self.width//2
|
roster_width = self.width//2
|
||||||
info_width = self.width-roster_width-1
|
info_width = self.width-roster_width-1
|
||||||
self.v_separator.resize(self.height-2, 1, 0, roster_width)
|
self.v_separator.resize(self.height-2, 1, 0, roster_width)
|
||||||
|
@ -1527,7 +1562,8 @@ class ConversationTab(ChatTab):
|
||||||
msg['body'] = xhtml.clean_text(line)
|
msg['body'] = xhtml.clean_text(line)
|
||||||
msg['xhtml_im'] = xhtml.poezio_colors_to_html(line)
|
msg['xhtml_im'] = xhtml.poezio_colors_to_html(line)
|
||||||
if config.get('send_chat_states', 'true') == 'true' and self.remote_wants_chatstates is not False:
|
if config.get('send_chat_states', 'true') == 'true' and self.remote_wants_chatstates is not False:
|
||||||
msg['chat_state'] = 'active'
|
needed = 'inactive' if self.core.status.show in ('xa', 'away') else 'active'
|
||||||
|
msg['chat_state'] = needed
|
||||||
msg.send()
|
msg.send()
|
||||||
self.core.add_message_to_text_buffer(self.get_room(), line, None, self.core.own_nick)
|
self.core.add_message_to_text_buffer(self.get_room(), line, None, self.core.own_nick)
|
||||||
logger.log_message(JID(self.get_name()).bare, self.core.own_nick, line)
|
logger.log_message(JID(self.get_name()).bare, self.core.own_nick, line)
|
||||||
|
@ -1541,6 +1577,7 @@ class ConversationTab(ChatTab):
|
||||||
def resize(self):
|
def resize(self):
|
||||||
if self.core.information_win_size >= self.height-3 or not self.visible:
|
if self.core.information_win_size >= self.height-3 or not self.visible:
|
||||||
return
|
return
|
||||||
|
self.need_resize = False
|
||||||
self.text_win.resize(self.height-4-self.core.information_win_size, self.width, 1, 0)
|
self.text_win.resize(self.height-4-self.core.information_win_size, self.width, 1, 0)
|
||||||
self.text_win.rebuild_everything(self._room)
|
self.text_win.rebuild_everything(self._room)
|
||||||
self.upper_bar.resize(1, self.width, 0, 0)
|
self.upper_bar.resize(1, self.width, 0, 0)
|
||||||
|
@ -1658,6 +1695,7 @@ class MucListTab(Tab):
|
||||||
def resize(self):
|
def resize(self):
|
||||||
if not self.visible:
|
if not self.visible:
|
||||||
return
|
return
|
||||||
|
self.need_resize = False
|
||||||
self.upper_message.resize(1, self.width, 0, 0)
|
self.upper_message.resize(1, self.width, 0, 0)
|
||||||
column_size = {'node-part': (self.width-5)//4,
|
column_size = {'node-part': (self.width-5)//4,
|
||||||
'name': (self.width-5)//4*3,
|
'name': (self.width-5)//4*3,
|
||||||
|
@ -1792,6 +1830,7 @@ class SimpleTextTab(Tab):
|
||||||
def resize(self):
|
def resize(self):
|
||||||
if not self.visible:
|
if not self.visible:
|
||||||
return
|
return
|
||||||
|
self.need_resize = False
|
||||||
self.text_win.resize(self.height-2, self.width, 0, 0)
|
self.text_win.resize(self.height-2, self.width, 0, 0)
|
||||||
self.input.resize(1, self.width, self.height-1, 0)
|
self.input.resize(1, self.width, self.height-1, 0)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue