(require racket/system
racket/port
racket/cmdline
- racket/string)
-
-(define (git . args) (string-split (with-output-to-string (λ () (system (string-join (cons "git" args))))) "\n"))
+ racket/function
+ racket/match
+ racket/string
+ racket/list)
+#| String helper functions |#
(define (split-prefix str)
(define components (string-split str))
(define head (car components))
- (define tail (string-join (list-tail components 1)))
+ (define tail (string-join (rest components)))
(cons head tail))
(define (file-string file) (format "\"~a\"" file))
+(define non-blank-string? (compose1 non-empty-string? string-trim))
+#| Git commands |#
+(define (git . args) (string-split (with-output-to-string (λ () (system (string-join (cons "git" args))))) "\n"))
(define (ls-files . args) (map split-prefix (git "ls-files" "-v" (string-join args))))
+(define (update-index . args) (git "update-index" (string-join args)))
+
(define (modified-files) (map cdr (ls-files "-m")))
(define (skipped-files) (map cdr (filter (λ (pair) (equal? "S" (car pair))) (ls-files))))
-(define (update-index . args) (git "update-index" (string-join args)))
(define (skip-file file) (update-index "--skip-worktree" (file-string file)))
(define (no-skip-file file) (update-index "--no-skip-worktree" (file-string file)))
(define (skip-modified) (for-each skip-file (modified-files)))
(define (no-skip-all) (for-each no-skip-file (skipped-files)))
+#| Interactive mode helper methods |#
+(define (find-numbered-list number items) (map cdr (filter (compose1 (curry equal? number) number->string car) items)))
+(define (numbered-list items) (map cons (inclusive-range 1 (length items)) items))
+(define (format-pair pair) (format "~a - ~a" (car pair) (cdr pair)))
+(define (format-numbered-list items) (map format-pair (numbered-list items)))
+
+(define (parse-input input) (regexp-match* #px"([sn])(\\d+)" input #:match-select rest))
+
+(define (interpret-input skipped-file-list modified-file-list pair)
+ (match (car pair)
+ ("s" (for-each skip-file (find-numbered-list (cadr pair) (numbered-list modified-file-list))))
+ ("n" (for-each no-skip-file (find-numbered-list (cadr pair) (numbered-list skipped-file-list))))))
+
+(define (handle-input input skipped-file-list modified-file-list)
+ (if (non-blank-string? input)
+ (for-each (curry interpret-input skipped-file-list modified-file-list) (parse-input input))
+ #f))
+
+(define (interactive-prompt skipped-file-list modified-file-list)
+ (displayln "Skipped Files:")
+ (for-each displayln (format-numbered-list skipped-file-list))
+ (displayln "Modified Files:")
+ (for-each displayln (format-numbered-list modified-file-list))
+ (displayln "Enter 's' or 'n' followed by a file number to skip or unskip a file respectively.")
+ (displayln "e.g. 's3 n12' skips the third file under Modified Files then unskips the twelfth file under Skipped Files.")
+ (displayln "Enter a blank line to quit.")
+ (display "Input: ")
+ (read-line))
+
+(define (interactive-loop)
+ (define skipped-file-list (skipped-files))
+ (define modified-file-list (modified-files))
+ (if (handle-input (interactive-prompt skipped-file-list modified-file-list) skipped-file-list modified-file-list)
+ (interactive-loop)
+ #f))
+
#| Programs |#
(define (program-display-skipped-files)
- (displayln "Skipped files:")
+ (displayln "Skipped Files:")
(for-each displayln (skipped-files)))
(define (program-skip-file file)
(skip-modified)
(program-display-skipped-files))
+(define (program-interactive)
+ (displayln "Interactive mode")
+ (interactive-loop))
+
(command-line
#:once-any
- #| (("-i" "--interactive") "Interactive mode" (interactive)) |#
+ (("-i" "--interactive") "Interactive mode" (program-interactive))
(("-l" "--list") "View skipped files" (program-display-skipped-files))
(("-s" "--skip") file "Skip single file" (program-skip-file file))
(("-n" "--no-skip") file "Unskip single file" (program-no-skip-file file))