refactor: Linus-style code quality improvements across Elisp and C modules

- Extract shared binary search from duplicate ekp--hyphenate-p/ekp--flagged-p
- Remove duplicate ekp-root-dir definition (shadowed ekp-utils.el version)
- Remove dead ekp-clear-caches from ekp-utils.el (cleared non-existent var)
- Replace hardcoded 'zsh' with shell-file-name for portability
- Deduplicate module reload: shared ekp--module-reload for Rust/C
- Add NULL guard for ekp_global in ekp_paragraph.c (crash prevention)
- Track actual thread count in pool to fix destroy joining wrong count
- Normalize line endings (CRLF→LF) in ekp-utils.el

Co-authored-by: Kinneyzhang <38454496+Kinneyzhang@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot] 2026-02-10 12:18:00 +00:00
parent ddfa26fafc
commit af855e3394
5 changed files with 398 additions and 410 deletions

View File

@ -228,12 +228,6 @@ Whitespace runs are preserved as separate boxes; CJK punctuation attaches to pre
(setq boxes (ekp--flush-trailing-spaces spaces boxes))
(vconcat (nreverse boxes))))))
(defun ekp-clear-caches ()
(interactive)
(setq ekp-caches
(make-hash-table
:test 'equal :size 100 :rehash-size 1.5 :weakness nil)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun ekp-start-process-with-callback
@ -257,12 +251,18 @@ Whitespace runs are preserved as separate boxes; CJK punctuation attaches to pre
,buffer-name))))
process))
(defun ekp-rust-module-reload (module)
(defun ekp--module-reload (module)
"Load MODULE from a temp copy to allow rebuilding."
(let ((tmpfile (make-temp-file
(file-name-nondirectory module))))
(copy-file module tmpfile t)
(module-load tmpfile)))
;;; Rust Module Support (currently unused — ekp_rust/ directory does not exist)
(defun ekp-rust-module-reload (module)
(ekp--module-reload module))
(defun ekp-module-dir ()
(when-let ((root-dir (ekp-root-dir)))
(expand-file-name "ekp_rust" root-dir)))
@ -279,7 +279,7 @@ Whitespace runs are preserved as separate boxes; CJK punctuation attaches to pre
(if (executable-find "cargo")
(let ((file (ekp-module-file)))
(if file
(ekp-rust-module-reload file)
(ekp--module-reload file)
(ekp-module-build)))
(error "Please install cargo and add it to executable path!")))
@ -293,10 +293,10 @@ Whitespace runs are preserved as separate boxes; CJK punctuation attaches to pre
((eq system-type 'windows-nt)
`("cmd.exe" "/c" ,(format "cd %s && cargo build -r"
(ekp-module-dir))))
(t `("zsh" "-c" ,(format "cd %s && cargo build -r"
(t `(,shell-file-name "-c" ,(format "cd %s && cargo build -r"
(ekp-module-dir)))))
(lambda (proc buffer)
(ekp-rust-module-reload (ekp-module-file))
(ekp--module-reload (ekp-module-file))
(message "ekp rust module reload success!")))
(error "Please install cargo and add it to executable path!")))
@ -322,12 +322,8 @@ Whitespace runs are preserved as separate boxes; CJK punctuation attaches to pre
(t "ekp.so"))))
(expand-file-name filename module-dir)))
(defun ekp-c-module-reload (module)
"Load MODULE from a temp copy to allow rebuilding."
(let ((tmpfile (make-temp-file
(file-name-nondirectory module))))
(copy-file module tmpfile t)
(module-load tmpfile)))
(defalias 'ekp-c-module-reload #'ekp--module-reload
"Load MODULE from a temp copy to allow rebuilding.")
(defun ekp-c-module-load ()
"Load EKP C module if available."
@ -368,7 +364,7 @@ Whitespace runs are preserved as separate boxes; CJK punctuation attaches to pre
(cond
((eq system-type 'windows-nt)
`("cmd.exe" "/c" ,(format "cd %s && make" module-dir)))
(t `("zsh" "-c" ,(format "cd %s && make" module-dir))))
(t `(,shell-file-name "-c" ,(format "cd %s && make" module-dir))))
(lambda (proc buffer)
(ekp-c-module-load)
(message "ekp C module build success!")))

42
ekp.el
View File

@ -124,11 +124,7 @@ Used for explicit line breaks in poetry, code blocks, etc.")
"Internal flag for parameter initialization.")
;;;; Initialization
(defun ekp-root-dir ()
"Return directory containing ekp.el."
(when ekp--load-file
(file-name-directory ekp--load-file)))
;; ekp-root-dir is provided by ekp-utils.el
(defun ekp--load-dicts ()
"Load hyphenation dictionaries."
@ -530,35 +526,25 @@ Returns (:badness NUM :fitness NUM :gaps LIST :adjustment NUM :flexibility NUM).
:adjustment adjustment
:flexibility flexibility)))
(defun ekp--hyphenate-p (hyphen-positions n)
"Return non-nil if position N ends with hyphenation.
HYPHEN-POSITIONS is a sorted vector of indices where hyphenation can occur.
Uses binary search for O(log n) lookup instead of O(n) linear search."
(and hyphen-positions
(> (length hyphen-positions) 0)
(let ((lo 0)
(hi (1- (length hyphen-positions))))
(while (< lo hi)
(let ((mid (/ (+ lo hi) 2)))
(if (< (aref hyphen-positions mid) n)
(setq lo (1+ mid))
(setq hi mid))))
(= (aref hyphen-positions lo) n))))
(defun ekp--flagged-p (flagged-positions n)
"Return non-nil if position N is a flagged (forced) break.
FLAGGED-POSITIONS is a sorted vector of indices where forced breaks occur.
(defun ekp--sorted-vector-member-p (vec n)
"Return non-nil if N exists in sorted vector VEC.
Uses binary search for O(log n) lookup."
(and flagged-positions
(> (length flagged-positions) 0)
(and vec
(> (length vec) 0)
(let ((lo 0)
(hi (1- (length flagged-positions))))
(hi (1- (length vec))))
(while (< lo hi)
(let ((mid (/ (+ lo hi) 2)))
(if (< (aref flagged-positions mid) n)
(if (< (aref vec mid) n)
(setq lo (1+ mid))
(setq hi mid))))
(= (aref flagged-positions lo) n))))
(= (aref vec lo) n))))
(defalias 'ekp--hyphenate-p #'ekp--sorted-vector-member-p
"Return non-nil if position N ends with hyphenation.")
(defalias 'ekp--flagged-p #'ekp--sorted-vector-member-p
"Return non-nil if position N is a flagged (forced) break.")
;;;; Dynamic Programming Line Breaking

View File

@ -155,6 +155,7 @@ typedef struct {
*/
typedef struct {
pthread_t threads[EKP_THREAD_POOL_SIZE];
size_t thread_count;
pthread_mutex_t queue_lock;
pthread_cond_t queue_cond;
pthread_cond_t done_cond;

View File

@ -311,6 +311,11 @@ ekp_paragraph_t *ekp_para_create(const char *text, size_t len,
return NULL;
}
if (!ekp_global) {
ekp_para_destroy(p);
return NULL;
}
ekp_spacing_t *sp = &ekp_global->spacing;
for (size_t i = 0; i < final_count; i++) {

View File

@ -92,6 +92,7 @@ ekp_thread_pool_t *ekp_pool_create(size_t num_threads)
}
}
pool->thread_count = num_threads;
return pool;
}
@ -105,8 +106,7 @@ void ekp_pool_destroy(ekp_thread_pool_t *pool)
pthread_cond_broadcast(&pool->queue_cond);
pthread_mutex_unlock(&pool->queue_lock);
for (size_t i = 0; i < EKP_THREAD_POOL_SIZE; i++) {
if (pool->threads[i])
for (size_t i = 0; i < pool->thread_count; i++) {
pthread_join(pool->threads[i], NULL);
}