Showing posts with label Emacs. Show all posts
Showing posts with label Emacs. Show all posts

Friday, March 4, 2016

GNU Emacs֊ի ևս մեկ ընդլայնում

GNU Emacs տեքստային խմբագրիչն իմ ամենօրյա աշխատանքային գործիքն է։ Դրանով եմ ես ծրագրեր գրում, նշումներ անում, OCR արված տեքստեր մաքրագրում և աշխատում իմ սեփական գրքերի ու գրառումների տեքստերի հետ։ Այս բոլոր գործերի մեծամասնությունը հայերեն տեքստերի հետ է կապված։ Եվ, բնականաբար, ինձ պետք է լինում ակտիվորեն օգտագործել Emacs-ի key-binding֊ները՝ ստեղնների համակցությունների հետ կապված գործողությունները։ Օրինակ, նոր ֆայլ ստեղծելու գործողությունը կապված է C-x C-f հաջորդականության հետ, որը նշանակում է․ «սեղմած պահել Control ստեղնը և հաջորդաբար սեղմել x և f ստեղնները»։ Սակայն անհարմարությունն այն է, որ Emacs֊ի բոլոր key-binding֊ները արված են լատինական (անգլերենի այբուբենի) տառերի համար, և հայերեն տեքստերի հետ աշխատելու ժամանակ, երբ մի որևէ գործ է պետք լինում անել, ես ստիպված եմ լինում փոխել ստեղնաշարը հայերենից անգլերենի, կատարել գործողութնունը (օրինակ, պահպանել ֆայլը, նշել տեքստի հատվածը և այլն), ապա վերադառնալ հայերեն դասավորությանն ու շարունակել իմ գործը տեքստի հետ։

Խմբագրման և գործողությունների հետ կապված անհարմարությունները լուծելու համար ես որոշեցի Emacs֊ի key-binding֊ները լրացնել նաև հայերեն տարբերակներով։ Այսինքն, ես ուզում եմ իմ .emacs ֆայլում ունենալ լատիներեն key-binding֊ներից հայերենի արտապատկերող մի այսպիսի արտահայտություն․
(armenian-keys 
 '(("C-x C-f" . "C-ղ C-ֆ")
   ("C-x C-s" . "C-ղ C-ս")
   ("M-w" . "M-ո")))
որում armenian-keys ֆունկցիան ստանում է կետով զույգերի (dotted pair) ցուցակ, որի տարրերից առաջինը արդեն գոյություն ունեցող համակցությունն է, իսկ երկրորդը դրա հայերեն համարժեքը, որը պետք է ստեղծել։

Արդեն գոյություն ունեցող key-binding֊ները պահվում են current-global-map ֆունկցիայի վերադարձրած օբյեկտում։ Ինձ հետաքրքրող key-binding֊ը վերցնում եմ lookup-key ֆունկցիայով, և global-set-key ֆունկցաիյով կապում եմ հայերեն համակցությանը։

armenian-keys ֆունկցիան սահմանել եմ հետևյալ կերպ․ այն անցնում է տրված ցուցակի տարրերով և ամեն մի զույգի համար կատարում է վերը թվարկված գործողությունները։
(defun armenian-keys (kml)
  (let ((cgm (current-global-map)))
    (dolist (e kml)
      (let ((en (kbd (car e)))
            (hy (kbd (cdr e))))
        (global-set-key hy (lookup-key cgm en))))))
Հիմա ես կարող եմ առանց ստեղնաշարը փոխելու օգտագործել ինձ հարկավոր գործողությունները։

Sunday, January 10, 2016

GNU/Emacs֊ի փոքր ընդլայնում

Հայերեն տեքստերը OCR գործիքներով ճանաչելիս բավականին հաճախ է պատահում, որ բառի մեջ հայտնվում են անցանկալի բացատանիշեր։ Դա կապված է, օրինակ հայերեն տառերի պատկերների հետ, երբ տառի ձախ ու աջ կողմերից կան ցցված մասեր։

Երբ մաքրագրում եմ այդպիսի «ցանցառ» տեքստերը, ժամանակիս մեծ մասը ծախսվում է բացատները հեռացնելու վրա։ Հենց այդ պատճառով էլ որոշեցի GNU/Emacs֊ի համար (քանի որ այդ խմբագրիչն եմ առավել հաճախ օգտագործում) գրել մի օժանդակ ֆունկցիա, որը կհեռացնի տեքստնի նշված հատվածի՝ ռեգիոնի բացատները։

Ես պետք է կատարեի հետևյալ քայլերը․ i) վերցնել նշված տեքստը, ii) տեքստից հեռացնել բացատները, iii) հեռացնել հին տեքստը և iv) տեղադրել հեռացված բացատներով տեքստը։ Այս քայլերը պետք է ծրագրավորել որպես Emacs Lisp լեզվի ֆունկցիա, և կապել ստեղնների ինչ֊որ համակցության հետ, որպեսզի հնարավոր լինի այն օգտագործել տեքստի խմբագրման ինտերակտիվ ռեժիմում։

Բնականաբար, գործը սկսվեց ինտերնետում փորփրելուց՝ վերը նշված քայլերը կատարող գործողություների որոնմամբ։ Եվ այսպես․ i) Emacs֊ի բուֆերից՝ խմբագրվող տեքստի տիրույթից տեքստի հատվածը կարելի է վերցնել buffer-substring և buffer-substring-no-properties ֆունկցիաներով։ Սրանցից առաջիննը տեքստը տալիս է ինչ֊որ ատրիբուտների հետ, իսկ երկրորդը՝ առանց ատրիբուտների: ինձ պետք է երկրորդը։ ii) Տեքստը ֆիլտրելու համար նախ պետք է string-to-list ֆունկցիայով նրանից ստանալ ցուցակ, ապա այդ ցուցակից remq ֆունկցիայով հեռացնել ոչ պետքական տարրերը, վերջում էլ ցուցակից նորից ստանալ տող։ iii) Ռեգիոնը բուֆերից հեռացվում է delete-region ֆունկցիայով։ iv) Բուֆերի ընթացիկ կետում (point) տեքստը տեղադրվում է insert ֆունկցիայով։

Իմ գրած remove-region-spaces ֆունկցիան ունի երկու պարամետր՝ նշված տեքստի սկիզբն ու վերջը ցույց տվող ինդեքսները։ Ֆունկցիայի առաջին տողում գրված (interactive "r") արտահայտությունը պահանջում է, որ խմբագրման ինտերակտիվ ռեժիմում այս ֆունկցիան կանչելիս նրան փոխանվեն ռեգիոնի սկիզբն ու վերջը (ավելի ճիշտ՝ mark֊ը և point֊ը)։

(defun remove-region-spaces (begin end)
  (interactive "r")
  (let ((text (buffer-substring-no-properties begin end)))
    (delete-region begin end)
    (insert (apply #'string (remq ?\  (string-to-list text))))))

GNU/Emacs֊ում ստեղնների C-x C-j համադրությունն ազատ է։ remove-region-spaces ֆունկցիան կապում եմ այդ ստեղնների հետ՝ և՛ լատինական և հայերեն տառերի համար։

(global-set-key (kbd "C-x C-j") 'remove-region-spaces)
(global-set-key (kbd "C-ղ C-յ") 'remove-region-spaces)

Այսքանը։ remove-region-spaces ֆունկցիան և այն ստեղնների համադրության հետ կապող արտահայտությունները գրում եմ .emacs ֆայլում, և վերագործարկում եմ խմբագրիչը։