mirror of
https://github.com/gristlabs/grist-core.git
synced 2026-03-02 04:09:24 +00:00
(core) Improve suggestions for formula autocomplete
Summary: - Make suggestions less case-sensitive (not entirely case-insensitive, but allow top-level suggestions to match in all-lowercase) - Add function signatures to suggestions for Grist functions. - Excel-like functions that are present but not implemented are no longer offered as suggestions. Test Plan: Added a test case on python side, and a browser test case for how suggestions are rendered and inserted. Reviewers: paulfitz Reviewed By: paulfitz Differential Revision: https://phab.getgrist.com/D2608
This commit is contained in:
@@ -9,9 +9,11 @@ import re
|
||||
|
||||
import column
|
||||
from functions import date # pylint: disable=import-error
|
||||
from functions.unimplemented import unimplemented
|
||||
from usertypes import AltText # pylint: disable=import-error
|
||||
from records import Record, RecordSet
|
||||
|
||||
@unimplemented
|
||||
def ISBLANK(value):
|
||||
"""
|
||||
Returns whether a value refers to an empty cell. It isn't implemented in Grist. To check for an
|
||||
@@ -486,6 +488,7 @@ def NA():
|
||||
return float('nan')
|
||||
|
||||
|
||||
@unimplemented
|
||||
def TYPE(value):
|
||||
"""
|
||||
Returns a number associated with the type of data passed into the function. This is not
|
||||
@@ -493,6 +496,7 @@ def TYPE(value):
|
||||
"""
|
||||
raise NotImplementedError()
|
||||
|
||||
@unimplemented
|
||||
def CELL(info_type, reference):
|
||||
"""
|
||||
Returns the requested information about the specified cell. This is not implemented in Grist
|
||||
|
||||
@@ -1,57 +1,72 @@
|
||||
# pylint: disable=redefined-builtin, line-too-long
|
||||
from unimplemented import unimplemented
|
||||
|
||||
@unimplemented
|
||||
def ADDRESS(row, column, absolute_relative_mode, use_a1_notation, sheet):
|
||||
"""Returns a cell reference as a string."""
|
||||
raise NotImplementedError()
|
||||
|
||||
@unimplemented
|
||||
def CHOOSE(index, choice1, choice2):
|
||||
"""Returns an element from a list of choices based on index."""
|
||||
raise NotImplementedError()
|
||||
|
||||
@unimplemented
|
||||
def COLUMN(cell_reference=None):
|
||||
"""Returns the column number of a specified cell, with `A=1`."""
|
||||
raise NotImplementedError()
|
||||
|
||||
@unimplemented
|
||||
def COLUMNS(range):
|
||||
"""Returns the number of columns in a specified array or range."""
|
||||
raise NotImplementedError()
|
||||
|
||||
@unimplemented
|
||||
def GETPIVOTDATA(value_name, any_pivot_table_cell, original_column_1, pivot_item_1=None, *args):
|
||||
"""Extracts an aggregated value from a pivot table that corresponds to the specified row and column headings."""
|
||||
raise NotImplementedError()
|
||||
|
||||
@unimplemented
|
||||
def HLOOKUP(search_key, range, index, is_sorted):
|
||||
"""Horizontal lookup. Searches across the first row of a range for a key and returns the value of a specified cell in the column found."""
|
||||
raise NotImplementedError()
|
||||
|
||||
@unimplemented
|
||||
def HYPERLINK(url, link_label):
|
||||
"""Creates a hyperlink inside a cell."""
|
||||
raise NotImplementedError()
|
||||
|
||||
@unimplemented
|
||||
def INDEX(reference, row, column):
|
||||
"""Returns the content of a cell, specified by row and column offset."""
|
||||
raise NotImplementedError()
|
||||
|
||||
@unimplemented
|
||||
def INDIRECT(cell_reference_as_string):
|
||||
"""Returns a cell reference specified by a string."""
|
||||
raise NotImplementedError()
|
||||
|
||||
@unimplemented
|
||||
def LOOKUP(search_key, search_range_or_search_result_array, result_range=None):
|
||||
"""Looks through a row or column for a key and returns the value of the cell in a result range located in the same position as the search row or column."""
|
||||
raise NotImplementedError()
|
||||
|
||||
@unimplemented
|
||||
def MATCH(search_key, range, search_type):
|
||||
"""Returns the relative position of an item in a range that matches a specified value."""
|
||||
raise NotImplementedError()
|
||||
|
||||
@unimplemented
|
||||
def OFFSET(cell_reference, offset_rows, offset_columns, height, width):
|
||||
"""Returns a range reference shifted a specified number of rows and columns from a starting cell reference."""
|
||||
raise NotImplementedError()
|
||||
|
||||
@unimplemented
|
||||
def ROW(cell_reference):
|
||||
"""Returns the row number of a specified cell."""
|
||||
raise NotImplementedError()
|
||||
|
||||
@unimplemented
|
||||
def ROWS(range):
|
||||
"""Returns the number of rows in a specified array or range."""
|
||||
raise NotImplementedError()
|
||||
|
||||
@@ -7,6 +7,7 @@ import operator
|
||||
import random
|
||||
|
||||
from functions.info import ISNUMBER, ISLOGICAL
|
||||
from functions.unimplemented import unimplemented
|
||||
import roman
|
||||
|
||||
# Iterates through elements of iterable arguments, or through individual args when not iterable.
|
||||
@@ -727,6 +728,7 @@ def SQRTPI(value):
|
||||
"""
|
||||
return _math.sqrt(_math.pi * value)
|
||||
|
||||
@unimplemented
|
||||
def SUBTOTAL(function_code, range1, range2):
|
||||
"""
|
||||
Returns a subtotal for a vertical range of cells using a specified aggregation function.
|
||||
@@ -755,12 +757,14 @@ def SUM(value1, *more_values):
|
||||
return sum(_chain_numeric_a(value1, *more_values))
|
||||
|
||||
|
||||
@unimplemented
|
||||
def SUMIF(records, criterion, sum_range):
|
||||
"""
|
||||
Returns a conditional sum across a range.
|
||||
"""
|
||||
raise NotImplementedError()
|
||||
|
||||
@unimplemented
|
||||
def SUMIFS(sum_range, criteria_range1, criterion1, *args):
|
||||
"""
|
||||
Returns the sum of a range depending on multiple criteria.
|
||||
@@ -782,6 +786,7 @@ def SUMPRODUCT(array1, *more_arrays):
|
||||
"""
|
||||
return sum(reduce(operator.mul, values) for values in itertools.izip(array1, *more_arrays))
|
||||
|
||||
@unimplemented
|
||||
def SUMSQ(value1, value2):
|
||||
"""
|
||||
Returns the sum of the squares of a series of numbers and/or cells.
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
from math import _chain, _chain_numeric, _chain_numeric_a
|
||||
from info import ISNUMBER, ISLOGICAL
|
||||
from date import DATE # pylint: disable=unused-import
|
||||
|
||||
from unimplemented import unimplemented
|
||||
|
||||
def _average(iterable):
|
||||
total, count = 0.0, 0
|
||||
@@ -24,6 +24,7 @@ def _default_if_empty(iterable, default):
|
||||
yield default
|
||||
|
||||
|
||||
@unimplemented
|
||||
def AVEDEV(value1, value2):
|
||||
"""Calculates the average of the magnitudes of deviations of data from a dataset's mean."""
|
||||
raise NotImplementedError()
|
||||
@@ -95,14 +96,17 @@ def AVERAGE_WEIGHTED(pairs):
|
||||
return sum_value / sum_weight
|
||||
|
||||
|
||||
@unimplemented
|
||||
def AVERAGEIF(criteria_range, criterion, average_range=None):
|
||||
"""Returns the average of a range depending on criteria."""
|
||||
raise NotImplementedError()
|
||||
|
||||
@unimplemented
|
||||
def AVERAGEIFS(average_range, criteria_range1, criterion1, *args):
|
||||
"""Returns the average of a range depending on multiple criteria."""
|
||||
raise NotImplementedError()
|
||||
|
||||
@unimplemented
|
||||
def BINOMDIST(num_successes, num_trials, prob_success, cumulative):
|
||||
"""
|
||||
Calculates the probability of drawing a certain number of successes (or a maximum number of
|
||||
@@ -111,10 +115,12 @@ def BINOMDIST(num_successes, num_trials, prob_success, cumulative):
|
||||
"""
|
||||
raise NotImplementedError()
|
||||
|
||||
@unimplemented
|
||||
def CONFIDENCE(alpha, standard_deviation, pop_size):
|
||||
"""Calculates the width of half the confidence interval for a normal distribution."""
|
||||
raise NotImplementedError()
|
||||
|
||||
@unimplemented
|
||||
def CORREL(data_y, data_x):
|
||||
"""Calculates r, the Pearson product-moment correlation coefficient of a dataset."""
|
||||
raise NotImplementedError()
|
||||
@@ -156,22 +162,27 @@ def COUNTA(value, *more_values):
|
||||
return sum(1 for v in _chain(value, *more_values))
|
||||
|
||||
|
||||
@unimplemented
|
||||
def COVAR(data_y, data_x):
|
||||
"""Calculates the covariance of a dataset."""
|
||||
raise NotImplementedError()
|
||||
|
||||
@unimplemented
|
||||
def CRITBINOM(num_trials, prob_success, target_prob):
|
||||
"""Calculates the smallest value for which the cumulative binomial distribution is greater than or equal to a specified criteria."""
|
||||
raise NotImplementedError()
|
||||
|
||||
@unimplemented
|
||||
def DEVSQ(value1, value2):
|
||||
"""Calculates the sum of squares of deviations based on a sample."""
|
||||
raise NotImplementedError()
|
||||
|
||||
@unimplemented
|
||||
def EXPONDIST(x, lambda_, cumulative):
|
||||
"""Returns the value of the exponential distribution function with a specified lambda at a specified value."""
|
||||
raise NotImplementedError()
|
||||
|
||||
@unimplemented
|
||||
def F_DIST(x, degrees_freedom1, degrees_freedom2, cumulative):
|
||||
"""
|
||||
Calculates the left-tailed F probability distribution (degree of diversity) for two data sets
|
||||
@@ -180,6 +191,7 @@ def F_DIST(x, degrees_freedom1, degrees_freedom2, cumulative):
|
||||
"""
|
||||
raise NotImplementedError()
|
||||
|
||||
@unimplemented
|
||||
def F_DIST_RT(x, degrees_freedom1, degrees_freedom2):
|
||||
"""
|
||||
Calculates the right-tailed F probability distribution (degree of diversity) for two data sets
|
||||
@@ -188,6 +200,7 @@ def F_DIST_RT(x, degrees_freedom1, degrees_freedom2):
|
||||
"""
|
||||
raise NotImplementedError()
|
||||
|
||||
@unimplemented
|
||||
def FDIST(x, degrees_freedom1, degrees_freedom2):
|
||||
"""
|
||||
Calculates the right-tailed F probability distribution (degree of diversity) for two data sets
|
||||
@@ -196,46 +209,57 @@ def FDIST(x, degrees_freedom1, degrees_freedom2):
|
||||
"""
|
||||
raise NotImplementedError()
|
||||
|
||||
@unimplemented
|
||||
def FISHER(value):
|
||||
"""Returns the Fisher transformation of a specified value."""
|
||||
raise NotImplementedError()
|
||||
|
||||
@unimplemented
|
||||
def FISHERINV(value):
|
||||
"""Returns the inverse Fisher transformation of a specified value."""
|
||||
raise NotImplementedError()
|
||||
|
||||
@unimplemented
|
||||
def FORECAST(x, data_y, data_x):
|
||||
"""Calculates the expected y-value for a specified x based on a linear regression of a dataset."""
|
||||
raise NotImplementedError()
|
||||
|
||||
@unimplemented
|
||||
def GEOMEAN(value1, value2):
|
||||
"""Calculates the geometric mean of a dataset."""
|
||||
raise NotImplementedError()
|
||||
|
||||
@unimplemented
|
||||
def HARMEAN(value1, value2):
|
||||
"""Calculates the harmonic mean of a dataset."""
|
||||
raise NotImplementedError()
|
||||
|
||||
@unimplemented
|
||||
def HYPGEOMDIST(num_successes, num_draws, successes_in_pop, pop_size):
|
||||
"""Calculates the probability of drawing a certain number of successes in a certain number of tries given a population of a certain size containing a certain number of successes, without replacement of draws."""
|
||||
raise NotImplementedError()
|
||||
|
||||
@unimplemented
|
||||
def INTERCEPT(data_y, data_x):
|
||||
"""Calculates the y-value at which the line resulting from linear regression of a dataset will intersect the y-axis (x=0)."""
|
||||
raise NotImplementedError()
|
||||
|
||||
@unimplemented
|
||||
def KURT(value1, value2):
|
||||
"""Calculates the kurtosis of a dataset, which describes the shape, and in particular the "peakedness" of that dataset."""
|
||||
raise NotImplementedError()
|
||||
|
||||
@unimplemented
|
||||
def LARGE(data, n):
|
||||
"""Returns the nth largest element from a data set, where n is user-defined."""
|
||||
raise NotImplementedError()
|
||||
|
||||
@unimplemented
|
||||
def LOGINV(x, mean, standard_deviation):
|
||||
"""Returns the value of the inverse log-normal cumulative distribution with given mean and standard deviation at a specified value."""
|
||||
raise NotImplementedError()
|
||||
|
||||
@unimplemented
|
||||
def LOGNORMDIST(x, mean, standard_deviation):
|
||||
"""Returns the value of the log-normal cumulative distribution with given mean and standard deviation at a specified value."""
|
||||
raise NotImplementedError()
|
||||
@@ -364,14 +388,17 @@ def MINA(value, *more_values):
|
||||
return min(_default_if_empty(_chain_numeric_a(value, *more_values), 0))
|
||||
|
||||
|
||||
@unimplemented
|
||||
def MODE(value1, value2):
|
||||
"""Returns the most commonly occurring value in a dataset."""
|
||||
raise NotImplementedError()
|
||||
|
||||
@unimplemented
|
||||
def NEGBINOMDIST(num_failures, num_successes, prob_success):
|
||||
"""Calculates the probability of drawing a certain number of failures before a certain number of successes given a probability of success in independent trials."""
|
||||
raise NotImplementedError()
|
||||
|
||||
@unimplemented
|
||||
def NORMDIST(x, mean, standard_deviation, cumulative):
|
||||
"""
|
||||
Returns the value of the normal distribution function (or normal cumulative distribution
|
||||
@@ -379,42 +406,52 @@ def NORMDIST(x, mean, standard_deviation, cumulative):
|
||||
"""
|
||||
raise NotImplementedError()
|
||||
|
||||
@unimplemented
|
||||
def NORMINV(x, mean, standard_deviation):
|
||||
"""Returns the value of the inverse normal distribution function for a specified value, mean, and standard deviation."""
|
||||
raise NotImplementedError()
|
||||
|
||||
@unimplemented
|
||||
def NORMSDIST(x):
|
||||
"""Returns the value of the standard normal cumulative distribution function for a specified value."""
|
||||
raise NotImplementedError()
|
||||
|
||||
@unimplemented
|
||||
def NORMSINV(x):
|
||||
"""Returns the value of the inverse standard normal distribution function for a specified value."""
|
||||
raise NotImplementedError()
|
||||
|
||||
@unimplemented
|
||||
def PEARSON(data_y, data_x):
|
||||
"""Calculates r, the Pearson product-moment correlation coefficient of a dataset."""
|
||||
raise NotImplementedError()
|
||||
|
||||
@unimplemented
|
||||
def PERCENTILE(data, percentile):
|
||||
"""Returns the value at a given percentile of a dataset."""
|
||||
raise NotImplementedError()
|
||||
|
||||
@unimplemented
|
||||
def PERCENTRANK(data, value, significant_digits=None):
|
||||
"""Returns the percentage rank (percentile) of a specified value in a dataset."""
|
||||
raise NotImplementedError()
|
||||
|
||||
@unimplemented
|
||||
def PERCENTRANK_EXC(data, value, significant_digits=None):
|
||||
"""Returns the percentage rank (percentile) from 0 to 1 exclusive of a specified value in a dataset."""
|
||||
raise NotImplementedError()
|
||||
|
||||
@unimplemented
|
||||
def PERCENTRANK_INC(data, value, significant_digits=None):
|
||||
"""Returns the percentage rank (percentile) from 0 to 1 inclusive of a specified value in a dataset."""
|
||||
raise NotImplementedError()
|
||||
|
||||
@unimplemented
|
||||
def PERMUT(n, k):
|
||||
"""Returns the number of ways to choose some number of objects from a pool of a given size of objects, considering order."""
|
||||
raise NotImplementedError()
|
||||
|
||||
@unimplemented
|
||||
def POISSON(x, mean, cumulative):
|
||||
"""
|
||||
Returns the value of the Poisson distribution function (or Poisson cumulative distribution
|
||||
@@ -422,42 +459,52 @@ def POISSON(x, mean, cumulative):
|
||||
"""
|
||||
raise NotImplementedError()
|
||||
|
||||
@unimplemented
|
||||
def PROB(data, probabilities, low_limit, high_limit=None):
|
||||
"""Given a set of values and corresponding probabilities, calculates the probability that a value chosen at random falls between two limits."""
|
||||
raise NotImplementedError()
|
||||
|
||||
@unimplemented
|
||||
def QUARTILE(data, quartile_number):
|
||||
"""Returns a value nearest to a specified quartile of a dataset."""
|
||||
raise NotImplementedError()
|
||||
|
||||
@unimplemented
|
||||
def RANK(value, data, is_ascending=None):
|
||||
"""Returns the rank of a specified value in a dataset."""
|
||||
raise NotImplementedError()
|
||||
|
||||
@unimplemented
|
||||
def RANK_AVG(value, data, is_ascending=None):
|
||||
"""Returns the rank of a specified value in a dataset. If there is more than one entry of the same value in the dataset, the average rank of the entries will be returned."""
|
||||
raise NotImplementedError()
|
||||
|
||||
@unimplemented
|
||||
def RANK_EQ(value, data, is_ascending=None):
|
||||
"""Returns the rank of a specified value in a dataset. If there is more than one entry of the same value in the dataset, the top rank of the entries will be returned."""
|
||||
raise NotImplementedError()
|
||||
|
||||
@unimplemented
|
||||
def RSQ(data_y, data_x):
|
||||
"""Calculates the square of r, the Pearson product-moment correlation coefficient of a dataset."""
|
||||
raise NotImplementedError()
|
||||
|
||||
@unimplemented
|
||||
def SKEW(value1, value2):
|
||||
"""Calculates the skewness of a dataset, which describes the symmetry of that dataset about the mean."""
|
||||
raise NotImplementedError()
|
||||
|
||||
@unimplemented
|
||||
def SLOPE(data_y, data_x):
|
||||
"""Calculates the slope of the line resulting from linear regression of a dataset."""
|
||||
raise NotImplementedError()
|
||||
|
||||
@unimplemented
|
||||
def SMALL(data, n):
|
||||
"""Returns the nth smallest element from a data set, where n is user-defined."""
|
||||
raise NotImplementedError()
|
||||
|
||||
@unimplemented
|
||||
def STANDARDIZE(value, mean, standard_deviation):
|
||||
"""Calculates the normalized equivalent of a random variable given mean and standard deviation of the distribution."""
|
||||
raise NotImplementedError()
|
||||
@@ -559,50 +606,62 @@ def STDEVPA(value, *more_values):
|
||||
"""
|
||||
return _stddev(list(_chain_numeric_a(value, *more_values)), 0)
|
||||
|
||||
@unimplemented
|
||||
def STEYX(data_y, data_x):
|
||||
"""Calculates the standard error of the predicted y-value for each x in the regression of a dataset."""
|
||||
raise NotImplementedError()
|
||||
|
||||
@unimplemented
|
||||
def T_INV(probability, degrees_freedom):
|
||||
"""Calculates the negative inverse of the one-tailed TDIST function."""
|
||||
raise NotImplementedError()
|
||||
|
||||
@unimplemented
|
||||
def T_INV_2T(probability, degrees_freedom):
|
||||
"""Calculates the inverse of the two-tailed TDIST function."""
|
||||
raise NotImplementedError()
|
||||
|
||||
@unimplemented
|
||||
def TDIST(x, degrees_freedom, tails):
|
||||
"""Calculates the probability for Student's t-distribution with a given input (x)."""
|
||||
raise NotImplementedError()
|
||||
|
||||
@unimplemented
|
||||
def TINV(probability, degrees_freedom):
|
||||
"""Calculates the inverse of the two-tailed TDIST function."""
|
||||
raise NotImplementedError()
|
||||
|
||||
@unimplemented
|
||||
def TRIMMEAN(data, exclude_proportion):
|
||||
"""Calculates the mean of a dataset excluding some proportion of data from the high and low ends of the dataset."""
|
||||
raise NotImplementedError()
|
||||
|
||||
@unimplemented
|
||||
def TTEST(range1, range2, tails, type):
|
||||
"""Returns the probability associated with t-test. Determines whether two samples are likely to have come from the same two underlying populations that have the same mean."""
|
||||
raise NotImplementedError()
|
||||
|
||||
@unimplemented
|
||||
def VAR(value1, value2):
|
||||
"""Calculates the variance based on a sample."""
|
||||
raise NotImplementedError()
|
||||
|
||||
@unimplemented
|
||||
def VARA(value1, value2):
|
||||
"""Calculates an estimate of variance based on a sample, setting text to the value `0`."""
|
||||
raise NotImplementedError()
|
||||
|
||||
@unimplemented
|
||||
def VARP(value1, value2):
|
||||
"""Calculates the variance based on an entire population."""
|
||||
raise NotImplementedError()
|
||||
|
||||
@unimplemented
|
||||
def VARPA(value1, value2):
|
||||
"""Calculates the variance based on an entire population, setting text to the value `0`."""
|
||||
raise NotImplementedError()
|
||||
|
||||
@unimplemented
|
||||
def WEIBULL(x, shape, scale, cumulative):
|
||||
"""
|
||||
Returns the value of the Weibull distribution function (or Weibull cumulative distribution
|
||||
@@ -610,6 +669,7 @@ def WEIBULL(x, shape, scale, cumulative):
|
||||
"""
|
||||
raise NotImplementedError()
|
||||
|
||||
@unimplemented
|
||||
def ZTEST(data, value, standard_deviation):
|
||||
"""Returns the two-tailed P-value of a Z-test with standard distribution."""
|
||||
raise NotImplementedError()
|
||||
|
||||
@@ -5,6 +5,7 @@ import dateutil.parser
|
||||
import numbers
|
||||
import re
|
||||
|
||||
from unimplemented import unimplemented
|
||||
from usertypes import AltText # pylint: disable=import-error
|
||||
|
||||
def CHAR(table_number):
|
||||
@@ -499,6 +500,7 @@ def T(value):
|
||||
str(value) if isinstance(value, AltText) else "")
|
||||
|
||||
|
||||
@unimplemented
|
||||
def TEXT(number, format_type):
|
||||
"""
|
||||
Converts a number into text according to a specified format. It is not yet implemented in
|
||||
|
||||
11
sandbox/grist/functions/unimplemented.py
Normal file
11
sandbox/grist/functions/unimplemented.py
Normal file
@@ -0,0 +1,11 @@
|
||||
"""
|
||||
Decorator that marks functions as not implemented. It sets func.unimplemented=True.
|
||||
Usage:
|
||||
|
||||
@unimplemented
|
||||
def func(...):
|
||||
raise NotImplemented
|
||||
"""
|
||||
def unimplemented(func):
|
||||
func.unimplemented = True
|
||||
return func
|
||||
Reference in New Issue
Block a user