Skip to content

Instantly share code, notes, and snippets.

@tsuu32
Created February 13, 2020 19:32
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tsuu32/1876b638af9ed37052af1e6da346ad77 to your computer and use it in GitHub Desktop.
Save tsuu32/1876b638af9ed37052af1e6da346ad77 to your computer and use it in GitHub Desktop.
From dacd2d63122622ddb967ad8bca46c158bcbfb85c Mon Sep 17 00:00:00 2001
From: Masahiro Nakamura <tsuucat@icloud.com>
Date: Fri, 14 Feb 2020 04:29:34 +0900
Subject: [PATCH] marked text face & Isearch patch
---
lisp/isearch.el | 3 +--
lisp/term/ns-win.el | 43 ++++++++++++++++++++++++++++++++++---------
src/keyboard.c | 7 ++++---
src/nsterm.m | 21 +++++++++++++++++++++
4 files changed, 60 insertions(+), 14 deletions(-)
diff --git a/lisp/isearch.el b/lisp/isearch.el
index ddf9190..c570db3 100644
--- a/lisp/isearch.el
+++ b/lisp/isearch.el
@@ -1306,8 +1306,7 @@ isearch-update
(if (and (null unread-command-events)
(null executing-kbd-macro))
(progn
- (if (not (input-pending-p))
- (funcall (or isearch-message-function #'isearch-message)))
+ (funcall (or isearch-message-function #'isearch-message))
(if (and isearch-slow-terminal-mode
(not (or isearch-small-window
(pos-visible-in-window-group-p))))
diff --git a/lisp/term/ns-win.el b/lisp/term/ns-win.el
index 6acf6cd..b4ee9e4 100644
--- a/lisp/term/ns-win.el
+++ b/lisp/term/ns-win.el
@@ -273,6 +273,16 @@ ns-working-text-face
"Face used to highlight working text during compose sequence insert."
:group 'ns)
+(defface ns-marked-text-face
+ '((t :inherit highlight))
+ "Face used to highlight marked text during compose sequence insert."
+ :group 'ns)
+
+(defface ns-unmarked-text-face
+ '((t :underline t))
+ "Face used to highlight marked text during compose sequence insert."
+ :group 'ns)
+
(defvar ns-working-overlay nil
"Overlay used to highlight working text during compose sequence insert.
When text is in th echo area, this just stores the length of the working text.")
@@ -300,25 +310,35 @@ ns-in-echo-area
;; always returns nil for some reason. If this WASN'T the case, we could
;; map this to [ns-insert-working-text] and eliminate Fevals in nsterm.m.
;; These functions test whether in echo area and delegate accordingly.
-(defun ns-put-working-text ()
- (interactive)
- (if (ns-in-echo-area) (ns-echo-working-text) (ns-insert-working-text)))
+(defun ns-put-working-text (event)
+ (interactive "e")
+ (let ((pos (nth 1 event))
+ (len (nth 2 event)))
+ (if (ns-in-echo-area)
+ (ns-echo-working-text pos len)
+ (ns-insert-working-text pos len))))
(defun ns-unput-working-text ()
(interactive)
(ns-delete-working-text))
-(defun ns-insert-working-text ()
+(defun ns-insert-working-text (pos len)
"Insert contents of `ns-working-text' as UTF-8 string and mark with
`ns-working-overlay'. Any previously existing working text is cleared first.
The overlay is assigned the face `ns-working-text-face'."
(interactive)
(ns-delete-working-text)
- (let ((start (point)))
+ (let ((start (point))
+ working-text)
+ (if (= len 0)
+ (setq working-text (propertize ns-working-text 'face 'ns-working-text-face))
+ (setq working-text (propertize ns-working-text 'face 'ns-unmarked-text-face))
+ (put-text-property pos (+ pos len)
+ 'face 'ns-marked-text-face working-text))
(overlay-put (setq ns-working-overlay (make-overlay start (point)))
'after-string
- (propertize ns-working-text 'face 'ns-working-text-face))))
+ working-text)))
-(defun ns-echo-working-text ()
+(defun ns-echo-working-text (pos len)
"Echo contents of `ns-working-text' in message display area.
See `ns-insert-working-text'."
(ns-delete-working-text)
@@ -327,8 +347,13 @@ ns-echo-working-text
message-log-max)
(setq ns-working-overlay (length ns-working-text))
(setq msg (concat msg ns-working-text))
- (put-text-property msglen (+ msglen ns-working-overlay)
- 'face 'ns-working-text-face msg)
+ (if (= len 0)
+ (put-text-property msglen (+ msglen ns-working-overlay)
+ 'face 'ns-working-text-face msg)
+ (put-text-property msglen (+ msglen ns-working-overlay)
+ 'face 'ns-unmarked-text-face msg)
+ (put-text-property (+ msglen pos) (+ msglen pos len)
+ 'face 'ns-marked-text-face msg))
(message "%s" msg)))
(defun ns-delete-working-text()
diff --git a/src/keyboard.c b/src/keyboard.c
index 9dd7e00..f31c70f 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -5447,9 +5447,10 @@ make_lispy_event (struct input_event *event)
#ifdef HAVE_NS
case NS_TEXT_EVENT:
- return list1 (intern (event->code == KEY_NS_PUT_WORKING_TEXT
- ? "ns-put-working-text"
- : "ns-unput-working-text"));
+ if (event->code == KEY_NS_PUT_WORKING_TEXT)
+ return Fcons (intern ("ns-put-working-text"), event->arg);
+ else
+ return list1 (intern ("ns-unput-working-text"));
/* NS_NONKEY_EVENTs are just like NON_ASCII_KEYSTROKE_EVENTs,
except that they are non-key events (last-nonmenu-event is nil). */
diff --git a/src/nsterm.m b/src/nsterm.m
index fddd4b0..c55f5af 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -6513,6 +6513,8 @@ - (void)setMarkedText: (id)aString selectedRange: (NSRange)selRange
{
NSString *str = [aString respondsToSelector: @selector (string)] ?
[aString string] : aString;
+ NSUInteger selPos = selRange.location;
+ NSUInteger selLen = selRange.length;
NSTRACE ("[EmacsView setMarkedText:selectedRange:]");
@@ -6536,8 +6538,27 @@ - (void)setMarkedText: (id)aString selectedRange: (NSRange)selRange
workingText = [str copy];
ns_working_text = build_string ([workingText UTF8String]);
+ for (NSUInteger i = 0; i < [str length]; i++)
+ {
+ NSUInteger code = [str characterAtIndex:i];
+ if (UTF_16_HIGH_SURROGATE_P (code) && i < [str length] - 1)
+ {
+ unichar low = [str characterAtIndex:i + 1];
+ if (UTF_16_LOW_SURROGATE_P (low))
+ {
+ if (i < selRange.location)
+ --selPos;
+ if (i >= selRange.location && i < selRange.location + selRange.length)
+ --selLen;
+ ++i;
+ }
+ }
+ }
+
emacs_event->kind = NS_TEXT_EVENT;
emacs_event->code = KEY_NS_PUT_WORKING_TEXT;
+ emacs_event->arg = list2 (make_fixnum (selPos),
+ make_fixnum (selLen));
EV_TRAILER ((id)nil);
}
--
2.21.0
@tsuu32
Copy link
Author

tsuu32 commented Feb 13, 2020

最小限 Emacs NS port 日本語インライン入力改善パッチ (https://github.com/takaxp/ns-inline-patch の多くを参考にしました)

  1. 日本語インライン入力時での「未確定文字列 (working text) に対して、変換中の文節 (marked text) とそれ以外を区別する」機能 (ns-marked-text-face, ns-unmarked-text-face)
  2. Isearchで日本語インライン入力中、特定の条件でエコーエリアの表示がおかしくなる問題の修正

Emacs 28で試して動作することを確認しています。
使い方:

# emacsリポジトリのルートで
git am 0001-marked-text-face-Isearch-patch.patch

@tsuu32
Copy link
Author

tsuu32 commented Feb 19, 2020

1について:
現在のEmacs NS portでは、変換時に文節を区切った場合、選択中の文節とそれ以外の見分けがつきません(gif画像は「にほんご」と入力して、文節として「にほん」を選択しているところ)。

このパッチではそれを区別し、別々のface (ns-marked-text-face, ns-unmarked-text-face) を使います。ns-marked-text-face, ns-unmarked-text-faceはカスタマイズ可能です。

2について:
現在のEmacs NS portでは、Isearchでインライン入力した際特定の条件で表示がバグります(gif画像はバグが発生しているところ)。
以下の条件で発生することを確認しています。
「未確定文字列に対して(スペースを押すなどして)候補を選択直後に、確定せずに次の文字を入力し始めたとき」
emacs-isearch-ime
このパッチではこれを修正し、上の条件下でもIsearchの表示がバグりません。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment