author | Alberto Bertogli
<albertogli@telpin.com.ar> 2005-04-09 18:44:12 UTC |
committer | Alberto Bertogli
<albertogli@telpin.com.ar> 2005-04-09 18:44:12 UTC |
parent | c75db00523331b0ba114853655445eda3f197480 |
msn | +200 | -60 |
diff --git a/msn b/msn index 1070f80..9e64de3 100644 --- a/msn +++ b/msn @@ -115,6 +115,13 @@ color_classes = { c = color_classes['default']() +# command list for tab-completion purposes +command_list = [ 'a', 'add', 'block', 'close', 'color', 'config', 'del', 'e', + 'ee', 'eg', 'g', 'gadd', 'gdel', 'green', 'h', 'help', 'info', + 'invite', 'lignore', 'luignore', 'm', 'nick', 'privacy', 'q', 'r', + 'ren', 'status', 'unblock', 'w', 'wr', 'ww' ] + + # # different useful prints # @@ -344,31 +351,70 @@ def email2nick(email): else: return None -def matchemail(begin): +def findemailnick(email, begin): + """Check if the email/nick of the given user begins with the given + beginning. Returns 1 if it matches the nick, or 2 if it matches the + email.""" + if m.users[email].nick.find(begin) == 0: + return 1 + elif email.find(begin) == 0: + return 2 + return 0 + +# global variable for matchemail() +start_from = 0 +def matchemail(begin, only_online = 0, start = 0): """"Returns a matching email/nick for the given beginning; it avoids - nicks with spaces""" - l = len(begin) - # first try the ones with sbd - for email in m.users.keys(): - if not m.users[email].sbd: - continue - nick = m.users[email].nick - if ' ' in nick: - nick = email - if len(nick) >= l and nick[0:l] == begin: - return nick - # then the nicks - for email in m.users.keys(): - nick = m.users[email].nick - if ' ' in nick: - continue - if len(nick) >= l and nick[0:l] == begin: - return nick - # and finally the emails - for email in m.users.keys(): - if len(email) >= l and email[0:l] == begin: - return email - return None + beginnings with spaces. If only_online is equal to 1 searchs only for + not offline users or users with an sbd. If start=1 it iterates the + last match and do a cyclical search.""" + + global start_from + + if ' ' in begin: + return None + + emails = m.users.keys() + + if start_from >= len(emails): + # the list has changed while iterating, reset + start_from = 0 + + if start: + pos = start_from + 1 + else: + pos = 0 + + found = 0 + while not found: + # we made a complete loop without matches + if start and pos == start_from: + break + elif pos == len(emails) - 1: + break + + #msnlib.debug("l: %d %s\n" % (pos, emails[pos])) + current = emails[pos] + if only_online and m.users[current].status == 'FLN': + pos = (pos + 1) % len(emails) + continue + if findemailnick(emails[pos], begin): + found = 1 + break + pos = (pos + 1) % len(emails) + + start_from = pos + 1 % len(emails) + + if found: + if findemailnick(emails[pos], begin) == 1: + # return the nick + return email2nick(emails[pos]) + else: + return emails[pos] + else: + start_from = 0 + return None + def gname2gid(gname): "Returns a group name according to the given group id" @@ -506,6 +552,20 @@ screenwidth = winsize[1] # input buffer, where all the characters written by the user are stored in inbuf = '' +# vars to control the tabs completions: +# match of commands +matchc_last = 0 +matchc_status = 0 +matchc_root = '' +# match of last send/received +matchl_status = 0 +# match of m command +matchm_status = 0 +matchm_root = '' +# match of others arguments +matchp_status = 0 +matchp_root = '' + # input history buffer, to store previous commands. # we use a list [buffer, pointer] to avoid namespace pollution inbuf_history = [[], -1] @@ -526,7 +586,30 @@ def stdin_read(): in_esc = 0 input = sys.stdin.read() + + global matchc_last + global matchc_status + global matchc_root + global matchl_status + global matchm_status + global matchm_root + global matchp_status + global matchp_root + for char in input: + # decrease the flag of the tab completion of commands + if matchc_status != 0: + matchc_status = matchc_status - 1 + # decrease the flag of the last received/last send completion + elif matchl_status != 0: + matchl_status = matchl_status - 1 + # decrease the flag of the m completion + elif matchm_status != 0: + matchm_status = matchm_status - 1 + # decrease the flag of the other arguments completion + elif matchp_status != 0: + matchp_status = matchp_status - 1 + if char == '\r': # replace \r with \n, so we handle mac keyboard input # properly (it breaks \r\n tho, but nobody uses it) @@ -538,6 +621,7 @@ def stdin_read(): del(inbuf_history[0][0]) inbuf_history[0].append(inbuf[:-1]) inbuf_history[1] = len(inbuf_history[0]) - 1 # moves the pointer + start_from = 0 # reset tab completion safe_write(char) tmpbuf = inbuf @@ -555,10 +639,14 @@ def stdin_read(): redraw_cli() elif char == '\t': # tab + p = inbuf.split() + # we do a basic cycling between the last received and # last sent; first we build the two strings and then # we see which one applies according to some messy # logic + # FIXME: it fails if we haven't in our contact list + # the person with we are talking if email2nick(last_received): nick = email2nick(last_received) if ' ' in nick: @@ -574,52 +662,104 @@ def stdin_read(): mtolsent = 'm ' + nick + ' ' else: mtolsent = None - + + # in an empty buffer we fill with the last received or + # the last sent if len(inbuf) == 1: if mtolsent: inbuf = mtolsent + matchl_status = 2 elif mtolrecv: inbuf = mtolrecv + matchl_status = 2 else: inbuf = inbuf[:-1] beep() + + # if in the last cycle we have replaced with + # mtolsent or mtolrecv we try to fill ciclical + elif mtolsent and mtolrecv and matchl_status == 1: + if inbuf.strip() == mtolrecv.strip(): + inbuf = mtolsent + matchl_status = 2 + else: + inbuf = mtolrecv + matchl_status = 2 + + # temporarily if not mtolsent or mtolrecv we beep + # FIXME it do nothing if there's only mtolrecv and + # it changes between two tabs + elif matchl_status == 1: + # it avoids that in the next iteration the + # empty buffer completion will be taked for + # an m completion + matchl_status = 2 + inbuf = inbuf[:-1] + beep() + + # we have something that is neither mtolsent or + # mtolrecv, if is the m command we try to find a + # matching email/nick + elif p[0] == 'm' and len(p) == 2: + begin = p[1] + if matchm_status == 1: + begin = matchm_root + + # we try to match with onlines contacts + # and contacts with sbd + email = matchemail(begin, 1, matchm_status) + if not email: + inbuf = inbuf[:-1] + beep() + else: + matchm_root = begin + matchm_status = 2 + inbuf = 'm ' + email + ' ' + + # if there's an only word buffer we try to match + # with one of the commands + elif len(p) == 1: + # if it's the 2nd tab we build a ciclical + # matching; if not, we remember the last match + if matchc_status == 1: + p[0] = matchc_root + matchc_last = matchc_last + 1 + + found = 1 + while found or matchc_last != len(command_list): + if matchc_last == len(command_list): + matchc_last = 0 + found = 0 + break + elif command_list[matchc_last].find(p[0]) == 0: + matchc_status = 2 + matchc_root = p[0] + break + matchc_last = matchc_last + 1 + if matchc_last == len(command_list): + inbuf = inbuf[:-1] + beep() + else: + inbuf = command_list[matchc_last] + ' ' + else: - # if we have mtolsent, replace with mtolrecv - # (if possible, otherwise beep) - if mtolsent and inbuf.strip() == mtolsent.strip(): - if mtolrecv: - inbuf = mtolrecv - else: - inbuf = inbuf[:-1] - beep() - # the opposite case - elif mtolrecv and inbuf.strip() == mtolrecv.strip(): - if mtolsent: - inbuf = mtolsent - else: - inbuf = inbuf[:-1] - beep() - # we have something that is neither mtolsent or - # mtolrecv, we try to find a matching - # email/nick + pn = p[len(p) - 1] + if matchp_status == 1: + pn = matchp_root + + # we try to match with all of contacts + email = matchemail(pn, 0, matchp_status) + if not email: + inbuf = inbuf[:-1] + beep() else: - p = inbuf.split() - if len(p) < 2: - # space + TAB or equivalent, - # just beep and ignore it - inbuf = inbuf[:-1] - beep() - elif p[0] != 'm' or len(p) != 2: - inbuf = inbuf[:-1] - beep() - else: - begin = p[1] - email = matchemail(begin) - if not email: - inbuf = inbuf[:-1] - beep() - else: - inbuf = 'm ' + email + ' ' + matchp_root = pn + matchp_status = 2 + p[len(p) -1] = email + inbuf = '' + for pi in p: + inbuf = inbuf + pi + ' ' + redraw_cli() elif ord(char) == 4: # EOT