Weird edge cases for returned labels

I was examining what happens when I return different labels from a plug-in.

Select less than a second in the middle of a track of several seconds, and observe the behavior of these:

(list (list 1 2 “”)) – good label out of bounds of the selection to the right, makes sense
(list (list 2 1 “”)) – weird backwards label is produced with two endpoints and zero extent at its right endpoint!
(list (list -2 -1 “”)) – good label out of bounds to the left, makes sense
(list (list -1 -2 “”)) – weird label left of selection

Shouldn’t you be stopped from making the weird labels? Should Audacity either turn them right side around, or make an error dialog and make no labels?

On the other hand it is good that the out-of-bounds cases are handled reasonably and symmetrically. I make sometimes want to make a label endpoint just a half-sample before or after the selection.

Nyquist is a programming language. If you write incorrect code then you should expect incorrect results. It is not Audacity’s task to protect against every possible user error.

How about something like this:

(defun validate-labels (labels &AUX (validated ()))
  (when (not (listp labels))
    (error "Not a list" labels))
  (dotimes (i (length labels))
    (setf element (nth i labels))
      ((not (listp element))
        (error (format nil "element #~a is not a list" i)
               (nth i labels)))
      ((or (< (length element) 2)(> (length element) 3))
        (error "Labels must have 2 or 3 elements"
               (nth i labels)))
      ((and (= (length element) 2)
            (or (not (numberp (first element)))
                (not (stringp (second element)))))
        (error "Invalid label" (nth i labels)))
      ((and (= (length element) 3)
            (or (not (numberp (first element)))
                (not (numberp (second element)))
                (not (stringp (third element)))))
        (error "Invalid label" (nth i labels)))
      ((and (= (length element) 3)
            (< (second element)(first element)))
        (setf element 
          (list (second element)(first element)(third element)))))
    (push element validated))
  (reverse validated))