;;This addition provides the capability of displaying a list. ;;There is only one list-item per line - if the item is too long for one ;;single line it's symbolic representation is seperated into more ;;than one lines. ;;The user can scroll up and down in the list and he can select the items ;;and later paste this newly-created list into the upper buffer. ;;Result-Object-Data-Type (define-record-type browse-list-res-obj browse-list-res-obj (make-browse-list-res-obj pos-y pos-x line col-in-line list result-text width marked-items marked-pos c-x-pressed) browse-list-res-obj? (pos-y browse-list-res-obj-pos-y) (pos-x browse-list-res-obj-pos-x) (line browse-list-res-obj-line) (col-in-line browse-list-res-obj-col-in-line) (list browse-list-res-obj-file-list) (result-text browse-list-res-obj-result-text) (width browse-list-res-obj-width) (marked-items browse-list-res-obj-marked-items) (marked-pos browse-list-res-obj-marked-pos) (c-x-pressed browse-list-res-obj-c-x-pressed)) ;;The layout-function ;;All lines are seperated (define layout-result-browse-list (lambda (lst width) (let loop ((pos-list 0) (buffer '())) (if (= pos-list (length lst)) buffer (loop (+ pos-list 1) (append buffer (seperated-line (list-ref lst pos-list) width))))))) ;;seperate one line -> return a list of the single lines (define seperated-line (lambda (el width) (let loop ((old el) (new '())) (if (<= (string-length old) 0) new (if (>= (string-length old) width) (let* ((old-cut (substring old width (string-length old))) (new-app (string-append " " (substring old 0 width)))) (loop old-cut (append new (list new-app)))) (append new (list (string-append " " old)))))))) ;;compute where the Cursor has to be put. ;;The cursor is always located in the last line of one item of the list (define compute-pos-y (lambda (pos lst width) (let* ((before-pos (sublist lst 0 pos)) (seperated-before (layout-result-browse-list before-pos width)) (pos-before (length seperated-before))) pos-before))) ;;Find out which lines of the buffer are to highlight. ;;Only those lines are highlighted, which contain the active item. (define get-highlighted-browse-list (lambda (line lst pos-y width) (let* ((act-line (list-ref lst (- line 1))) (seperated (seperated-line act-line width)) (length-seperated (length seperated)) (first-pos (- pos-y length-seperated))) (let loop ((count 1) (res '())) (if (> count length-seperated) res (loop (+ count 1) (append res (list (+ count first-pos))))))))) ;;find out which lines are to be marked. Lines are marked if they have ;;recently been selected (define get-marked-pos-browse (lambda (marked lst width) (let loop ((m marked) (new '())) (if (null? m) new (let* ((pos (car m))) (loop (cdr m) (append (get-marked-browse-list pos lst width) new ))))))) (define get-marked-browse-list (lambda (pos lst width) (let* ((act-line (list-ref lst (- pos 1))) (seperated (seperated-line act-line width)) (length-seperated (length seperated)) (before-pos (sublist lst 0 pos)) (seperated-before (layout-result-browse-list before-pos width)) (length-before (- (length seperated-before) length-seperated))) (let loop ((res '()) (count 1)) (if (> count length-seperated) res (loop (cons (+ length-before count) res) (+ count 1))))))) ;;Receiving-Function, that answers to incomming messages and changes state ;;of the passed "browse-list-res-obj" (define browse-list-receiver (lambda (message) (cond ((next-command-message? message) (let* ((command (next-command-string message)) (parameters (next-command-message-parameters message)) (result #f) (width (next-command-message-width message))) (if (< (length parameters) 1) (begin (set! result (list "forgot parameter?")) (let* ((text (layout-result-standard "forgot parameters?" result width)) (browse-obj (make-browse-list-res-obj 1 1 1 1 result text width '() '() #f))) browse-obj)) (let ((lst (list-ref parameters 0))) (if (not (null? lst)) (let* ((result-string (map exp->string lst)) (text (layout-result-browse-list result-string (- width 1))) (sep-line-1 (seperated-line (exp->string (list-ref lst 0)) width)) (pos-y (length sep-line-1)) (browse-obj (make-browse-list-res-obj pos-y 1 1 1 lst text width '() '() #f))) browse-obj) (let ((browse-obj (make-browse-list-res-obj 1 1 1 1 '("") '("") width '() '() #f))) browse-obj)))))) ((print-message? message) (let* ((model (message-result-object message)) (pos-y (browse-list-res-obj-pos-y model)) (pos-x (browse-list-res-obj-pos-x model)) (text (browse-list-res-obj-result-text model)) (line (browse-list-res-obj-line model)) (lst (map exp->string (browse-list-res-obj-file-list model))) (width (browse-list-res-obj-width model)) (marked (browse-list-res-obj-marked-items model)) (marked-pos (browse-list-res-obj-marked-pos model)) (real-marked-pos (get-marked-pos-browse marked-pos lst width)) (highlighted (get-highlighted-browse-list line lst pos-y width))) (make-print-object pos-y pos-x text highlighted real-marked-pos))) ((key-pressed-message? message) (let* ((model (message-result-object message)) (key (key-pressed-message-key message)) (c-x-pressed (browse-list-res-obj-c-x-pressed model))) (if c-x-pressed (cond ;;Ctrl+x s ->selection ((= key 115) (let* ((marked-items (browse-list-res-obj-marked-items model)) (actual-pos (browse-list-res-obj-line model)) (all-items (browse-list-res-obj-file-list model))) (if (< actual-pos 1) model (let* ((actual-item (list-ref all-items (- actual-pos 1)))) (begin (if (member actual-item marked-items) model (let* ((new-marked-items (append marked-items (list actual-item))) (new-marked-pos (append (list actual-pos) (browse-list-res-obj-marked-pos model))) (new-model (make-browse-list-res-obj (browse-list-res-obj-pos-y model) (browse-list-res-obj-pos-x model) (browse-list-res-obj-line model) (browse-list-res-obj-col-in-line model) (browse-list-res-obj-file-list model) (browse-list-res-obj-result-text model) (browse-list-res-obj-width model) new-marked-items new-marked-pos #f))) new-model))))))) ;;Ctrl+x u -> unselect ((= key 117) (let* ((marked-items (browse-list-res-obj-marked-items model)) (marked-pos (browse-list-res-obj-marked-pos model)) (actual-pos (browse-list-res-obj-line model)) (all-items (browse-list-res-obj-file-list model))) (if (< actual-pos 1) model (let* ((actual-item (list-ref all-items (- actual-pos 1))) (rest (member actual-item marked-items)) (rest-pos (member actual-pos marked-pos))) (if (not rest) model (let* ((after-item (length rest)) (after-marked (length rest-pos)) (all-items (length marked-items)) (all-marked (length marked-pos)) (before-item (sublist marked-items 0 (- all-items after-item ))) (before-marked (sublist marked-pos 0 (- all-marked after-marked))) (new-marked-items (append before-item (list-tail rest 1))) (new-marked-pos (append before-marked (list-tail rest-pos 1))) (new-model (make-browse-list-res-obj (browse-list-res-obj-pos-y model) (browse-list-res-obj-pos-x model) (browse-list-res-obj-line model) (browse-list-res-obj-col-in-line model) (browse-list-res-obj-file-list model) (browse-list-res-obj-result-text model) (browse-list-res-obj-width model) new-marked-items new-marked-pos #f))) new-model)))))) (else (make-browse-list-res-obj (browse-list-res-obj-pos-y model) (browse-list-res-obj-pos-x model) (browse-list-res-obj-line model) (browse-list-res-obj-col-in-line model) (browse-list-res-obj-file-list model) (browse-list-res-obj-result-text model) (browse-list-res-obj-width model) (browse-list-res-obj-marked-items model) (browse-list-res-obj-marked-pos model) #f))) (cond ;;ctrl+x ((= key 24) (make-browse-list-res-obj (browse-list-res-obj-pos-y model) (browse-list-res-obj-pos-x model) (browse-list-res-obj-line model) (browse-list-res-obj-col-in-line model) (browse-list-res-obj-file-list model) (browse-list-res-obj-result-text model) (browse-list-res-obj-width model) (browse-list-res-obj-marked-items model) (browse-list-res-obj-marked-pos model) #t)) ((= key key-up) (let ((line (browse-list-res-obj-line model)) (lst (map exp->string (browse-list-res-obj-file-list model))) (width (browse-list-res-obj-width model))) (if (<= line 1) model (let* ((new-line (- line 1)) (pos-y (compute-pos-y new-line lst width))) (make-browse-list-res-obj pos-y 1 new-line 1 (browse-list-res-obj-file-list model) (browse-list-res-obj-result-text model) (browse-list-res-obj-width model) (browse-list-res-obj-marked-items model) (browse-list-res-obj-marked-pos model) #f))))) ((= key key-down) (let ((line (browse-list-res-obj-line model)) (lst (map exp->string (browse-list-res-obj-file-list model))) (width (browse-list-res-obj-width model))) (if (>= line (length lst)) model (let* ((new-line (+ line 1)) (pos-y (compute-pos-y new-line lst width))) (make-browse-list-res-obj pos-y 1 new-line 1 (browse-list-res-obj-file-list model) (browse-list-res-obj-result-text model) (browse-list-res-obj-width model) (browse-list-res-obj-marked-items model) (browse-list-res-obj-marked-pos model) #f))))) (else model))))) ((selection-message? message) (let* ((model (message-result-object message)) (marked-items (browse-list-res-obj-marked-items model))) (string-append "'" (exp->string marked-items)))) ))) (register-plugin! (make-plugin "browse-list" browse-list-receiver))