[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Nmh-workers] showing the n messages 'around' a particular message

From: Robert Elz
Subject: Re: [Nmh-workers] showing the n messages 'around' a particular message
Date: Wed, 18 Jan 2006 20:44:42 +0700

    Date:        Tue, 17 Jan 2006 22:36:44 +0000
    From:        address@hidden
    Message-ID:  <address@hidden>

  | A friend was trying to sort out a suitable shell alias/function for
  | doing a scan of the N messages 'around' the current one,

Try the following, which I think is approximately what you're looking
for (without a drop of awk in sight, much less gawk)

Except ...
  | and you don't give an error message if cur is
  | off the end of the folder or off the start or points to a message
  | you've just deleted.

If there's no "cur" message (and you don't specify which message
should go in the approximate middle) then I have no idea what should
get put there.   I suspect you want the message in the middle to be
a message near where cur used to be, but I'm not sure that makes
MH sense (feel free to correct this oversight).

Usage is

        xxx [any non message designator scan args] [-N] [A:[[-]N]]

Where: "xxx" is whatever you call this thing (I hate inventing names)

"N" (either way you specify it) is the number of scan lines you want -
provided there are at least that many messages in the folder of course,
if there are less messages, all you can get is what exists.  N defaults to 20.

"A" is a message designator - either a message number, or "cur" or
"prev" or "next" (I didn't bother with "first" or "last" - they don't
make sense here, just use "scan" if you'd want to use those).  Sequence
names don't work.   Default is "cur".

As usual with MH commands, arg order doesn't matter (ie: you can
intermix the scan args with the couple this script interprets, in any
order that you like) - except of course, as with all MH commands, later
args override earlier ones.

Naturally you can put an entry in your MH profile for this script, just
like you would for any other MH command.   The most likely uses of this
would be to specify your preferred default for N, or perhaps to select
a different scan format than the normal one you use with "scan", but
anything's possible.

The stuff that deals with "next" and "prev" is not very nice - to
start with, they mean the same as they do in "show", whereas here it
would probably be better to mean "the N scan lines after (or before)
the last time this command was run", but do do that, this script would
need to keep state, and that is too much effort.

There are a couple of odd corner cases that aren't handled sanely
(one is where there are many "vacant" message numbers before the
message that's to be put in the middle - output still appears, but
it probably isn't what you really want).

This assumes a Bourne (type) shell from at least the late 20th
century (though it would be possible to switch back to original
Bourne shell at some cost of speed and notational clarity).


#! /bin/sh

# MH scan listing, with selected message (approximately) centred

# Usage: $0 [non-message-scan-args] [-N] [msg:[[-]N]]

N=20            # default number of scan lines

set -- $( mhparam "${CMD}" ) "$@"       # extract args from MH profile

# Args for internal uses of scan, not used for final output
SC_ARGS="-format %(msg) -noheader -noclear -width 20"

AC="$#"; I=0; Z=''
while [ ${I} -lt ${AC} ]
        I=$(( ${I} + 1 ))


        # handle extra arg required by an earlier one
        test -n "${Z}" && {
                set -- "$@" "${X}"

        case "${X}" in

        cur)            ;;
        cur:[0-9]*)     N="${X#cur:}" ;;
        cur:-[0-9]*)    N="${X#cur:-}" ;;

        next)           CUR=NEXT ;;
        next:[0-9]*)    CUR=NEXT; N="${X#next:}" ;;
        next:-[0-9]*)   CUR=NEXT; N="${X#next:-}" ;;

        prev)           CUR=PREV;;
        prev:[0-9]*)    CUR=PREV; N="${X#prev:}" ;;
        prev:-[0-9]*)   CUR=PREV; N="${X#prev:-}" ;;

        all)            N=1000000;;

        [A-Za-z]*)      echo "Sequences don't work here" >&2; exit 1;;

        -[0-9]*)        N="${X#-}";;
        [0-9]*:[0-9]*)  CUR="${X%:*}"; N="${X#*:}";;
        [0-9]*:-[0-9]*) CUR="${X%:*}"; N="${X#*:-}";;
        [0-9]*)         CUR="${X}";;

        #       -f* covers -file, -form and -format ...
        -f*)            set -- "$@" "${X}"; Z=Z;;
        -width)         set -- "$@" "${X}"; Z=Z;;

        *)              set -- "$@" "${X}";;


case "${CUR}" in
NEXT)   CUR=$( scan "$@" ${SC_ARGS} next ) || exit 1 ;;
PREV)   CUR=$( scan "$@" ${SC_ARGS} prev ) || exit 1 ;;

if test -n "${CUR}" || CUR=$( scan "$@" ${SC_ARGS} cur )
        FIRST=$( scan "$@" ${SC_ARGS} first ) || exit 1
        LAST=$( scan "$@" ${SC_ARGS} last ) || exit 1

        if [ $(( ${LAST} - ${FIRST} )) -lt ${N} ]
                # FOlder cannot contain N messages, list everything
                exec scan "$@"

        elif [ $(( ${CUR} - ${FIRST} )) -lt $(( (${N} + 1) / 2 )) ]
                # Start would be before beginning, start at start instead
                exec scan "$@" "${FIRST}:${N}"

        elif [ $(( ${LAST} - ${CUR} )) -lt $(( (${N} + 1) / 2 )) ]
                # End would be after last, go backwards from final message
                exec scan "$@" "${LAST}:-${N}"
                # This is where it gets a bit trickier...

                START="$(( ${CUR} - ${N} / 2 ))"
                if [ $( scan "$@" "${START}:${N}" ${SC_ARGS} |
                                                        wc -l ) -lt "${N}" ]
                        # Going forwards we get less than N lines
                        # so, list backwards instead, we might get more

                        LAST=$( scan "$@" "${START}:${N}" ${SC_ARGS} | tail -1 )
                        exec scan "$@" "${LAST}:-${N}"
                        # List forwards starting N/2 message numbers
                        # before the middle message - this isn't really
                        # correct, N/2 message number slots might contain
                        # no messages at all...

                        exec scan "$@" "${START}:${N}"

reply via email to

[Prev in Thread] Current Thread [Next in Thread]