Like @benknoble suggested I tried to rewrite the macro using more pattern matching, at first that seemed a bit difficult. But by using a helper macro, fixing my syntax-class (so that it keeps the original identifiers in #:with to ...) and using format-id like @SamPhillips suggested, I managed to get it quite conscise and now it shows arrows properly. Here is the new version:
#lang racket
(provide define-attributes)
(require syntax/parse/define
(for-syntax racket/syntax))
(begin-for-syntax
(define-syntax-class name-mapping
#:description "name-mapping"
[pattern from:id
#:with to #'from]
[pattern (from:id)
#:with to '||] ; empty symbol
[pattern (from:id to-id:id)
#:with to #'to-id]))
;(define-attributes (l r) vec3- (x y z)) lx ly lz rx ry rz
;(define-attributes ([l]) vec3- (x y z)) x y z
;(define-attributes ([l o]) vec3- (x y z)) ox oy oz
;(define-attributes ([l l.]) vec3- (x y z)) l.x l.y l.z
;(define-attributes ([l]) vec3- (x y z [length len])) x y z len
(define-syntax-parser define-attributes
[(_ (ids:name-mapping ...+) prefix:id (attributes:name-mapping ...+))
#`(begin (define-attributes-id #,this-syntax ids prefix attributes ...) ...)])
(define-syntax-parser define-attributes-id
[(_ loc id:name-mapping prefix:id attribute:name-mapping)
#:with newid (syntax-property
(format-id #'id "~a~a" #'id.to #'attribute.to #:subs? #t)
'original-for-check-syntax #t)
#:with accessor (format-id #'loc "~a~a" #'prefix #'attribute.from #:source #'loc)
#:with expr #'(accessor id.from)
#'(define newid expr)]
[(_ loc id:name-mapping prefix:id attributes:name-mapping ...+)
#'(begin (define-attributes-id loc id prefix attributes) ...)])
;; example
(struct vec3 (x y z))
(define (x² x) (* x x))
(define (vec3-length v)
(define-attributes ([v]) vec3- (x y z))
(sqrt (+ (x² x) (x² y) (x² z))))
(define-syntax-rule (fmt x ...) (begin (displayln (~a (~a (quote x) ": " x " ") ...))))
(module+ main
(define l (vec3 3 5 7))
(define r (vec3 0 2 4))
(define-attributes (l r) vec3- (x y z)) ; lx ly lz rx ry rz
(define-attributes ([l]) vec3- (x y z)) ; x y z
(define-attributes ([l o]) vec3- (x y z)) ; ox oy oz
(define-attributes ([l l.]) vec3- (x y z)) ; l.x l.y l.z
(fmt lx ly lz rx ry rz)
(fmt x y z)
(fmt ox oy oz)
(fmt l.x l.y l.z)
(let ()
(define-attributes ([l]) vec3- (x y z [length len])) ; x y z len
(fmt x y z len)))
