pfeiffer@deva.irit.fr (Daniel Pfeiffer) (04/19/91)
Anta^u ia tempo, mi demandis al reto Some time back, I asked the net, ^cu estis Emacs paketa^jo por whether there was an Emacs package samtempa, dulingva tajpado. Kion mi for simultaneous bilingual editing. demandis, eble estis troa laboro por What I asked for was maybe to much programisto. Mi ricevis shell pro- work to program. I received one gramon por kunmeti du datarojn, kun shell script, permitting to merge la bona ideo modifi ^giaj lar^gecoj two files, with the neat idea of ^gis ili estas samlongaj. reformatting the files until they Malfeli^ce li utiligas nestandardaj have the same length. Too bad he argumentoj. uses non-standard arguments. RMS proponis ke mi disigu la ekranon RMS proposed that I split the screen horizontale, tajpu, kaj poste horizontally, edit, and then merge kunmetu la du partoj. Por facile the two parts. To easily do this, I fari tion, mis skribis la apudan have written the following program. programon. Mi ^satus havi viajn I'd like to hear your remarks on it. rimakrojn pri ^gi. -- -- Daniel Pfeiffer <pfeiffer@cix.cict.fr> -- Tolosa (Toulouse), Midi-Pyrenees, Europe <pfeiffer@irit.fr> -- "Beware - polyglot esperantist" <pfeiffer@frcict81.bitnet> -- --8<--------8<--------8<--------8<--------8<--------8<--------8<--------8<--- ; Minora modalo por samtempa, dulingva Minor mode for simultaneous ; tajpado bilingual editing ; Copyright (C) 1991 Free Software Foundation, Inc. ; ^Ci dataro estas ero de GNU Emacs. This file is part of GNU Emacs. ; GNU Emacs estas disdonata en la GNU Emacs is distributed in the hope ; espero ke ^gi estos utila, sed SEN that it will be useful, but WITHOUT ; IA GARANTIO. Neniu a^utoro a^u ANY WARRANTY. No author or ; disdonanto akceptas respondecon al distributor accepts responsibility ; iu ajn por la sekvoj de ^gia uzado, to anyone for the consequences of ; a^u ^cu ^gi serveblas al iu celo, using it or for whether it serves ; a^u e^c entute funkcias, se li ni any particular purpose or works at ; estas skribinta tion. Vidu la GNU all, unless he says so in writing. ; Emacs ^Generala Publika Licenso por Refer to the GNU Emacs General ; plenaj detaloj. Public License for full details. ; ^Ciu rajtas kopii, modifi kaj ree Everyone is granted permission to ; disdoni GNU Emacs, sed nur sub la copy, modify and redistribute GNU ; condi^coj priskribitaj en la GNU Emacs, but only under the conditions ; Emacs ^Generala Publika Licenso. described in the GNU Emacs General ; Kopio de tiu licenso estas supozinta Public License. A copy of this ; donita al vi kune kun GNU Emacs, por license is supposed to have been ; ke vi sciu viaj rajtoj kaj given to you along with GNU Emacs so ; respondecoj. ^Gi devus esti en you can know your rights and ; dataro nomata COPYING. Kun responsibilities. It should be in a ; alia^joj, la notico pri kopirajto file named COPYING. Among other ; kaj ^ci notico devas esti gardata things, the copyright notice and ; sur ^ciuj kopioj. this notice must be preserved on all ; copies. ; Tiu minora modalo ebligas al vi This minor mode allows you to ; tajpi sendepende en du apudaj independently edit two adjacent ; bufroj. Vi ekas ^gin per C-x 6 2 buffers. You start it up with C-x 6 ; (bilingual:split), kiu donas al vi 2 (bilingual:split), which gives you ; horizontale disigatan fenestron, a horizontally split window similar ; simila al fina apareco de via to the final outcome of your text. ; teksto. Je ^cia flanko estas bufro, On each side is a buffer that knows ; kiu konas la alian. Kun la ordonoj about the other. With the commands ; C-x 6 SPC, C-x 6 DEL kaj C-x 6 RET C-x 6 SPC, C-x 6 DEL and C-x 6 RET ; oni povas suben- a^u supreniri unu you can simultaneously scroll up or ; ekranon, kaj subeniri linion, down by a screenfull and by a line ; samtempe en la du bufroj. Kiam vi in both buffers. When you only have ; nur plu havas unu el la du bufroj one of the two buffers onscreen you ; surekrane vi revidos la alian per can get the other back with C-x 6 2 ; denove C-x 6 2. once more. ; Kiu bufro estas dekstre a^u Which buffer is right or left on the ; maldekstre ne gravas por la fina screen has no importance for the ; rezulto. Sed se vi volas meti final outcome. However, if you ; longajn liniojn (ekz. programerojn) include long lines, i.e which will ; en la kunigotan tekston, ili devas span both columns (eg. source code), ; esti en la estonte unua kolumno. La they should be in what will be the ; alia devas havi malplenajn linion first column, with the associated ; apud ili. buffer having empty lines next to ; them. ; Kiam vi estos kontenta de la When you have edited both buffers to ; rezulto, vi kunmetos la du kolumnoj your content, you merge them with ; per C-x 6 1 ( (bilingual:merge). Se C-x 6 1 (bilingual:merge). If you ; vi poste vidas problemojn, vi then see a problem, you undo the ; neniigi la kunmeton per C-x u kaj merge with C-x u and continue to ; plue modifu la du bufrojn. edit. (provide 'bilingual) (defvar bilingual:mode-map nil "Keymap useful with bilingual minor mode.") (if bilingual:mode-map () (setq bilingual:mode-map (make-sparse-keymap)) (define-key bilingual:mode-map "1" 'bilingual:merge) (define-key bilingual:mode-map "2" 'bilingual:split) (define-key bilingual:mode-map "o" 'bilingual:other) (define-key bilingual:mode-map " " 'bilingual:scroll-up) (define-key bilingual:mode-map "\^?" 'bilingual:scroll-down) (define-key bilingual:mode-map "\C-m" 'bilingual:scroll-line)) (global-set-key "\C-x6" bilingual:mode-map) ; markers seem to be the only buffer-id not affected by renaming ; a buffer (defvar bilingual:other nil "Marker to the other buffer which will be merged to this one, if non-nil.") (make-variable-buffer-local 'bilingual:other) (setq minor-mode-alist (cons '(bilingual:other " 2L") minor-mode-alist)) ; rearranged, so that the pertinent info will show in 40 columns (defvar bilingual:mode-line-format '("-%*- %15b (" mode-name ")--" (-3 . "%p") "--%[" minor-mode-alist "%n" mode-line-process " %]%-") "*Value of mode-line-format for a buffer in bilingual minor mode.") (defvar bilingual:window-width 40 "*The width of the first column.") (defvar bilingual:fill-column 36 "*Value of fill-column for a buffer in bilingual minor mode.") (defvar bilingual:mode-hook nil "Function called, if non-nil, whenever bilingual:split is called, on both buffers if they are not already in bilingual minor mode.") ;;;;; base functions (defun bilingual:split () "Split current window vertically for bilingual editing. When called the first time, associates the buffer *Bilingual* with the current buffer. Both buffers are put in bilingual minor mode and bilingual:mode-hook gets called on both. These buffers remember about one another, even when renamed. When called again, restores the screen layout with the current buffer first and the associated buffer to it's right. Which buffer is right or left on the screen has no importance for the final outcome. However, if you include long lines, i.e which will span both columns (eg. source code), they should be in what will be the first column, with the associated buffer having empty lines next to them. You have the following commands at your disposal: C-x 6 2 Enter this minor mode, or, afterwards, rearrange screen C-x 6 SPC Scroll both buffers up by a screenfull C-x 6 DEL Scroll both buffers down by a screenful C-x 6 RET Scroll both buffers up by one or more lines C-x 6 o Switch to associated buffer C-x 6 1 Merge the other buffer, starting next to this line" (interactive) (if (< (window-width) (screen-width)) (enlarge-window-horizontally 99999)) (split-window nil bilingual:window-width t) (if bilingual:other (progn (other-window 1) (switch-to-buffer (marker-buffer bilingual:other)) (other-window -1)) (setq fill-column bilingual:fill-column mode-line-format bilingual:mode-line-format) (run-hooks bilingual:mode-hook) (let ((other (point-marker))) (other-window 1) (switch-to-buffer "*Bilingual*") (setq fill-column bilingual:fill-column mode-line-format bilingual:mode-line-format bilingual:other other other (point-marker)) (run-hooks bilingual:mode-hook) (other-window -1) (setq bilingual:other other)))) (fset 'bilingual:mode 'bilingual:split) ; this doesn't use yank-rectangle, so that the first column can ; contain long lines (defun bilingual:merge () "Merges the associated buffer to the right of the current buffer, at the column, which is the value of bilingual:window-width. You should have split the window with \\[bilingual:split], in which case the effect is as though you erase the vertical window separator. That is, the two columns are pasted side by side, with the first line of column 2 appearing next to the current line of column 1, in a single text." (interactive) (or bilingual:other (error "You must set bilingual minor mode with bilingual:split.")) (save-excursion (let ((b1 (current-buffer)) (b2 (marker-buffer bilingual:other)) string) (set-buffer b2) (goto-char (point-min)) (while (not (eobp)) (setq string (buffer-substring (point) (progn (end-of-line) (point)))) (or (eobp) (forward-char)) ; next line (set-buffer b1) (if (string= string "") () (end-of-line) (indent-to-column bilingual:window-width) (insert string)) (next-line 1) ; add one if necessary (set-buffer b2)) (set-buffer b2))) (if (< (window-width) (screen-width)) (enlarge-window-horizontally 99999))) ;;;;; utility functions (defun bilingual:other () "Switch to associated buffer." (interactive) (or bilingual:other (error "You must set bilingual minor mode with bilingual:split.")) (if (get-buffer-window (marker-buffer bilingual:other)) (select-window (get-buffer-window (marker-buffer bilingual:other))) (switch-to-buffer (marker-buffer bilingual:other)))) (defun bilingual:scroll (arg function) (or bilingual:other (error "You must set bilingual minor mode with bilingual:split.")) (funcall function arg) (if (get-buffer-window (marker-buffer bilingual:other)) (let ((window (selected-window))) (select-window (get-buffer-window (marker-buffer bilingual:other))) (funcall function arg) (select-window window)))) (defun bilingual:scroll-up (arg) "Scroll current window and window showing associated buffer upward a page, or upward by ARG lines." (interactive "P") (bilingual:scroll arg 'scroll-up)) (defun bilingual:scroll-down (arg) "Scroll current window and window showing associated buffer downward a page, or downward by ARG lines." (interactive "P") (bilingual:scroll arg 'scroll-down)) (defun bilingual:scroll-line (arg) "Scroll current window and window showing associated buffer upward by ARG lines." (interactive "p") (bilingual:scroll arg 'scroll-up))