Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

port some functions #298

Merged
merged 20 commits into from Sep 14, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
20 changes: 20 additions & 0 deletions rust_src/remacs-sys/lib.rs 100644 → 100755
Expand Up @@ -296,6 +296,18 @@ pub struct Lisp_Marker {
pub bytepos: ptrdiff_t,
}

// TODO: write a docstring based on the docs in lisp.h.
#[repr(C)]
pub struct Lisp_Overlay {
pub ty: Lisp_Misc_Type,
// GC mark bit, 16 bits spacer
padding: u16,
pub next: *const Lisp_Overlay,
pub start: Lisp_Object,
pub end: Lisp_Object,
pub plist: Lisp_Object,
}

/// Represents the cursor position within an Emacs window. For
/// documentation see stuct cursor_pos in window.h.
#[repr(C)]
Expand Down Expand Up @@ -1297,6 +1309,9 @@ extern "C" {
pub static Qcharacterp: Lisp_Object;
pub static Qchar_table_p: Lisp_Object;
pub static Qbufferp: Lisp_Object;
pub static Qwindowp: Lisp_Object;
pub static Qwindow_live_p: Lisp_Object;
pub static Qoverlayp: Lisp_Object;
pub static Qminus: Lisp_Object;

pub static Qinteger: Lisp_Object;
Expand Down Expand Up @@ -1344,7 +1359,12 @@ extern "C" {
pub static lispsym: Lisp_Symbol;
pub static Vbuffer_alist: Lisp_Object;
pub static Vprocess_alist: Lisp_Object;
pub static Vminibuffer_list: Lisp_Object;
pub static minibuf_level: EmacsInt;
pub static minibuf_window: Lisp_Object;
pub static selected_window: Lisp_Object;

pub fn Faref(array: Lisp_Object, idx: Lisp_Object) -> Lisp_Object;
pub fn Fcons(car: Lisp_Object, cdr: Lisp_Object) -> Lisp_Object;
pub fn Fcurrent_buffer() -> Lisp_Object;
pub fn Fsignal(error_symbol: Lisp_Object, data: Lisp_Object) -> !;
Expand Down
67 changes: 66 additions & 1 deletion rust_src/src/buffers.rs
Expand Up @@ -3,10 +3,12 @@
use libc::{c_void, c_uchar, ptrdiff_t};

use lisp::{LispObject, ExternalPtr};
use remacs_sys::{Lisp_Object, EmacsInt, Lisp_Buffer, Lisp_Type, Vbuffer_alist, make_lisp_ptr};
use remacs_sys::{Lisp_Object, EmacsInt, Lisp_Buffer, Lisp_Overlay, Lisp_Type, Vbuffer_alist,
make_lisp_ptr, set_buffer_internal, nsberror};
use strings::string_equal;
use lists::{car, cdr};
use threads::ThreadState;
use marker::{marker_position, marker_buffer};

use std::mem;

Expand All @@ -16,6 +18,7 @@ pub const BEG: ptrdiff_t = 1;
pub const BEG_BYTE: ptrdiff_t = 1;

pub type LispBufferRef = ExternalPtr<Lisp_Buffer>;
pub type LispOverlayRef = ExternalPtr<Lisp_Overlay>;

impl LispBufferRef {
#[inline]
Expand Down Expand Up @@ -93,6 +96,11 @@ impl LispBufferRef {
unsafe { (*self.text).chars_modiff }
}

#[inline]
pub fn name(&self) -> LispObject {
LispObject::from_raw(self.name)
}

// Check if buffer is live
#[inline]
pub fn is_live(self) -> bool {
Expand All @@ -111,6 +119,18 @@ impl LispBufferRef {
}
}

impl LispOverlayRef {
#[inline]
pub fn start(&self) -> LispObject {
LispObject::from_raw(self.start)
}

#[inline]
pub fn end(&self) -> LispObject {
LispObject::from_raw(self.end)
}
}

impl LispObject {
/// Return SELF as a struct buffer pointer, defaulting to the current buffer.
/// Same as the decode_buffer function in buffer.h
Expand Down Expand Up @@ -230,6 +250,28 @@ fn buffer_chars_modified_tick(buffer: LispObject) -> LispObject {
LispObject::from_fixnum(buffer.as_buffer_or_current_buffer().chars_modiff())
}

/// Return the position at which OVERLAY starts.
#[lisp_fn]
fn overlay_start(overlay: LispObject) -> LispObject {
let marker = overlay.as_overlay_or_error().start();
marker_position(marker)
}

/// Return the position at which OVERLAY ends.
#[lisp_fn]
fn overlay_end(overlay: LispObject) -> LispObject {
let marker = overlay.as_overlay_or_error().end();
marker_position(marker)
}

/// Return the buffer OVERLAY belongs to.
/// Return nil if OVERLAY has been deleted.
#[lisp_fn]
fn overlay_buffer(overlay: LispObject) -> LispObject {
let marker = overlay.as_overlay_or_error().start();
marker_buffer(marker)
}

#[no_mangle]
pub extern "C" fn validate_region(b: *mut Lisp_Object, e: *mut Lisp_Object) {
let start = LispObject::from_raw(unsafe { *b });
Expand All @@ -255,3 +297,26 @@ pub extern "C" fn validate_region(b: *mut Lisp_Object, e: *mut Lisp_Object) {
args_out_of_range!(current_buffer(), start, stop);
}
}

/// Make buffer BUFFER-OR-NAME current for editing operations.
/// BUFFER-OR-NAME may be a buffer or the name of an existing buffer.
/// See also `with-current-buffer' when you want to make a buffer current
/// temporarily. This function does not display the buffer, so its effect
/// ends when the current command terminates. Use `switch-to-buffer' or
/// `pop-to-buffer' to switch buffers permanently.
/// The return value is the buffer made current.
#[lisp_fn]
fn set_buffer(buffer_or_name: LispObject) -> LispObject {
let buffer = get_buffer(buffer_or_name);
if buffer.is_nil() {
unsafe { nsberror(buffer_or_name.to_raw()) }
};
if !buffer.as_buffer().unwrap().is_live() {
error!("Selecting deleted buffer");
};
unsafe {
set_buffer_internal(buffer.as_buffer_or_error().as_ptr() as *const _ as
*const c_void)
};
buffer
}
6 changes: 3 additions & 3 deletions rust_src/src/editfns.rs
Expand Up @@ -25,9 +25,9 @@ pub fn point() -> LispObject {
/// in some other BUFFER, use
/// `(with-current-buffer BUFFER (- (point-max) (point-min)))'.
#[lisp_fn(min = "0")]
pub fn buffer_size(object: LispObject) -> LispObject {
let buffer_ref = if object.is_not_nil() {
get_buffer(object).as_buffer_or_error()
pub fn buffer_size(buffer: LispObject) -> LispObject {
let buffer_ref = if buffer.is_not_nil() {
get_buffer(buffer).as_buffer_or_error()
} else {
ThreadState::current_buffer()
};
Expand Down
19 changes: 19 additions & 0 deletions rust_src/src/fns.rs
@@ -0,0 +1,19 @@
//! Random utility Lisp functions.

use remacs_macros::lisp_fn;
use remacs_sys::{Faref, Qsequencep};
use lisp::LispObject;
use lists::{car, nthcdr};

/// Return element of SEQUENCE at index N.
#[lisp_fn]
pub fn elt(sequence: LispObject, n: LispObject) -> LispObject {
n.as_natnum_or_error();
if sequence.is_cons() || sequence.is_nil() {
car(nthcdr(n, sequence))
} else if sequence.is_array() {
LispObject::from_raw(unsafe { Faref(sequence.to_raw(), n.to_raw()) })
} else {
wrong_type!(Qsequencep, sequence);
}
}
23 changes: 23 additions & 0 deletions rust_src/src/lib.rs
Expand Up @@ -55,6 +55,8 @@ mod chartable;
mod category;
mod obarray;
mod editfns;
mod minibuf;
mod fns;

#[cfg(all(not(test), target_os = "macos"))]
use alloc_unexecmacosx::OsxUnexecAlloc;
Expand All @@ -72,6 +74,9 @@ pub use base64::base64_decode_1;
pub use buffers::Fbuffer_live_p;
pub use buffers::Fbuffer_modified_p;

// Used in window.c
pub use windows::Fwindow_buffer;

// used in process.c
pub use buffers::Fbuffer_name;

Expand All @@ -92,6 +97,7 @@ pub use math::Fleq;
pub use math::arithcompare;
pub use editfns::Feobp;
pub use editfns::Fbobp;
pub use fns::Felt;

// Widely used in the C codebase.
pub use lists::Fsetcar;
Expand Down Expand Up @@ -137,11 +143,13 @@ pub use vectors::Fsort;
pub use lists::merge;
pub use buffers::Fget_buffer;
pub use buffers::Fcurrent_buffer;
pub use buffers::Fset_buffer;
pub use obarray::intern_1;
pub use obarray::Fintern;
pub use obarray::Fintern_soft;
pub use marker::Fmarker_position;
pub use marker::Fmarker_buffer;
pub use windows::Fwindow_point;

// Used in fileio.c
pub use editfns::Fpoint;
Expand All @@ -168,6 +176,10 @@ pub use multibyte::str_to_multibyte;
pub use multibyte::str_as_unibyte;
pub use multibyte::str_to_unibyte;

// Used in xdisp.c
pub use buffers::Foverlay_start;
pub use buffers::Foverlay_end;

// Used in window.c, macros.c
pub use interactive::Fprefix_numeric_value;
pub use editfns::Fbolp;
Expand All @@ -189,8 +201,16 @@ pub extern "C" fn rust_init_syms() {
defsubr(&*buffers::Sbuffer_modified_tick);
defsubr(&*buffers::Sbuffer_chars_modified_tick);
defsubr(&*buffers::Sbuffer_name);
defsubr(&*buffers::Sset_buffer);
defsubr(&*buffers::Soverlay_start);
defsubr(&*buffers::Soverlay_end);
defsubr(&*buffers::Soverlay_buffer);
defsubr(&*windows::Swindowp);
defsubr(&*windows::Swindow_live_p);
defsubr(&*windows::Swindow_point);
defsubr(&*windows::Sselected_window);
defsubr(&*windows::Swindow_buffer);
defsubr(&*windows::Swindow_valid_p);
defsubr(&*process::Sget_process);
defsubr(&*process::Sprocessp);
defsubr(&*lists::Satom);
Expand Down Expand Up @@ -335,5 +355,8 @@ pub extern "C" fn rust_init_syms() {
defsubr(&*editfns::Seolp);
defsubr(&*editfns::Spoint_min);
defsubr(&*editfns::Spoint_max);
defsubr(&*minibuf::Sminibufferp);
defsubr(&*minibuf::Sactive_minibuffer_window);
defsubr(&*fns::Selt);
}
}
35 changes: 33 additions & 2 deletions rust_src/src/lisp.rs
Expand Up @@ -14,7 +14,7 @@ use libc::{c_char, c_void, intptr_t, ptrdiff_t, uintptr_t};
use multibyte::{Codepoint, LispStringRef, MAX_CHAR};
use symbols::LispSymbolRef;
use vectors::LispVectorlikeRef;
use buffers::LispBufferRef;
use buffers::{LispBufferRef, LispOverlayRef};
use windows::LispWindowRef;
use marker::LispMarkerRef;
use hashtable::LispHashTableRef;
Expand All @@ -28,7 +28,8 @@ use remacs_sys::{EmacsInt, EmacsUint, EmacsDouble, VALMASK, VALBITS, INTTYPEBITS
make_float, circular_list, internal_equal, Fcons, CHECK_IMPURE, Qnil, Qt,
Qnumberp, Qfloatp, Qstringp, Qsymbolp, Qnumber_or_marker_p, Qinteger_or_marker_p,
Qwholenump, Qvectorp, Qcharacterp, Qlistp, Qintegerp, Qhash_table_p,
Qchar_table_p, Qconsp, Qbufferp, Qmarkerp, SYMBOL_NAME, PseudovecType, EqualKind};
Qchar_table_p, Qconsp, Qbufferp, Qmarkerp, Qoverlayp, Qwindowp, Qwindow_live_p,
SYMBOL_NAME, PseudovecType, EqualKind};

// TODO: tweak Makefile to rebuild C files if this changes.

Expand Down Expand Up @@ -508,6 +509,20 @@ impl LispObject {
self.as_vectorlike().map_or(None, |v| v.as_window())
}

pub fn as_window_or_error(self) -> LispWindowRef {
self.as_window().unwrap_or_else(
|| wrong_type!(Qwindowp, self),
)
}

pub fn as_live_window_or_error(self) -> LispWindowRef {
if self.as_window().map_or(false, |w| w.is_live()) {
self.as_window().unwrap()
} else {
wrong_type!(Qwindow_live_p, self);
}
}

pub fn is_frame(self) -> bool {
self.as_vectorlike().map_or(false, |v| {
v.is_pseudovector(PseudovecType::PVEC_FRAME)
Expand Down Expand Up @@ -925,6 +940,22 @@ impl LispObject {
)
}

pub fn as_overlay(self) -> Option<LispOverlayRef> {
self.as_misc().and_then(
|m| if m.ty == Lisp_Misc_Type::Overlay {
unsafe { Some(mem::transmute(m)) }
} else {
None
},
)
}

pub fn as_overlay_or_error(self) -> LispOverlayRef {
self.as_overlay().unwrap_or_else(
|| wrong_type!(Qoverlayp, self),
)
}

// The three Emacs Lisp comparison functions.

#[inline]
Expand Down
4 changes: 2 additions & 2 deletions rust_src/src/lists.rs
Expand Up @@ -95,7 +95,7 @@ fn cdr_safe(object: LispObject) -> LispObject {

/// Take cdr N times on LIST, return the result.
#[lisp_fn]
fn nthcdr(n: LispObject, list: LispObject) -> LispObject {
pub fn nthcdr(n: LispObject, list: LispObject) -> LispObject {
let num = n.as_fixnum_or_error();
let mut tail = list;
for _ in 0..num {
Expand All @@ -122,7 +122,7 @@ fn nth(n: LispObject, list: LispObject) -> LispObject {
/// Return non-nil if ELT is an element of LIST. Comparison done with `eq'.
/// The value is actually the tail of LIST whose car is ELT.
#[lisp_fn]
fn memq(elt: LispObject, list: LispObject) -> LispObject {
pub fn memq(elt: LispObject, list: LispObject) -> LispObject {
for tail in list.iter_tails() {
if elt.eq(tail.car()) {
return tail.as_obj();
Expand Down
8 changes: 4 additions & 4 deletions rust_src/src/marker.rs
Expand Up @@ -47,8 +47,8 @@ fn markerp(object: LispObject) -> LispObject {

/// Return the position of MARKER, or nil if it points nowhere.
#[lisp_fn]
fn marker_position(object: LispObject) -> LispObject {
let pos = object.as_marker_or_error().charpos();
pub fn marker_position(marker: LispObject) -> LispObject {
let pos = marker.as_marker_or_error().charpos();
match pos {
Some(p) => LispObject::from_natnum(p as EmacsInt),
None => LispObject::constant_nil(),
Expand All @@ -58,8 +58,8 @@ fn marker_position(object: LispObject) -> LispObject {
/// Return the buffer that MARKER points into, or nil if none.
/// Returns nil if MARKER points into a dead buffer.
#[lisp_fn]
fn marker_buffer(object: LispObject) -> LispObject {
let buf = object.as_marker_or_error().buffer();
pub fn marker_buffer(marker: LispObject) -> LispObject {
let buf = marker.as_marker_or_error().buffer();
match buf {
Some(b) => unsafe {
LispObject::from_raw(make_lisp_ptr(
Expand Down